Search code examples
lambdaschemeprocedure

Define (pointers to) procedures in scheme


I am new to scheme and trying to understand how define works when a procedure is created. More precisely the difference between the following two declarations:

(define name (procedure))
(define (name) (procedure))

Could someone, pls, hint on how define works 'under the hood'? I understand that in the first case define creates a pointer to a procedure. The second is a trimmed version of a procedure without arguments (define (name arg) (procedure)), but how the pointers name and (name) differ from each other?

Clearly, the use of name depends on how it was defined.

> (define proc (+ 1 1))
> proc
2
> (proc)
. . application: not a procedure;


> (define (proc) (+ 1 1))
> proc
#<procedure:proc>
> (proc)
2

Thanks!


Solution

  • Neither of these is a pointer in any way, shape, or form.

    define binds a name to a value in the current environment, and in Scheme, procedures are first-class values.

    (define name (procedure))
    

    defines name to be the value that is the result of calling procedure right now.

    (define (name) (procedure))
    

    defines name to be a procedure that takes no arguments and, when called, returns the result of calling procedure with no arguments.
    The second form is equivalent to

    (define name (lambda () (procedure)))
    

    Example (from Racket - current-seconds is the number of seconds since midnight UTC, January 1, 1970):

    > (current-seconds)
    1462879945
    > (define name (current-seconds))
    > name
    1462879957
    

    name is a number, not a procedure.

    > (define (nameproc) (current-seconds))
    > nameproc
    #<procedure:nameproc>
    

    nameproc is a procedure, not a number.

    > (nameproc)
    1462879980
    > (nameproc)
    1462879983
    

    As you can see, nameproc returns different values each time it's called...

    > name
    1462879957
    > name
    1462879957
    

    ... but name is an integer and doesn't change.