I notice, upon reading Keene's book, that defgeneric has a :method option, which seems like it allows you to specify a method in the generic definition itself. Most documentation I've seen has all of the applicable methods defined in separate defmethods. The hyperspec, with its usual clarity, lists :method as an option for defgeneric, but does not say what it means.
Does the :method option present a default, or at least, document what you expect the most common use case will be, or does it have additional semantics? As a style point, if you expect to define only one method, does it make more sense to define it in the defgeneric form (if you can, indeed, do that), or separately in a defmethod? Or does it not make sense to make a generic function in this case at all, and instead use a regular defun?
The hyperspec, with its usual clarity, lists :method as an option for
defgeneric, but does not say what it means.
Actually, the HyperSpec entry for defgeneric, with its usual clarity, says exactly what it means. It says the syntax for defgeneric is:
defgeneric function-name gf-lambda-list [[option | {method-description}*]]
and then says that the syntax for method-description is:
method-description::= (:method method-qualifier* specialized-lambda-list [[declaration* | documentation]] form*)
And then it describes method-combination:
Each method-description defines a method on the generic function. The
lambda list of each method must be congruent with the lambda list
specified by the gf-lambda-list option. If no method descriptions are
specified and a generic function of the same name does not already
exist, a generic function with no methods is created.
So the :method forms are for defining methods on the generic function, just like defmethod forms.
(I will grant that it doesn't really say anything about why you'd prefer defgeneric plus :method as opposed to defmethod. Remember that the Common in Common Lisp means that the language is an attempt to unify lots of existing Lisp implementations. Maybe some supported :method and others supported defmethod, and this was the easiest way to provide a unified interface.)
That is, the following would have the same effect:
(defgeneric to-list (object))
(defmethod to-list ((object t))
(list object))
(defmethod to-list ((object list))
object)
(defgeneric to-list (object)
(:method ((object t))
(list object))
(:method ((object list))
object))
Sometimes it can be convenient to define some of the methods along with the defgeneric form. It's more a matter of style, and this gets into the other parts of your question.
Does the :method option present a default, or at least, document what
you expect the most common use case will be, or does it have
additional semantics?
It can be a sort of default, if you define a method without type specifiers, or with type specifiers that apply to every object (e.g., t).
As a style point, if you expect to define only one method, does it make more sense to define it in the defgeneric form (if you can,
indeed, do that), or separately in a defmethod? Or does it not make
sense to make a generic function in this case at all, and instead use
a regular defun?
I think it depends on why you expect to define only one method. If it's because you're just defining a default, but expect other users to implement methods on it, then putting the methods along with the defmethod might be convenient if anyone needs to find the source. If you expect that there's only one thing to do, then a normal function might make more sense. I think these decisions just come down to style choices.
It's also worth noting that there are other forms that can define methods on a generic function (and other forms that can produce generic functions, too). In the HyperSpec, using the up arrows to go to higher sections will usually bring you to more prose. In this case, 7.6.1 Introduction to Generic Functions is useful:
Some operators define methods for a generic function. These operators
will be referred to as method-defining operators; their associated
forms are called method-defining forms. The standardized
method-defining operators are listed in the next figure.
defgeneric defmethod defclass
define-condition defstruct
It's up to personal preference and what how the system would be organized in source. Either
simple generic function: a bunch of DEFMETHODS
complex generic function: a DEFGENERIC and a bunch of DEFMETHODS
generic function: a DEFGENERIC and a bunch of methods inside
Most Lisp OO-systems before CLOS used the single method definition form. Code could get too long in one form otherwise, generic functions mostly did not exist, ...
With class-oriented single-dispatch systems it could have made sense to organize methods in a class definition. With the introduction of generic functions and multiple dispatch it made sense to organize them under a generic function definition.
Related
I have seen and heard many times that Julia allows "multiple dispatch", but I am not really sure what that means or looks like. Can anyone provide me an example of what it looks like programmatically and what it enables?
From the Julia docs
The choice of which method to execute when a function is applied is called dispatch. Julia allows the dispatch process to choose which of a function's methods to call based on the number of arguments given, and on the types of all of the function's arguments. This is different than traditional object-oriented languages, where dispatch occurs based only on the first argument, which often has a special argument syntax, and is sometimes implied rather than explicitly written as an argument. 1 Using all of a function's arguments to choose which method should be invoked, rather than just the first, is known as multiple dispatch. Multiple dispatch is particularly useful for mathematical code, where it makes little sense to artificially deem the operations to "belong" to one argument more than any of the others: does the addition operation in x + y belong to x any more than it does to y? The implementation of a mathematical operator generally depends on the types of all of its arguments. Even beyond mathematical operations, however, multiple dispatch ends up being a powerful and convenient paradigm for structuring and organizing programs.
So in short: other languages rely on the first parameter of a method in order to determine which method should be called whereas in Julia, multiple parameters are taken into account. This enables multiple definitions of similar functions that have the same initial parameter.
A simple example of multiple dispatch in Julia can be found here.
Have I understood correctly that in (most? some?) multiple dispatch languages each method gets added to the function at some point in time of program's execution.
Can I then conclude that multiple dispatch as a feature forces functions to be mutable?
Is there a multiple dispatch language, where all methods are attached to a (generic)function together (at load time?), so that it's not possible to see the function in different states at different points in time?
at some point in time of program's execution.
In Common Lisp the methods get added/replaced when the method definitions are executed - for a compiled system this is typically at load-time of the compiled code - not necessarily during the program's execution.
Remember, that Common Lisp has an object system (CLOS, the Common Lisp Object System), which is defined by its behaviour. It's slightly different from a language or a language extension.
Common Lisp allows runtime modification of the object system. For example also adding/removing/replacing methods.
Common Lisp also may combine more than one applicable method into an effective method, which then gets executed. Typical example: all applicable :before methods and the most specific applicable primary method will be combined into one effective method.
There exist extensions for CLOS in some implementations, which seal a generic function against changes.
For a longer treatment of the idea of an object system see: The Structure of a Programming Language Revolution by Richard P. Gabriel.
In Common Lisp, you can read the following from the specification:
7.6.1 Introduction to Generic Functions
When a defgeneric form is evaluated, one of three actions is taken (due to ensure-generic-function):
If a generic function of the given name already exists, the existing generic function object is modified. Methods specified by the current defgeneric form are added, and any methods in the existing generic function that were defined by a previous defgeneric form are removed. Methods added by the current defgeneric form might replace methods defined by defmethod, defclass, define-condition, or defstruct. No other methods in the generic function are affected or replaced.
If the given name names an ordinary function, a macro, or a special operator, an error is signaled.
Otherwise a generic function is created with the methods specified by the method definitions in the defgeneric form.
7.6.2 Introduction to Methods
When a method-defining form is evaluated, a method object is created and one of four actions is taken:
If a generic function of the given name already exists and if a method object already exists that agrees with the new one on parameter specializers and qualifiers, the new method object replaces the old one. For a definition of one method agreeing with another on parameter specializers and qualifiers, see Section 7.6.3 (Agreement on Parameter Specializers and Qualifiers).
If a generic function of the given name already exists and if there is no method object that agrees with the new one on parameter specializers and qualifiers, the existing generic function object is modified to contain the new method object.
If the given name names an ordinary function, a macro, or a special operator, an error is signaled.
Otherwise a generic function is created with the method specified by the method-defining form.
The definition of ensure-generic-function:
If function-name specifies a generic function that has a different value for the :lambda-list argument, and the new value is congruent with the lambda lists of all existing methods or there are no methods, the value is changed; otherwise an error is signaled.
If function-name specifies a generic function that has a different value for the :generic-function-class argument and if the new generic function class is compatible with the old, change-class is called to change the class of the generic function; otherwise an error is signaled.
If function-name specifies a generic function that has a different value for the :method-class argument, the value is changed, but any existing methods are not changed.
You also have add-method and remove-method.
As you can see, generic functions retain their identify between defmethod definitions, and even between defgeneric definitions. Generic functions are mutable in Common Lisp.
In Julia, you can read the following from the documentation:
Defining Methods
To define a function with multiple methods, one simply defines the function multiple times, with different numbers and types of arguments. The first method definition for a function creates the function object, and subsequent method definitions add new methods to the existing function object.
As you can see, functions objects are mutable in Julia.
This says nothing about all other multiple dispatch languages. You can invent a multiple dispatch language right now just for the purpose of showing you can do it with immutability, e.g. adding methods would return a new function similar to the previous function but with the added method. Or a language where functions are generated statically at compile-time, such that you can't change it at runtime in any way, not even to add or remove methods.
Paraphrasing from the excellent "Getting started with Julia" book which has a nice section on this (emphasis mine):
We already saw that functions are inherently defined as generic, that is, they can be used for different types of their arguments. The compiler will generate a separate version of the function each time it is called with arguments of a new type. A concrete version of a function for a specific combination of argument types is called a method in Julia. To define a new method for a function (also called overloading), just use the same function name but a different signature, that is, with different argument types.
A list of all the methods is stored in a virtual method table ( vtable ) on the function itself; methods do not belong to a particular type. When a function is called, Julia will do a lookup in that vtable at runtime to find which concrete method it should call based on the types of all its arguments; this is Julia's mechanism of multiple dispatch, which neither Python, nor C++ or Fortran implements. It allows open extensions where normal object-oriented code would have forced you to change a class or subclass an existing class and thus change your library. Note that only the positional arguments are taken into account for multiple dispatch, and not the keyword arguments.
For each of these different methods, specialized low-level code is generated, targeted to the processor's instruction set. In contrast to object-oriented (OO) languages, vtable is stored in the function, and not in the type (or class). In OO languages, a method is called on a single object, object.method(), which is generally called single dispatch. In Julia, one can say that a function belongs to multiple types, or that a function is specialized or overloaded for different types. Julia's ability to compile code that reads like a high-level dynamic language into machine code that performs like C almost entirely is derived from its ability to do multiple dispatch.
So, the way I understand this (I may be wrong) is that:
The generic function needs to be defined in the session before you can use it
Explicitly defined methods for concrete arguments are added to the function's multiple-dispatch lookup table at the point where they're defined.
Whenever a function is called with specific arguments for which an explicitly defined method does not exist, a concrete version for those arguments is compiled and added to the vtable. (however, this does not show up as an explicit method if you run methods() on that function name)
The first call of such a function will result in some compilation overhead; however, subsequent calls will use the existing compiled version*.
I wouldn't say this makes functions mutable though, that's an altogether different issue. You can confirm yourself they're immutable using the isimmutable() function on a function 'handle'.
*I know modules can be precompiled, but I am not entirely sure if these on-the-fly compiled versions are saved between sessions in any form -- comments welcome :)
Dynamicity can be a real asset in your application, if only for debugging. Trying to prevent a function from being later updated, redefined, etc. might be a little bit short-sighted. But if you are sure you want static dispatch, you can define your own class of generic functions thanks to the MOP, the Meta-Object Protocol, which is not part of the standard but still largely supported. That's what the Inlined-Generic-Function library provides (and this is possible because CLOS is open to extensions).
In Dylan, methods are generally added to a generic function at compile time, but they may also be added at run time (via add-method or remove-method). However, a generic function may be sealed, which prevents libraries other than the one in which the g.f. is defined from adding methods. So to answer your question, in Dylan generic functions are always mutable within the defining library but they may be rendered immutable to other libraries.
I'm trying to simulate something akin to Haskell's typeclasses with Common Lisp's CLOS. That is, I'd like to be able to dispatch a method on an object's "typeclasses" instead of its superclasses.
I have a metaclass defined for classes which have and implement typeclasses(which are just other classes). Those classes(those that implement typeclasses) have a slot containing the list of the typeclasses they implement.
I'd like to be able to define methods for a typeclass, and then be able to dispatch that method on objects whose class implement that typeclass. And I'd like to be able to add and remove typeclasses dynamically.
I figure I could probably do this by changing the method dispatch algorithm, though that doesn't seem too simple.
Anybody is comfortable enough with CLOS and the MOP to give me some suggestions?
Thanks.
Edit: My question might be specified as, how do I implement compute-applicable-methods-using-classes and compute-applicable-methods for a "custom" generic-function class such that if some of the specializers of a generic function method are typeclasses(classes whose metaclass is the 'typeclass' class), then the corresponding argument's class must implement the typeclass(which simply means having the typeclass stored in a slot of the argument's class) for the method to be applicable?
From what I understand from documentation, when a generic function is called, compute-discriminating-functionis first called, which will first attempt to obtain applicable methods through compute-applicable-methods-using-classes, and if unsuccessful, will try the same with compute-applicable-methods.
While my definition of compute-applicable-methods-using-classes seems to work, the generic function fails to dispatch an applicable function. So the problem must be in compute-discriminating-function or compute-effective-method.
See code.
This is not easily achievable in Common Lisp.
In Common Lisp, operations (generic functions) are separate from types (classes), i.e. they're not "owned" by types. Their dispatch is done at runtime, with the possibility of adding, modifying and removing methods at runtime as well.
Usually, errors from missing methods are signaled only at runtime. The compiler has no way to know if a generic function is being "well" used or not.
The idiomatic way in Common Lisp is to use generic functions and describe its requirements, or in other words, the closest to an interface in Common Lisp is a set of generic functions and a marker mixin class. But most usually, only a protocol is specified, and its dependencies on other protocols. See, for instance, the CLIM specification.
As for type classes, it's a key feature that keeps the language not only fully type-safe, but also makes it very extensible in that aspect. Otherwise, either the type system would be too strict, or the lack of expressiveness would lead to type-unsafe situations, at least from the compiler's point of view. Note that Haskell doesn't keep, or doesn't have to keep, object types at runtime, it takes every type inference at compile-time, much in contrast with idiomatic Common Lisp.
To have something similar to type classes in Common Lisp at runtime, you have a few choices
Should you choose to support type classes with its rules, I suggest you use the meta-object protocol:
Define a new generic function meta-class (i.e. one which inherits from standard-generic-function)
Specialize compute-applicable-methods-using-classes to return false as a second value, because classes in Common Lisp are represented solely by their name, they're not "parameterizable" or "constrainable"
Specialize compute-applicable-methods to inspect the argument's meta-classes for types or rules, dispatch accordingly and possibly memoize results
Should you choose to only have parameterizable types (e.g. templates, generics), an existing option is the Lisp Interface Library, where you pass around an object that implements a particular strategy using a protocol. However, I see this mostly as an implementation of the strategy pattern, or an explicit inversion of control, rather than actual parameterizable types.
For actual parameterizable types, you could define abstract unparameterized classes from which you'd intern concrete instances with funny names, e.g. lib1:collection<lib2:object>, where collection is the abstract class defined in the lib1 package, and the lib2:object is actually part of the name as is for a concrete class.
The benefit of this last approach is that you could use these classes and names anywhere in CLOS.
The main disadvantage is that you must still generate concrete classes, so you'd probably have your own defmethod-like macro that would expand into code that uses a find-class-like function which knows how to do this. Thus breaking a significant part of the benefit I just mentioned, or otherwise you should follow the discipline of defining every concrete class in your own library before using them as specializers.
Another disadvantage is that without further non-trivial plumbing, this is too static, not really generic, as it doesn't take into account that e.g. lib1:collection<lib2:subobject> could be a subclass of lib1:collection<lib2:object> or vice-versa. Generically, it doesn't take into account what is known in computer science as covariance and contravariance.
But you could implement it: lib:collection<in out> could represent the abstract class with one contravariant argument and one covariant argument. The hard part would be generating and maintaining the relationships between concrete classes, if at all possible.
In general, a compile-time approach would be more appropriate at the Lisp implementation level. Such Lisp would most probably not be a Common Lisp. One thing you could do is to have a Lisp-like syntax for Haskell. The full meta-circle of it would be to make it totally type-safe at the macro-expansion level, e.g. generating compile-time type errors for macros themselves instead of only for the code they generate.
EDIT: After your question's edit, I must say that compute-applicable-methods-using-classes must return nil as a second value whenever there is a type class specializer in a method. You can call-next-method otherwise.
This is different than there being a type class specializer in an applicable method. Remember that CLOS doesn't know anything about type classes, so by returning something from c-a-m-u-c with a true second value, you're saying it's OK to memoize (cache) given the class alone.
You must really specialize compute-applicable-methods for proper type class dispatching. If there is opportunity for memoization (caching), you must do so yourself here.
I believe you'll need to override compute-applicable-methods and/or compute-applicable-methods-using-classes which compute the list of methods that will be needed to implement a generic function call. You'll then likely need to override compute-effective-method which combines that list and a few other things into a function which can be called at runtime to perform the method call.
I really recommend reading The Art of the Metaobject Protocol (as was already mentioned) which goes into great detail about this. To summarize, however, assume you have a method foo defined on some classes (the classes need not be related in any way). Evaluating the lisp code (foo obj) calls the function returned by compute-effective-method which examines the arguments in order to determine which methods to call, and then calls them. The purpose of compute-effective-method is to eliminate as much of the run-time cost of this as is possible, by compiling the type tests into a case statement or other conditional. The Lisp runtime thus does not have to query for the list of all methods each time you make a method call, but only when you add, remove or change a method implementation. Usually all of that is done once at load time and then saved into your lisp image for even better performance while still allowing you to change these things without stopping the system.
(define hypot
(lambda (a b)
(sqrt (+ (* a a) (* b b)))))
This is a Scheme programming language.
"define" creates a variable and global binding
lambda creates a procedure
I would like to know if "define" would be considered as an imperative language feature! As long as I know imperative feature is static scoping. I think it is an imperative feature since "define" create a global binding and static scoped looks at global binding for any variable definition where as in dynamic it looks at the current most active binding.
Please help me find the correct answer!! And I would like to know why or why not?
In a Scheme program (define var expr) statement is both a declaration and an initialization. Declarations introduce a new name into the scope. Declarations and initialization are present in both imperative and declarative languages.
However if the same variable is defined twice, then define behave as an assignment - which belongs to the imperative paradigm.
You've put your finger on a subtle and contentious issue. There have long been two informal camps on how define should work, which I would label (very imperfectly, and very controversially!) as the static vs. dynamic camps.
The static camp sees define as a non-side-effecting top-level declaration—it's a syntax that simply defines a name in a top-level scope, just like let is a syntax that defines a name in a local scope. A bit more precisely, this camp tends to see the top-level environment as equivalent to a big letrec with all the defines as the bindings, and all "loose" top-level expressions as the body. This is, incidentally, similar to the way that simple compilers work—read the whole program from one or more files, figure out all of the top-level bindings and generate code with knowledge of the whole program's source text.
The dynamic camp, on the other hand, tends to conceive of the top-level environment as a mutable data structure to which bindings can be added at runtime, and define is then an operation that modifies the top-level environment. This is, incidentally, similar to how simple interactive interpreters work—read definitions interactively from input, one at a time, and incorporate them into the environment as the user provides them.
To give one example, the SLIB library is one that I recall has been criticized for being much too firmly in the "dynamic" camp. If you read Section 1.1 on "features", you see this right from the beginning:
SLIB maintains a list of features supported by a Scheme session. The set of features provided by a session may change during that session.
The documentation for the require form that you use in SLIB to "load" modules continues with this:
Procedure: require feature
If (provided? feature) is true, then require just returns.
Otherwise, if feature is found in the catalog, then the corresponding files will be loaded and (provided? feature) will henceforth return #t. That feature is thereafter provided.
Otherwise (feature not found in the catalog), an error is signaled.
If you read this carefully, you will be struck that it's framing the whole thing as modules being "loaded" at runtime—and not as compile-time linking, which is foreign to the design.
So a "session" is a set of bindings whose keys—not just their values—changes during the runtime of the program. Programs are able to mutate the session with provide and require. They are able to directly observe the mutation with provided?. And it is implied that they can indirectly observe the set of identifiers bound in top-level environment change as a result of require—a call to require causes procedure invocations that would result in a runtime error before its invocation to no longer be so afterwards.
So we can't help but conclude that going by the philosophy of the people who designed this library, define is imperative. But not every Scheme user or implementer shares this philosophy.
First off Scheme is lexically scoped. Define usually is not limited to top level bindings like it is in Racket. It can create bindings within other procedure bodies.
In some implementations define can manipulate state but only for top level definitions. Otherwise it acts like let and binds a variable to the local scope. To actually take advantage of the top-level rebinding programatically is difficult.
So define doesn't introduce an imperative style into scheme code. Compare define to set! and its relatives, which by modify the variable in whatever environment it is bound, thereby allowing imperative style in scheme code.
There are many SO posts related to this, but I am asking this again with a different purpose
I am trying to understand why closures are important and useful. One of things that I've read in other SO posts related to this is that when you pass a variable to closure, the closure starts remembering this value from then onwards. Is this the entire Technical aspect of it or there is more to what happens there.
What I wonder then is what would happen when the variable used inside the closure gets modified from outside. Should they be constants only?
In the language Clojure, I can do the following: But since there are value is immutable, this issue does not arise. What about other languages and what is the proper technical definition of a closure?
(defn make-greeter [greeting-prefix]
(fn [username] (str greeting-prefix ", " username)))
((make-greeter "Hello") "World")
This is not the sort of answer that appears to get up-votes around here, but I would heartily urge you to discover the answer to your question by reading Shriram Krishnamurthi's (free!) (online!) textbook, Programming Languages: Application and Interpretation.
I will paraphrase the book very, very briefly, by summarizing the development of the teeny tiny interpreters that it leads you through:
an arithmetic expression language (AE)
an arithmetic expression language with named expressions (WAE);
implementing this involves developing a substitution function that can
replace names with values
a language that adds first-order functions (F1WAE): using a function involves substituting
values for each of the parameter names.
The same language, without substitution: it turns out that "environments" allow you to avoid the overhead of pre-emptive substitution.
a language that eliminates the separation between functions and expressions by allowing
functions to be defined at arbitrary locations (FWAE)
This is the key point: you implement this, and then you discover that with substitution it works fine, but with environments it's broken. In particular, in order to fix it up, you must be sure to associate with an evaluated function definition the environment that was in place when it was evaluated. This pair (fundef + environment-of-definition) is what's called a "closure".
Whew!
Okay, what happens when we add mutable bindings to the picture? If you try this yourself, you'll see that the natural implementation replaces an environment that associates names with values with an environment that associates names with bindings. This is orthogonal to the notion of closures; since closures capture environments, and since environments now map names to bindings, you get the behavior you describe, whereby mutation of a variable captured in an environment is visible and persistent.
Again, I would very much urge you to take a look at PLAI.
A closure is really a data structure used by the compiler to make sure that a function will always have access to the data that it needs to opperate. here is an example of a function that recordes when it was defined.
(defn outer []
(let [foo (get-time-of-day)]
(defn inner []
#(str "then:" foo " now:" (get-time-of-day)))))
(def then-and-now (outer))
(then-and-now) ==> "then:1:02:03 now:2:30:01"
....
(then-and-now) ==> "then:1:02:03 now:2:31:02"
when this function is defined a class is created and a small structure (a closure) is allocated on the heap that stores the value of foo. the class has a pointer to that (or it contains it im not sure). if you run this again then a second closure would be allocated to hold that other foo. When we say "this function closes over foo" we mean to say that it has a reference to a stricture/class/whatever that stores the state of foo at the time it was compiled. The reason you need to close over something is because the function that contains it is going away before the data will be used. In this case outer (which contains the value of foo) is going to end and be gone long before foo is used so nobody will be around to modify foo. of course foo could pas a ref to somebody who could then modify it.
A lexical closure is one in which the enclosed variables (e.g. greeting-prefix in your example) are enclosed by reference. The closure created does not simply get the value of greeting-prefix at the time it is created, but gets a reference. If greeting-prefix is modified after the closure is created, then its new value will be used by the closure every time it is called.
In pure functional languages this isn't much of a distinction, because values are never changed. So it doesn't matter if the value of greeting-prefix is copied into the closure: there's no possible difference in behaviour that could arise from referring to the original versus its copy.
In "imperative-languages-with-closures", such as C# and Java (via anonymous classes), some decision has to be made about whether the enclosed variable is enclosed by value or by reference. In Java this decision is pre-empted by only allowing final variables to be enclosed, effectively mimicking a functional language as far as that variable is concerned. In C# I believe it is a different matter.
Enclosing by value simplifies the implementation: the variable to be enclosed will often exist on the stack and hence will be destroyed when the function constructing the closure returns -- that means it can't be enclosed by reference. If you need enclosure by reference, a workaround is to identify such variables and keep them in an object allocated each time that function is called. This object is then kept as part of the closure's environment and must remain live as long as all closures using it are live. (I do not know if any compiled languages directly use this technique.)
For more descriptions see for example:
Common Lisp HyperSpec, 3.1.4 Closures and Lexical Binding
and
Common Lisp the Language, 2nd Edition, Chapter 3., Scope and Extent
You can think of a closure as an "environment", in which names are bound to values. Those names are entirely private to the closure, which is why we say that it "closes over" its environment. So your question isn't meaningful, in that the "outside" cannot affect the closed-over environment. Yes, a closure can refer to a name in a global environment (in other words, if it uses a name that is not bound in its private, closed-over environment), but that's a different story.
If you like, you can think of an environment as a dictionary, or hash table. A closure gets its own little dictionary where names are looked up.
You might enjoy reading On lambdas, capture, and mutability, which describes how this works in C# and F#, for comparison.
Have a look at this blog post: ADTs in Clojure. It shows a nice application of closures to the problem of locking up data so that it is accessible exclusively through a particular interface (rendering the data type opaque).
The main idea behind this type of locking is more simply illustrated with the counter example, which huaiyuan posted in Common Lisp while I was composing this answer. Actually, the Clojure version is interesting in that it shows that the issue of a closed-over variable changing its value does arise in Clojure if the variable happens to hold an instance of one of the reference types.
(defn create-counter []
(let [counter (atom 0)
inc-counter! #(swap! counter inc)
get-counter (fn [] #counter)]
[inc-counter! get-counter]))
As for the original make-greeter example, you could rewrite it thus (note the deref/#):
(defn make-greeter [greeting-prefix]
(fn [username] (str #greeting-prefix ", " username)))
Then you can use it to render personalised greetings from the different operators of various sections of a website. :-)
((make-greeter "Hello from Gizmos Dept") "John")
((make-greeter "Hello from Gadgets Dept") "Jack").
You can think of a closure as an
"environment", in which names are
bound to values. Those names are
entirely private to the closure, which
is why we say that it "closes over"
its environment. So your question
isn't meaningful, in that the
"outside" cannot affect the
closed-over environment. Yes, a
closure can refer to a name in a
global environment (in other words, if
it uses a name that is not bound in
its private, closed-over environment),
but that's a different story.
I suppose that the question was if things like these are possible in languages which allow mutation of local variables:
CL-USER> (let ((x (list 1 2 3)))
(prog1
(let ((y x))
(lambda () y))
(rplaca x 2)))
#<COMPILED-LEXICAL-CLOSURE #x9FEC77E>
CL-USER> (funcall *)
(2 2 3)
And -- since they are obviously possible -- I think the question is legitimate.