The outer function must return the inner function (or otherwise make it
reachable, perhaps inside some data structure). For example:

> (define (make-counter init)
    (define (counter)
      (set! init (add1 init))
      init)
    (displayln "Making a counter!")
    counter)
> (define count-from-five
    (make-counter 5))
Making a counter!
> (count-from-five)
6
> (count-from-five)
7
> (count-from-five)
8
> (define count-from-two
    (make-counter 2))
Making a counter!
> (count-from-two)
3
> (count-from-five)
9


On Fri, Dec 16, 2016 at 11:15 AM, Jan Hondebrink <jrhondebr...@gmail.com>
wrote:

> Thank you so much. This is extremely helpful and instructive.
>
> One thing I don't understand: how do you call or access an inner function
> after its outer function has completed?
>
> On Fri, Dec 16, 2016 at 5:41 AM, George Neuner <gneun...@comcast.net>
> wrote:
>
>> On Thu, 15 Dec 2016 06:03:54 -0800 (PST), NeverTooOldToCode
>> <jrhondebr...@gmail.com> wrote:
>>
>> >Racket Reference section 1.1.5 states: "Operations that create
>> >objects, such as vector, add to the set of objects" followed
>> >by a nice and instructive step-by-step evaluation example.
>> >Further on, lambda is used as another example of an operation
>> >creating an object.
>> >
>> >How can I tell which operations create objects?
>>
>> It is safe to assume that most operations will create new objects.  If
>> you're just beginning to learn the language, it isn't something you
>> need to worry about yet.
>>
>>
>> Racket is in the Lisp family of languages: most types of data are
>> "boxed".  Boxed data is stored in an object on the heap, together with
>> a "tag" that describes the type of the data.  Variables in your
>> program will contain references (pointers) to boxed values.
>>
>> Racket does not distinguish between the boxed object and the reference
>> to it.  Any time you try to look at the reference, you see the data
>> inside the box instead.  In this way Racket is _not_ like other
>> languages in which pointers and/or references can examined and/or
>> manipulated separately.
>>
>> The above is a bit simplistic: some types like characters and small
>> integers are "immediate" - stored directly in variables (or list
>> nodes, array slots, structure fields, etc.).  But it is safe to assume
>> that *most* types of data will be an object on the heap.
>>
>>
>> When you get to the point of needing to optimize programs for speed,
>> Racket does offer typed vectors and arrays which store numeric values
>> unboxed.  There is also a typed version of Racket which tries to
>> eliminate boxing data as much as is possible.
>>
>>
>>
>> Explaining why lambda creates an object is a bit more complicated.
>>
>> Lisp family languages, including Racket, support the concept of
>> "nested" functions: in other words, they permit functions to be
>> declared inside the scope of other functions.
>> [If you're familar with Algol or Pascal, etc., in general the nested
>> functions in Racket will act very similarly.]
>>
>> Inner functions can access local variables of the outer functions that
>> enclose them.  This type of access is known as "non-global,
>> non-local", usually shortened in the literature to just "non-local".
>> It requires having a way to locate the variables that belong to the
>> enclosing functions.
>>
>> Now, Racket also is in the Scheme language family.  In Scheme,
>> functions are "1st class", which means that they may create and return
>> new functions, be stored in data structures, be passed as arguments to
>> other functions, etc.
>>
>> In particular, Scheme - and Racket - allows the creation of inner
>> functions that persist and can be called *after* their outer functions
>> have completed.
>>
>> Executing a function requires not just its code, but also external
>> data needed by the function: it's so-called "environment".  In many
>> languages, the environment consists only of global data and arguments
>> passed directly to the function - but the environment of an inner
>> function includes local variables of enclosing outer functions.
>>
>> If an inner function is to persist after its enclosing outer function
>> has completed, the local variables of the outer function must *also*
>> persist.
>>
>> To accomplish this, lambda creates an object called a "closure".  The
>> closure contains data defined by the outer function(s) that is needed
>> by the inner function, together with a pointer to the code of the
>> inner function.  The closure, being an object itself, can be
>> referenced by other data structures, passed as an argument, etc.
>>
>> Closures permit functions to have persistent private data.  By sharing
>> closures, multiple functions can share data without the data being
>> defined globally.
>>
>>
>> If this sounds quite like the objects in your favorite OO language ...
>> well, it *is*.  The major difference is that closures are more general
>> than objects in most OO lanuages.   Lambda permits ad hoc associations
>> of data and code, without having to define classes, or clone a
>> "prototype" object, or worry about inheritence hierarchies.
>>
>>
>> Hope this helps,
>> George
>>
>> --
>> You received this message because you are subscribed to a topic in the
>> Google Groups "Racket Users" group.
>> To unsubscribe from this topic, visit https://groups.google.com/d/to
>> pic/racket-users/3oZ0U0_0E94/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to
>> racket-users+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to