(fboundp 'number) ; => nil
(boundp 'number) ; => nil
(defun number ()
42)
(defvar number pi)
number is a symbol defined by CL. It has unbound function and
variable slots. Does the standard allow the use of such symbols in a
way this program does?
I think I read somewhere that this kind of use is not allowed.
Further, if I remember right, the following program should be OK
though.
(setf (get 'number :my-property) 42)
Please advise.
There are some restrictions on what you can do with symbols in the
"COMMON-LISP" package, but you can still do some things. See
"§11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming
Programs" for details [1], but I think of particularly, you'd want to
know that:
"Except where explicitly allowed, the consequences are undefined if any
of the following actions are performed on an external symbol of the
COMMON-LISP package:
1. Binding or altering its value (lexically or dynamically). (Some
exceptions are noted below.)
2. Defining, undefining, or binding it as a function. (Some exceptions
are noted below.)"
and here are the exceptions [2]:
"If an external symbol of the COMMON-LISP package is not globally
defined as a standardized dynamic variable or constant variable, it is
allowed to lexically bind it and to declare the type of that binding,
and it is allowed to locally establish it as a symbol macro (e.g., with
symbol-macrolet)."
So your DEFVAR is OK.
"If an external symbol of the COMMON-LISP package is not defined as a
standardized function, macro, or special operator, it is allowed to
lexically bind it as a function (e.g., with flet), to declare the ftype
of that binding, and (in implementations which provide the ability to do
so) to trace that binding."
So your DEFUN is OK, too. [3]
> Further, if I remember right, the following program should be OK
> though.
>
> (setf (get 'number :my-property) 42)
I don't see anything wrong with this, either.
//JT
[1] http://www.lispworks.com/documentation/HyperSpec/Body/11_abab.htm
[2] http://www.lispworks.com/documentation/HyperSpec/Body/11_ababa.htm
[3] The hyperspec's mention of lexical binding threw up a red flag for
me at the moment: since there are no dynamic bindings of functions, I
wondered if the emphasis on lexical binding should have been local
bindings (e.g., FLET, which the exception mentions, and LABELS). DEFUN
defines things lexically in the global environment too, though, so it
all seems OK to me.
> "If an external symbol of the COMMON-LISP package is not globally
> defined as a standardized dynamic variable or constant variable, it is
> allowed to lexically bind it and to declare the type of that binding,
> and it is allowed to locally establish it as a symbol macro (e.g., with
> symbol-macrolet)."
>
> So your DEFVAR is OK.
>
> "If an external symbol of the COMMON-LISP package is not defined as a
> standardized function, macro, or special operator, it is allowed to
> lexically bind it as a function (e.g., with flet), to declare the ftype
> of that binding, and (in implementations which provide the ability to do
> so) to trace that binding."
>
> So your DEFUN is OK, too. [3]
But it's still not really a good idea to do it. If two applications
both try to use NUMBER as a global variable or function, you can't load
them both into the same Lisp environment, because they'll interfere.
--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
The spec talks about "lexically binding" the symbol as a variable or a
function, I read that as meaning that global bindings are not allowed
- DEFVAR and DEFUN are NOT ok, whereas LET, FLET, SYMBOL-MACROLET,
etc. are.
And in the symbol's plist, it would be better to use 'my-package:my-
property rather than :my-property to avoid clashes.
Alessio
Well I wonder how this is dealt with in practice as it is relatively
easy for a larger software project to bind a standardized symbol (a
symbol from the CL package) accidentally.
One strategy I can think of is to just not use the CL package in your
own packages and use package prefixes.
Indeed, if you need your own "keywords", define a package that doesn't
use CL:
(defpackage "KW" (:use))
(setf (get 'car 'kw::doc) "A small vehicle moved on wheels.")
(symbol-plist 'car) --> (KW::DOC "A small vehicle moved on wheels."
SYSTEM::INSTRUCTION 91
SYSTEM::SETF-EXPANDER SYSTEM::%RPLACA
SYSTEM::DOC (SYSTEM::FILE ((DEFSETF #P"/data/src/languages/clisp/clisp-2.49/build/places.fas" 523 523))))
Look Ma! No collision with system::doc! :-)
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
As was mentioned in one of the responses, it's OK to create LOCAL
bindings of these symbols, only global bindings are prohibited.
If you follow the *...* naming scheme for special variables, you
shouldn't accidentally create any variables that conflict with
standardized symbols, since all the standard *...* symbols have pretty
distinctive names that you're unlikely to reuse in your own applications.
Which are actually prohibited, though? Global bindings or special
(i.e., dynamic) bindings? To clarify, earlier, I'd looked at the
hyperspec and quoted,
"If an external symbol of the COMMON-LISP package is not defined as a
standardized function, macro, or special operator, it is allowed to
lexically bind it as a function (e.g., with flet), to declare the ftype
of that binding, and (in implementations which provide the ability to do
so) to trace that binding."
and understood "lexically binding" to be in contrast to special (i.e.,
dynamic binding). As a result, I'd come to the conclusion that DEFUN
would be OK to use, since it's establishing a *lexical* function binding
in the global environment.
However, Allesio Stalla later replied in the thread,
"The spec talks about "lexically binding" the symbol as a variable or a
function, I read that as meaning that global bindings are not allowed
- DEFVAR and DEFUN are NOT ok, whereas LET, FLET, SYMBOL-MACROLET,
etc. are."
The hyperspec says that "lexical bindings" are allowed, so I'd think
that DEFVAR and other operators that establish a special binding would
be disallowed, but I still think DEFUN would be OK.
//JT
> On 2011.05.07 6:06 PM, Barry Margolin wrote:
>> As was mentioned in one of the responses, it's OK to create LOCAL
>> bindings of these symbols, only global bindings are prohibited.
>
> Which are actually prohibited, though? Global bindings or special
> (i.e., dynamic) bindings? To clarify, earlier, I'd looked at the
> hyperspec and quoted,
>
> "If an external symbol of the COMMON-LISP package is not defined as a
> standardized function, macro, or special operator, it is allowed to
> lexically bind it as a function (e.g., with flet), to declare the ftype
> of that binding, and (in implementations which provide the ability to do
> so) to trace that binding."
>
> and understood "lexically binding" to be in contrast to special (i.e.,
> dynamic binding). As a result, I'd come to the conclusion that DEFUN
> would be OK to use, since it's establishing a *lexical* function binding
> in the global environment.
DEFUN, like DEFVAR and DEFPARAMETER, establishes a *DYNAMIC* function
binding!
(defun f () (g)) ; notice, no error here.
(defun g () '(got special !))
(f)
--> (GOT SPECIAL !)
(eql (function g) (symbol-function 'g))
--> T
Other example:
(defun a () '(first definition of a))
(defun b () (a))
(defun a () '(second definition of a))
(b)
--> (SECOND DEFINITION OF A)
Again, it's the dynamic function binding of A that is taken into account
in B.
There is no way to define a global lexical function, notably because the
function position in applications is not evaluated. (For variables, we
can use define-symbol-macro to define global lexical functions, because
variable deferencements are evaluated as expressions, therefore symbol
macros are expanded).
> However, Allesio Stalla later replied in the thread,
>
> "The spec talks about "lexically binding" the symbol as a variable or a
> function, I read that as meaning that global bindings are not allowed
> - DEFVAR and DEFUN are NOT ok, whereas LET, FLET, SYMBOL-MACROLET,
> etc. are."
>
> The hyperspec says that "lexical bindings" are allowed, so I'd think
> that DEFVAR and other operators that establish a special binding would
> be disallowed, but I still think DEFUN would be OK.
No, DEFUN establishes a dynamic binding.
I think you are missing the words "lexically" and "locally".
IMO, the DEFVAR is _NOT_ okay.
> "If an external symbol of the COMMON-LISP package is not defined as a
> standardized function, macro, or special operator, it is allowed to
> lexically bind it as a function (e.g., with flet), to declare the ftype
> of that binding, and (in implementations which provide the ability to do
> so) to trace that binding."
>
> So your DEFUN is OK, too. [3]
Again, I think you are missing the word "lexically".
IMO, the DEFUN is _NOT_ okay either.
>> Further, if I remember right, the following program should be OK
>> though.
>>
>> (setf (get 'number :my-property) 42)
>
> I don't see anything wrong with this, either.
I am too lazy to check with the spec, but, even if the spec neglects to
ban this, it is still a horrible idea.
--
Sam Steingold (http://sds.podval.org/) on CentOS release 5.6 (Final) X 11.0.60900031
http://palestinefacts.org http://thereligionofpeace.com http://memri.org
http://camera.org http://mideasttruth.com http://dhimmi.com http://ffii.org
There is an exception to every rule, including this one.
DEFUN is specified to establish a function in the global environment,
though, and section 3.1.1.3.1 says that "The null lexical environment
is equivalent to the global environment." This means that DEFUN is
doing something in a lexical environment, doesn't it?
> (defun f () (g)) ; notice, no error here.
> (defun g () '(got special !))
> (f)
> --> (GOT SPECIAL !)
> (eql (function g) (symbol-function 'g))
> --> T
I do agree that the fact that (g) doesn't produce an error in the
first definition of f is important, though. Yet I'd have described it
as a layer of indirection through symbol-function. I.e., (g) is
equivalent to (funcall 'g) is equivalent to (funcall (symbol-function
'g)), so the lookup of g's function-binding is put off until later.
Akin to the way that the following doesn'tr involve any dynamic
bindings:
(let ((f nil) (g nil))
(setf f (lambda () (funcall g))) ; no error here
(setf g (lambda () '(got special !)))
(funcall f) ; would produce (GOT SPECIAL !)
(eql g g) ; would produce T
...)
> Other example:
>
> (defun a () '(first definition of a))
> (defun b () (a))
> (defun a () '(second definition of a))
> (b)
> --> (SECOND DEFINITION OF A)
In a single compilation unit will have the results you specify, but if
compilation happens between, can't the results be different? E.g.,
isn't
> (defun a () 'first-a)
> (defun b () (a))
> (compile 'b)
> (defun a () 'second-a)
> (b)
=> 'first-a
permissible?
Another example that would make what DEFUN does seem more like a
lexical binding than a dynamic one is to consider what happens with
the only local function binding constructs that Common Lisp provides,
viz., FLET and LABELS.
(defun f () 'outer-f)
(defun eff () (f))
(flet ((f () (list 'inner-f (eff))))
(f))
=> (INNER-F OUTER-F)
Now, I grant that this example isn't entirely relevant because no one
has ever made the claim that FLET and LABELS are doing the same kind
of thing that DEFUN is doing. I think it is relevant insofar as there
are ways of lexically shadowing function definitions but no (built in)
ways of dynamically shadowing them.
> There is no way to define a global lexical function, notably because the
> function position in applications is not evaluated.
I'm still not entirely convinced, but I do think that this line of
reasoning might be what persuades me. The relationship between DEFUN
and a symbol's SYMBOL-FUNCTION is very similar to DEF{VAR,PARAMETER}
and a symbol's SYMBOL-VALUE.
//JT
You're right. When I read that "Binding or altering its value
(lexically or dynamically)." was prohibited, I thought the noted
exceptions permitted the dynamic binding, but the exception only
allows lexically and locally binding the symbol. So the DEFVAR is
_NOT_ OK. Thanks for catching that.
> > "If an external symbol of the COMMON-LISP package is not defined as a
> > standardized function, macro, or special operator, it is allowed to
> > lexically bind it as a function (e.g., with flet), to declare the ftype
> > of that binding, and (in implementations which provide the ability to do
> > so) to trace that binding."
>
> > So your DEFUN is OK, too. [3]
>
> Again, I think you are missing the word "lexically".
> IMO, the DEFUN is _NOT_ okay either.
I still have some questions about whether what DEFUN does is better
characterized as lexical binding or dynamic binding, but that's been
continuing in a another strand of this thread.
>
> >> Further, if I remember right, the following program should be OK
> >> though.
>
> >> (setf (get 'number :my-property) 42)
>
> > I don't see anything wrong with this, either.
>
> I am too lazy to check with the spec, but, even if the spec neglects to
> ban this, it is still a horrible idea.
Horrible idea, sure, but not (as far as I understood) forbidden.
However, my spec reading ability has already been shown to be a bit
faulty, so I'm glady stand corrected if someone finds out where it's
forbidden.
//JT
That's rather radical, like wearing condom all the time "just in case".
Many implementation provide package locks -- they will warn you if you
do something wrong.
Yes. Like when your probe is two light hours away. Sure, it's great to
have a REPL, but when your round trip is four hours, it's like having
punch cards and paper print outs.
Well, the point is that my example with defun is different from this
example with lexical variables.
In your case, if you call a function (h 'g f), whatever you do in h, if
it calls the function bound to f, you'll get (got special !).
In my case:
(defun h (inner fun)
(setf (symbol-function inner) (lambda () '(gocha!)))
(funcall fun))
(h 'g (function f))
--> (gocha!)
That's why DEFUN is more like DEFVAR than like LET.
>> Other example:
>>
>> (defun a () '(first definition of a))
>> (defun b () (a))
>> (defun a () '(second definition of a))
>> (b)
>> --> (SECOND DEFINITION OF A)
>
> In a single compilation unit will have the results you specify, but if
> compilation happens between, can't the results be different? E.g.,
> isn't
Yes, this is correct, as an _exception_, in a single compilation unit
the compiler may still inline function calls that are not declared
notinline.
Let me rewrite my example:
(defun a () '(first definition of a))
(declaim (notinline a))
(defun b () (a))
(declaim (notinline b))
(defun a () '(second definition of a))
(b)
--> (SECOND DEFINITION OF A)
so that it works the same, conformingly, in all circumstances.
>> (defun a () 'first-a)
>> (defun b () (a))
>> (compile 'b)
>> (defun a () 'second-a)
>> (b)
> => 'first-a
>
> permissible?
Yes.
> Another example that would make what DEFUN does seem more like a
> lexical binding than a dynamic one is to consider what happens with
> the only local function binding constructs that Common Lisp provides,
> viz., FLET and LABELS.
>
> (defun f () 'outer-f)
> (defun eff () (f))
>
> (flet ((f () (list 'inner-f (eff))))
> (f))
> => (INNER-F OUTER-F)
>
> Now, I grant that this example isn't entirely relevant because no one
> has ever made the claim that FLET and LABELS are doing the same kind
> of thing that DEFUN is doing. I think it is relevant insofar as there
> are ways of lexically shadowing function definitions but no (built in)
> ways of dynamically shadowing them.
Again, let's draw similarities:
(defun f () '(global special function))
(defvar *v* '(global special variable))
(flet ((f () '(local lexical function)))
(let ((*v* '(local special variable))
(v '(local lexical variable)))
(list (list v *v* (symbol-value '*v*))
(list (funcall (function f)) (funcall 'f) (funcall (symbol-function 'f))))))
--> (((LOCAL LEXICAL VARIABLE) (LOCAL SPECIAL VARIABLE) (LOCAL SPECIAL VARIABLE))
((LOCAL LEXICAL FUNCTION) (GLOBAL SPECIAL FUNCTION) (GLOBAL SPECIAL FUNCTION)))
Doesn't it look like defun makes a "special" function binding?
>> There is no way to define a global lexical function, notably because the
>> function position in applications is not evaluated.
>
> I'm still not entirely convinced, but I do think that this line of
> reasoning might be what persuades me. The relationship between DEFUN
> and a symbol's SYMBOL-FUNCTION is very similar to DEF{VAR,PARAMETER}
> and a symbol's SYMBOL-VALUE.
Yes.
Perhaps it would help to learn historic perspective.
Dynamic variables are trivial to implement in an interpreter, so first
Lisp interpreter had only dynamic variables.
Use of dynamic variables has many problems, so later lexical variables
were introduced.
Implementation of lexical variables is a bit harder, (generally) you
need compiler to understand whole piece of code instead of interpreting
form by form.
But lexical variables are a lot cleaner, they help to prevent unwanted
interactions and stuff like that.
So it is simple like this: if it is clean it is lexical, if it is messy
it is dynamic. That's it.
If something in the spec implies that thing might be lexical, but you
see from its behaviour that it is of a 'messy' kind then YOUR
understanding of what spec implies is wrong -- you need to find
interpretation which goes in line with objective reality.
People had good results with this article:
http://www.flownet.com/gat/specials.pdf
I haven't read it for quite a while, though...
> DEFUN is specified to establish a function in the global environment,
> though, and section 3.1.1.3.1 says that "The null lexical environment
> is equivalent to the global environment." This means that DEFUN is
> doing something in a lexical environment, doesn't it?
This is an excellent example why you shouldn't be reading the spec
without understanding concepts first: you'll be taking words out of context.
This chapter describes how lexical environments work -- i.e. what is
visible, what is not etc. So, obviously, when it says that something is
equivalent it means equivalence w.r.t. variable visibility etc.
Note that it does not say "null lexical environment IS the global
environment" (and so "global lexical IS null lexical environment").
What it says is that when there are no lexical bindings (null lexical
environment) what you see is global stuff.
If you're in doubt, check the glossary:
global environment n. that part of an environment that contains bindings
with indefinite scope and indefinite extent.
lexical environment n. that part of the environment that contains
bindings whose names have lexical scope. A lexical environment contains,
among other things: ordinary bindings of variable names to values,
lexically established bindings of function names to functions, macros,
symbol macros, blocks, tags, and local declarations (see declare).
lexical scope n. scope that is limited to a spatial or textual region
within the establishing form. ``The names of parameters to a function
normally are lexically scoped.''
null lexical environment n. the lexical environment which has no bindings.
This rules out your understanding of the passage, doesn't it?
> I do agree that the fact that (g) doesn't produce an error in the
> first definition of f is important, though. Yet I'd have described it
> as a layer of indirection through symbol-function.
> I.e., (g) is
> equivalent to (funcall 'g) is equivalent to (funcall (symbol-function
> 'g)), so the lookup of g's function-binding is put off until later.
> Akin to the way that the following doesn'tr involve any dynamic
> bindings:
This IS how dynamic variables work in Common Lisp -- indirection though
symbol-value.
So you're trying argue that this is lexical binding rather than dynamic
because it is implemented just like dynamic.
> I'm still not entirely convinced, but I do think that this line of
> reasoning might be what persuades me. The relationship between DEFUN
> and a symbol's SYMBOL-FUNCTION is very similar to DEF{VAR,PARAMETER}
> and a symbol's SYMBOL-VALUE.
Oh, so you've noticed that too?
What's wrong with you, guys? (I mean you, TheFlyingDutchman and alike.)
Why do you need to be 'persuaded' by someone who clearly knows subject
way better (I mean Pascal, he knows CL inside out)?
Do you read textbooks same ways -- you need to be persuaded by author?
(The other way is to try to understand what person/text actually meant.)
No, it doesn't. The NULL lexical environment is, well, ... null. It
has no lexical bindings in it, by definition. If defun were to
establish a new lexical binding in the null lexical environment, it
wouldn't be null anymore. Thus, defun cannot be establishing a
lexical binding.
You've been trying to prove your point using the spec; this is a
dangerous thing. You must understand the _entire_ spec before you can
do things like that. What you're missing is the definition (and its
progeny) of "lexical binding": "n. a binding in a lexical
environment." Looking up "lexical environment", then: "n. that part
of the environment that contains bindings whose names have lexical
scope. ..." from which we then look at "lexical scope": ". scope that
is limited to a spatial or textual region within the establishing
form. ..." Clearly, defun does not establish a binding of lexical
scope, because it persists globally. Flets, on the other hand, only
persist within the functions which define them.
> > (defun f () (g)) ; notice, no error here.
> > (defun g () '(got special !))
> > (f)
> > --> (GOT SPECIAL !)
> > (eql (function g) (symbol-function 'g))
> > --> T
>
> I do agree that the fact that (g) doesn't produce an error in the
> first definition of f is important, though. Yet I'd have described it
> as a layer of indirection through symbol-function. I.e., (g) is
> equivalent to (funcall 'g) is equivalent to (funcall (symbol-function
> 'g)), so the lookup of g's function-binding is put off until later.
> Akin to the way that the following doesn'tr involve any dynamic
> bindings:
In all of these experiments below, you've done no similar experiments
with flet, which the spec calls out as an example of a lexical
binding. Try defining a function bar with an flet of f below, and
within bar try comparing (symbol-function 'f) with (function f). The
difference should come screaming out at you.
> (let ((f nil) (g nil))
> (setf f (lambda () (funcall g))) ; no error here
> (setf g (lambda () '(got special !)))
> (funcall f) ; would produce (GOT SPECIAL !)
> (eql g g) ; would produce T
> ...)
>
> > Other example:
>
> > (defun a () '(first definition of a))
> > (defun b () (a))
> > (defun a () '(second definition of a))
> > (b)
> > --> (SECOND DEFINITION OF A)
>
> In a single compilation unit will have the results you specify, but if
> compilation happens between, can't the results be different? E.g.,
> isn't
>
> > (defun a () 'first-a)
> > (defun b () (a))
> > (compile 'b)
> > (defun a () 'second-a)
> > (b)
>
> => 'first-a
>
> permissible?
Of course, permissible, I assume you typed these into a top level,
which is definitely not a compilation unit. If you were to place
these forms into a file, then according to 3.2.2.3:
"A call within a file to a named function that is defined in the same
file refers to that function, unless that function has been declared
notinline. The consequences are unspecified if functions are redefined
individually at run time or multiply defined in the same file."
So if you placed your example into a file and compiled that, it is
explicitly ok for an implementation to compile b to call the first a,
or the second a, or to halt your computer and catch it on fire.
> Another example that would make what DEFUN does seem more like a
> lexical binding than a dynamic one is to consider what happens with
> the only local function binding constructs that Common Lisp provides,
> viz., FLET and LABELS.
>
> (defun f () 'outer-f)
> (defun eff () (f))
>
> (flet ((f () (list 'inner-f (eff))))
> (f))
> => (INNER-F OUTER-F)
>
> Now, I grant that this example isn't entirely relevant because no one
> has ever made the claim that FLET and LABELS are doing the same kind
> of thing that DEFUN is doing.
Nonsense. The paragraph others have been quoting you up to now uses
flet explicitly as an example of lexically binding a symbol as a
function.
I think it is relevant insofar as there
> are ways of lexically shadowing function definitions but no (built in)
> ways of dynamically shadowing them.
Correct.
> > There is no way to define a global lexical function, notably because the
> > function position in applications is not evaluated.
>
> I'm still not entirely convinced, but I do think that this line of
> reasoning might be what persuades me. The relationship between DEFUN
> and a symbol's SYMBOL-FUNCTION is very similar to DEF{VAR,PARAMETER}
> and a symbol's SYMBOL-VALUE.
Whatever gets you to the correct conclusion is fine. The spec was not
written in a vacuum, and there are good reasons why the rules the spec
states and implies are as they are. So if you have to go through the
thought process of reinventing the implementations to figure it out,
by all means, do it. It is evident, however, in the spec.
Duane
> So if you placed your example into a file and compiled that, it is
> explicitly ok for an implementation to compile b to call the first a,
> or the second a, or to halt your computer and catch it on fire.
You are of course referring here to that little known implemenation,
ACL or Arson Common Lisp, which gave a whole new meaning to the phrase
"smoke testing."
;^)
warmest regards,
Ralph
--
Raffael Cavallaro
> You are of course referring here to that little known implemenation,
> ACL or Arson Common Lisp, which gave a whole new meaning to the phrase
> "smoke testing."
Just to be clear, this is not intended as a dig at ACL or Allegro
Common Lisp in any way, for, now that I come to think of it, CCL or
Conflagration Common Lisp behaved similarly.
I guess these implementations never caught on precisely because they
caught on fire.
If memory serves CCL or Conflagration Common Lisp was eventually forked
to create ECL or Extinguisher Common Lisp to resolve these issues...
OK, many thanks to you and various others for all the detailed
responses. I concur, DEFUN is establishing dynamic bindings, and will
pose no more questions about what DEFUN is doing.
I will, however, make one remark, and pose one more related question.
(And I really am doing this for discussion---I'm not trying to be
argumentative or anything.)
** First, the remark, and this involves some mention of Scheme, so it's
getting a bit off topic for c.l.l...
I think part of what had been leading me astray is that top-level
function definitions are just that---top level. I'd been influenced by
Scheme's static scoping and top-level definitions, about which R5RS says,
"To each place where an identifier is bound in a program there
corresponds a region of the program text within which the binding is
visible. The region is determined by the particular binding construct
that establishes the binding; if the binding is established by a lambda
expression; ... Definitions and syntax definitions occurring at the top
level of a program can be interpreted declaratively. They cause
bindings to be created in the top level environment or modify the value
of existing top-level bindings."
I've never heard anyone claim that Scheme is dynamically scoped, but
since something like
(define (foo x) (bar x))
(define (bar x) ...)
is OK in Scheme, I'd been thinking that these sorts of top level
definitions would be lexically scoped. I would no longer say this
though. Scheme isn't lexically scoped, but *statically* scoped. In the
definition of foo, the reference is to the bar defined in the top-level
environment (which happens to be defined later, but that's fine). This
is different model from Common Lisp's where a top-level DEFUN defines a
dynamic binding, wherein the function binding always has to be retrieved
at runtime (caveats about compilation inlining aside).
** Second, the question:
In a hypothetical Common Lisp-like language that supported both lexical
and dynamic bindings for variables, but provided only assignment, i.e.,
no binding operators (e.g., LAMBDA, LET, &c), would there be a way to
distinguish, within <body>, the following:
(let (v1 v2 v3 ...) ; lexical variables
<body>) ; body can assign to v1 v2 v3
; but can't establish new bindings
; for v1 v2 v3 ...
(let (v1 v2 v3 ...) ; dynamic variables
(declare (special v1 v2 v3 ...))
<body>)
I think I'd been viewing what DEFUN was doing as more in line with the
first case than the second (but again, through the course of this
thread, I no longer have this opinion). With top level lexicals (not
that CL has them) and assignment we can simulate dynamically bound
variables (by (unwind-protect (progn (setf x new-value)
(do-stuff-with-x)) (setf x old-value)) patterns). Without binding
operators, trying to go in the other direction doesn't make much sense.
At any rate, would anything in <body> be able to distinguish the
difference?
//JT
> You are of course referring here to that little known implemenation,
> ACL or Arson Common Lisp, which gave a whole new meaning to the phrase
> "smoke testing."
Just to be clear, this is not intended as a dig at ACL or Allegro
Common Lisp in any way, for, now that I come to think of it, CCL or
Conflagration Common Lisp behaved similarly.
I guess these implementations never caught on precisely because they
caught on fire.
If memory serves CCL or Conflagration Common Lisp was eventually forked
to create ECL or Extinguisher Common Lisp to resolve these issues...
;^)
warme
--
Raffael Cavallaro
You know, I don't agree with the fact that DEFUN establishes dynamic
bindings ;) DEFUN establishes *global* bindings, and a global binding
is neither lexical nor dynamic (or is both of them, depending on how
you view things); a global binding is always visible, whereas a
lexical or dynamic binding is visible only somewhere, or sometimes
[*]. So I don't think Scheme and CL differ wrt. their treatment of
global bindings (in general, that is; surely there are subtle
differences about corner cases). This is, imho, orthogonal with the
semantics of function resolution (how and when the function associated
to a given symbol is retrieved).
[*] In fact, the CL spec glossary defines three parts of an
environment:
global environment n. that part of an environment that contains
bindings with indefinite scope and indefinite extent
lexical environment n. that part of the environment that contains
bindings whose names have lexical scope. (...)
dynamic environment n. that part of an environment that contains
bindings with dynamic extent (...)
To be precise, the standard distinguishes between scope (~space) and
extent (~time).
> ** Second, the question:
>
> In a hypothetical Common Lisp-like language that supported both lexical
> and dynamic bindings for variables, but provided only assignment, i.e.,
> no binding operators (e.g., LAMBDA, LET, &c), would there be a way to
> distinguish, within <body>, the following:
>
> (let (v1 v2 v3 ...) ; lexical variables
> <body>) ; body can assign to v1 v2 v3
> ; but can't establish new bindings
> ; for v1 v2 v3 ...
>
> (let (v1 v2 v3 ...) ; dynamic variables
> (declare (special v1 v2 v3 ...))
> <body>)
>
> I think I'd been viewing what DEFUN was doing as more in line with the
> first case than the second (but again, through the course of this
> thread, I no longer have this opinion). With top level lexicals (not
> that CL has them) and assignment we can simulate dynamically bound
> variables (by (unwind-protect (progn (setf x new-value)
> (do-stuff-with-x)) (setf x old-value)) patterns). Without binding
> operators, trying to go in the other direction doesn't make much sense.
> At any rate, would anything in <body> be able to distinguish the
> difference?
It's not clear what you mean: you say there's no binding operator but
then your very example uses let. If there weren't really any binding
construct, then there would be no scope, everything would be global -
unless by "assignment" you mean "binding (if necessary) + assignment",
but you didn't specify the semantics for that. Note that lambda *is* a
binding operator: (let ((a b) (c d)) (f a c)) is semantically
equivalent to ((lambda (a c) (f a c)) b d). So a language with no way
of binding variables would be very poor.
Alessio
Yes, I wasn't very clear. And such a language would be pretty
disappointing. And yes, of course LAMBDA is a binding operator, that's
why it got disallowed along with LET. What I meant was, could you write
a <body> without using any binding constructs (LET, LAMBDA, &c) that
could behave differently in the two cases? I think the answer is no,
but I'd love to see some clever trick that I haven't thought of.
This is relevant to your comment above, that "DEFUN establishes *global*
bindings, and a global binding is neither lexical nor dynamic (or is
both of them, depending on how you view things)[.]" Since there's no
built-in construct for introducing function bindings with dynamic extent
(though it is easy enough to make one that assigns a symbol's
SYMBOL-FUNCTION, executes some code, and restores the old function), and
since FLET and LABELS don't make the global functions definitions
unavailable (they're accessible with SYMBOL-FUNCTION), the only thing,
it seems to me, that can be done with global function definitions is
essentially assignment, and in that case, they seem to be "neither
lexical nor dynamic (or ... both of them, depending on how you view
things)[.]"
At the risk of sounding like I don't know what I'm talking about again,
a dynamically-bound name just doesn't feel as dynamically-bound when
there are no [built-in] operators to rebind it with dynamic extent, and
a lexically bound name wouldn't feel as lexically-bound if there were no
operators to rebind it with lexical scope.
//JT
But doesn't everybody know about the HCF instruction?
Duane
(defun side-effect (x)
(declare (special v1))
(setq v1 x))
<body> =
(setq v1 10)
(print v1)
(side-effect 20)
(print v1)
This will detect the difference between lexical and dynamic variables.
So will
<body> =
(setq v1 10)
(setq v2 v1)
(side-effect 20)
(= v1 v2)
--
Thomas A. Russ, USC/Information Sciences Institute
Yes, that's the sort of thing that you can do when binding operators
like LAMBDA (indirectly through DEFUN) [1] *are* available. But it's
not within the (admittedly terribly phrased, but see my latest reply to
Alessio Stalla) constraint of using "only assignment, i.e., no binding
operators (e.g., LAMBDA, LET, &c), would there be a way to distinguish,
within <body>".
//JT
[1] http://www.lispworks.com/documentation/HyperSpec/Body/m_defun.htm
"Evaluating defun causes function-name to be a global name for the
function specified by the lambda expression
(lambda lambda-list
[[declaration* | documentation]]
(block block-name form*))"
> At the risk of sounding like I don't know what I'm talking about again,
> a dynamically-bound name just doesn't feel as dynamically-bound when
> there are no [built-in] operators to rebind it with dynamic extent, and
> a lexically bound name wouldn't feel as lexically-bound if there were no
> operators to rebind it with lexical scope.
Which is why emacs lisp (and older lisps) mostly worked.
But since lambda is an essential feature of lisp, of course the dynamic
binding bug was discovered early.
> But doesn't everybody know about the HCF instruction?
Of course, but the only modern lisp compiler to emit that instruction
is SBCL or Smoking Burning Common Lisp which is of course a descendant
of CMMUCL or Crispy Memory Management Unit Common Lisp.
;^)
--
Raffael Cavallaro
> But doesn't everybody know about the HCF instruction?
Of course, but the only modern lisp compiler to emit that instruction
And, on early large DEC machines, a related data file
named "FIRE". If you told it to "PRINT FIRE"... it did.[1]
-Rob
[1] Spoiler...
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
As the story goes, back in the 1970s there was an occasional
manufacturing bug on an early DEC line printer [you know,
*line printers*? -- those things as big as commercial stoves, that
printed on 132-column-wide fanfold paper?] such that the output
take-up basket and the guides leading to it weren't properly
grounded. If you prepared a file [let's call it "FIRE", eh?]
consisting of *only* a sequence of <formfeed><space><cr><lf>,
over & over again, and then said "PRINT FIRE", the printer would
stream a whole box of paper from the feed box to the output.
[The single blank line per page defeated the "runaway detection"
that was normally supposed to prevent that sort of nonsense.]
Now since the output guides/basket weren't properly grounded,
with the paper running away like that, supposedly it made the
printer act a bit like a Van de Graaff generator, and enough
static could build up on the output guides/basket that it could
spark through the paper onto the main (and grounded) frame of
the printer and even -- so the story goes -- in the worst case
actually cause the paper [or, more probably, the mounds of paper
dust that tending to accumulate in & around such beasts that the
operators never kept tidied up] to start burning. Hence, "PRINT FIRE".
-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <http://rpw3.org/>
San Mateo, CA 94403
Except that it doesn't depend on the lambda binding of defun.
Perhaps you would prefer:
(defun side-effect ()
(setq v1 20))
which doesn't have any lambda variables and therefore doesn't have any
bindings. You would then use:
<body> =
(setq v1 10)
(setq v2 v1)
(side-effect)
(= v1 v2)
BTW, if you don't allow for any sort of function definitions, then it is
pretty hard to write much in the way of any sort of program. You would
have to write the entire program as a series of statements with no
function calls, other than what was built-in.
Again, the original "specification" was pretty terrible, but the idea
was to only replace <body>. We don't get observably different behavior in:
(let (v1 v2 v3 ...) ; lexical variables
(defun side-effect ()
(setq v1 20))
(setq v1 10)
(setq v2 v1)
(side-effect)
(= v1 v2))
(let (v1 v2 v3 ...) ; dynamic variables
(declare (special v1 v2 v3 ...))
(defun side-effect ()
(setq v1 20))
(setq v1 10)
(setq v2 v1)
(side-effect)
(= v1 v2))
> BTW, if you don't allow for any sort of function definitions, then it is
> pretty hard to write much in the way of any sort of program. You would
> have to write the entire program as a series of statements with no
> function calls, other than what was built-in.
Certainly. The point of the "exercise" wasn't to propose any sort of
programming language, but rather to either confirm or else find a
counterexample to, roughly, the proposition that "code written and
executed in the lexical or dynamic scope of a binding for variable v
that does not lexically or dynamically rebind v either directly or
through other code defined within the lexical or dynamic scope of the
binding of v cannot determine whether v is bound lexically or
dynamically." I think that this proposition is true. If it is not, I
think that a counterexample could take the form of a block of code that
could be substituted for <body> such that the two (let (v1 v2 v2 ...)
... <body>) forms produce different results. I apologize if the intent
has been unclear---I know that the "specification" of the "exercise"
certainly was.
//JT
Well, it seems that you have constrained the problem to be one where the
only references to variables that are allowed are those that are within
the lexical scope of the binding form.
So if you restrict yourself to lexical references only, then you will
not be able to see any effects of dynamic binding, because you have
defined away any capability to see a dynamic effect.
But it seems that this proposition is essentially meaningless, since it
says that if you only allow lexical references then you can't detect
dynamic access. But that seems somehow definitional and thus rather
uninteresting.
Precisely! But if we're limited to writing code within that lexical
scope, all of those variables *appear* to us as having indefinite (i.e.,
unlimited) scope. And this is true whether the variables are bound
lexically or dynamically (but we are still talking about how the
variables appear within the *lexical* scope).
> So if you restrict yourself to lexical references only, then you will
> not be able to see any effects of dynamic binding, because you have
> defined away any capability to see a dynamic effect.
Precisely! And I think the counterpart for variables with indefinite
scope (whether lexical or dynamic), if there is no available way of
re-binding them (lexically or dynamically), we cannot see the effects of
dynamic versus lexical binding.
If we had operators DEFDYNAMIC and DEFLEXICAL [1] (in CL, of course, the
former can be DEFVAR or DEFPARAMETER, and the latter can be implemented
using symbol-macros) that introduced bindings in the global environment
(if the global environment had lexical bindings), then the parallel is
that if we write code that can't rebind names, we can't tell which of
(DEFDYNAMIC v1 nil)
(DEFDYNAMIC v2 nil)
(DEFDYNAMIC v3 nil)
...
and
(DEFLEXICAL v1 nil)
(DEFLEXICAL v2 nil)
(DEFLEXICAL v3 nil)
...
preceded our code.
> But it seems that this proposition is essentially meaningless, since it
> says that if you only allow lexical references then you can't detect
> dynamic access. But that seems somehow definitional and thus rather
> uninteresting.
Fortunately, in one sense I wasn't trying to say anything interesting.
;) I was just trying to confirm that although the bindings that DEFUN
establishes in the global environment, since there is no way rebind
these names dynamically [2], there's nothing that user code can do
actually distinguish whether the bindings are dynamic or lexical.
//JT
[1] Given the other discussion in this thread, DEFLEXICAL is really a
misnomer, since the variable being defined can't actually be a global
lexical since there's no globally-enclosing form. It seems like
DEFLEXICAL should be called DEFSTATIC (cf. Scheme's *static*, not
*lexical* scoping).
[2] FLET and LABELS rebind the name lexically, and here we get into an
interesting aspect of how function forms are are evaluated: if the car
of the form is a symbol, then "the functional value of the operator is
retrieved from the lexical environment" (and we must remember that
"within a given namespace, a name is said to be bound in a lexical
environment if there is a binding associated with its name in the
lexical environment or, if not, there is a binding associated with its
name in the global environment." [3])
[3] So, while the point is often made that the pervasive SPECIALness
that results from DEFVAR, DEFPARAMETER, etc, can be frustrating, since
there is no (declare (lexical ...)), and so for variables there's no way
to lexically shadow a special bindings, with functions we *can*
lexically shadow a dynamic binding.