Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's a common way to implement OO in Lisp-y languages, and it fits if you're taking Smalltalk as an inspiration. SICP has an example in chapter 3 (IIRC) of doing the same, but the selector had to be quoted as in:

  (my-account 'balance)
  (my-account 'withdraw 10)


Uses an internal lambda for dispatching on messages.

We can also create objects that handle deposits as well as withdrawals, and thus we can represent simple bank accounts. Here is a procedure that returns a “bank-account object” with a specified initial balance:

  (define (make-account balance)
    (define (withdraw amount)
      (if (>= balance amount)
          (begin (set! balance 
                       (- balance amount))
                 balance)
          "Insufficient funds"))
    (define (deposit amount)
      (set! balance (+ balance amount))
      balance)
    (define (dispatch m)
      (cond ((eq? m 'withdraw) withdraw)
            ((eq? m 'deposit) deposit)
            (else (error "Unknown request: 
                   MAKE-ACCOUNT" m))))
    dispatch)
Each call to make-account sets up an environment with a local state variable balance. Within this environment, make-account defines procedures deposit and withdraw that access balance and an additional procedure dispatch that takes a “message” as input and returns one of the two local procedures. The dispatch procedure itself is returned as the value that represents the bank-account object. This is precisely the message-passing style of programming that we saw in 2.4.3, although here we are using it in conjunction with the ability to modify local variables.

3.1.1 Local State Variables

https://sarabander.github.io/sicp/html/3_002e1.xhtml#g_t3_00...


A closure, specifically, because closures are a poor man's object.

https://wiki.c2.com/?ClosuresAndObjectsAreEquivalent


You fool! Objects are a poor man’s closures!


:-D

Closures indeed! A key concept of Scheme that distinguished it from most Lisps at the time:

(LAMBDA ( <identifier list> ) <body> )

Lambda-expressions evaluate to procedures. Unlike most LISP systems, SCHEME does not consider a lambda-expression (an s-expression whose car is the atom LAMBDA) to be a procedure. A lambda-expression only evaluates to a procedure. A lambda-expression should be thought of as a partial description of a procedure; a procedure and a description of it are conceptually distinct objects. A lambda-expression must be “closed” (associated with an environment) to produce a procedure object. Evaluation of a lambda-expression performs such a closure operation.

The resulting procedure takes as many arguments as there are identifiers in the identifier list of the lambda-expression. When the procedure is eventually invoked, the intuitive effect is that the evaluation of the procedure call is equivalent to the evaluation of the <body> in an environment consisting of (a) the environment in which the lambda-expression had been evaluated to produce the procedure, plus (b) the pairing of the identifiers of the <identifier list> with the arguments supplied to the procedure. The pairings (b) take precedence over the environment (a), and to prevent confusion no identifier may appear twice in the <identifier list>. The net effect is to implement ALGOL-style lexical scoping [Naur], and to “solve the funarg problem” [Moses].

THE REVISED REPORT ON SCHEME: A DIALECT OF LISP

B.1. Kernel Magic Forms

https://research.scheme.org/lambda-papers/lambda-papers-revi...

Moar:

3.2 The Environment Model of Evaluation

https://sarabander.github.io/sicp/html/3_002e2.xhtml#g_t3_00...


Yup!

Here's a video demo of the code completion in vscode:

https://www.youtube.com/watch?v=YuIjug7elPY




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: