Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

(SETF (FUNCTION FOO) (FUNCTION BAR)) ?

29 views
Skip to first unread message

Rainer Joswig

unread,
Nov 22, 2000, 2:43:21 AM11/22/00
to
Question: can I set a local function binding
in Common Lisp?

Local variable bindings can be changed via
SETF/SETQ like in the following example:

(let ((foo 2))
(print foo)
(setf foo 3)
(print foo))


Wouldn't it seem logical to be able to
change local functions, too? Like
in the following - not working - example:

(flet ((foo (x) (+ x 2)))
(print (foo 3))
(setf (function foo) #'1+)
(print (foo 3)))


Is there a reason why this is not in Common Lisp?
Or is there any other way? Setting FDEFINITION
or SYMBOL-FUNCTION only works for global
functions - but not for local functions.


Rainer Joswig

--
Rainer Joswig, Hamburg, Germany
Email: mailto:jos...@corporate-world.lisp.de
Web: http://corporate-world.lisp.de/

Barry Margolin

unread,
Nov 22, 2000, 3:00:00 AM11/22/00
to
In article <joswig-7D90C2....@news.is-europe.net>,

Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
>Question: can I set a local function binding
>in Common Lisp?

No.

>Wouldn't it seem logical to be able to
>change local functions, too? Like

I guess so.

>Is there a reason why this is not in Common Lisp?

No one thought of it way back when, I guess.

>Or is there any other way? Setting FDEFINITION
>or SYMBOL-FUNCTION only works for global
>functions - but not for local functions.

Why do you need to do this? Redefining global functions is relatively
uncommon (most commonly only during development or when patching a running
system), I can hardly think of a good reason to redefine local functions.
You could always have the local function check the value of a variable and
dispatch on that to different behaviors.

--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Rob Warnock

unread,
Nov 22, 2000, 8:30:37 PM11/22/00
to
Barry Margolin <bar...@genuity.net> wrote:
+---------------

| Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
| >Question: can I set a local function binding in Common Lisp?
|
| No.
+---------------

Hunh? What's FLET all about then?

> #'car
#<SYSTEM-FUNCTION CAR>
> (car '(a . b))
A
> (flet ((car (n) (+ 1 n)))
(values #'car (car 17)))
#<CLOSURE CAR (N) (+ 1 N)> ;
18
>

And don't tell me I didn't shadow the right one, either:

> (symbol-package 'car)
#<PACKAGE LISP>
> (flet ((lisp:car (n) (+ 1 n)))
(lisp:car 17))
18
>


-Rob

-----
Rob Warnock, 31-2-510 rp...@sgi.com
Network Engineering http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
1600 Amphitheatre Pkwy. PP-ASEL-IA
Mountain View, CA 94043

Kent M Pitman

unread,
Nov 22, 2000, 11:05:27 PM11/22/00
to
Barry Margolin <bar...@genuity.net> writes:

> >Question: can I set a local function binding
> >in Common Lisp?
>

> No.


>
> >Wouldn't it seem logical to be able to
> >change local functions, too? Like
>

> I guess so.


>
> >Is there a reason why this is not in Common Lisp?
>

> No one thought of it way back when, I guess.

I'm pretty sure it was discussed. I think some people thought it was
a bad idea. Maybe it was just because the whole lexical scoping thing
was new and they were leary on general principles, or maybe it was something
else.

I have generally alleged that people treat "function definitions" in CL
as "constants" and that they treat "variables" as mutable. Certainly
well-written macros tend to assume this stylistically. I would never
encourage someone to have a macro that assumed a reference to the function
namespace was going to vary (e.g., worried that CAR might be FLET'd).
A consequence of this, I claim, is that proper style if you want to set
the thing is to put it in a variable to cue the human reader that it might,
well, vary. I don't think this aspect of CL is intentionally designed in,
at least that we ever discussed it, but I do think it's pretty much the de
facto way of doing things.

> >Or is there any other way? Setting FDEFINITION
> >or SYMBOL-FUNCTION only works for global
> >functions - but not for local functions.
>

> Why do you need to do this? Redefining global functions is relatively
> uncommon (most commonly only during development or when patching a running
> system), I can hardly think of a good reason to redefine local functions.
> You could always have the local function check the value of a variable and
> dispatch on that to different behaviors.


Rewrite
(FLET ((FOO () ...))
... (FOO) ...
(SETF #'FOO ...)
... (FOO) ...)
as
(LET ((FOO #'(LAMBDA () ...)))
... (FUNCALL FOO) ...
(SETQ FOO ...)
... (FUNCALL FOO) ...)

Erik Naggum

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to
* rp...@rigden.engr.sgi.com (Rob Warnock)

| Hunh? What's FLET all about then?

I think the proper question is "What's Scheme all about then?".

With distinct function and variable namespaces, you don't need to
create the kind of hellish environment where you never know what a
function does that Scheme has invented for itself.

Please note that you were not allowed to do what you just did if you
also want to have a conforming ANSI Common Lisp program.

#:Erik
--
Solution to U.S. Presidential Election Crisis 2000:
Let Texas secede from the Union and elect George W. Bush their
very first President. All parties, states would rejoice.

Rainer Joswig

unread,
Nov 23, 2000, 3:00:00 AM11/23/00
to
In article <sfwitpf...@world.std.com>, Kent M Pitman
<pit...@world.std.com> wrote:

> I have generally alleged that people treat "function definitions" in CL
> as "constants" and that they treat "variables" as mutable.

Well (SETF SYMBOL-FUNCTION), DEFUN, COMPILE, etc. all can
**change** function definitions. But only global.

> > Why do you need to do this? Redefining global functions is relatively
> > uncommon (most commonly only during development or when patching a running
> > system), I can hardly think of a good reason to redefine local functions.
> > You could always have the local function check the value of a variable and
> > dispatch on that to different behaviors.
>
>
> Rewrite
> (FLET ((FOO () ...))
> ... (FOO) ...
> (SETF #'FOO ...)
> ... (FOO) ...)
> as
> (LET ((FOO #'(LAMBDA () ...)))
> ... (FUNCALL FOO) ...
> (SETQ FOO ...)
> ... (FUNCALL FOO) ...)


Let's look at an example (very simplified):


(defun accumulate (fn list)
(let ((result 0))
(dolist (item list)
(setf result (FUNCALL fn result item)))
result))

(accumulate #'+ '(1 2 3))

** Now I want to write the code without using FUNCALL. **

Just assume that I want that.

I want to be able to pass in a function
as a parameter (in value space) and
then be able to call the function in function
space:

(defun accumulate (fn list)
(flet ((fn (&rest args)
(apply fn args)))
(let ((result 0))
(dolist (item list)
(setf result (fn result item)))
result)))

I find the introduction of a different function
FN ugly. Its purpose is just to be able
to get rid of FUNCALL later in the code
(which maybe my application code, or
user code). To pass in a function fn into another
function, the function fn has to leave the
function namespace, it will be passed as a
parameter - how do I get the function back
into the function namespace (in this case
as a local function)?

Alternative (not possible in CL):

(defun accumulate (fn1 list)
(flet (fn)
(setf (function fn) fn1)
(let ((result 0))
(dolist (item list)
(setf result (fn result item)))
result)))

Or:

(defun accumulate (fn list)
(flet1 ((fn (function fn)))
(let ((result 0))
(dolist (item list)
(setf result (fn result item)))
result)))

Often when programming, I'm using extensive macrology
to provide a domain language for the application.
The domain language then is being used to code
the domain specific information (it's kind
of a configuration). So it's not untypical
to have a tool to consist of 2/3 code and
1/3 configuration data, which then generates
the necessary functionality. What I want Common Lisp
to be, is a language to implement the domain
language and to provide the implementor of
the domain specific code (maybe me, maybe somebody else)
a comfortable and concise environment.
Think for example of an report generator as the application
and the report specifications as the domain specific
data.

Erik Naggum

unread,
Nov 24, 2000, 2:41:33 PM11/24/00
to
* Rainer Joswig <jos...@corporate-world.lisp.de>

| ** Now I want to write the code without using FUNCALL. **
|
| Just assume that I want that.

I think you need a more modern Lisp, because this is just like someone
complaining wildly about Common Lisp having upper-case symbol names
and walking off huffing and puffing to make his own Common Lisp look-
alike with lower-case symbol names.

| What I want Common Lisp to be, is a language to implement the domain
| language and to provide the implementor of the domain specific code
| (maybe me, maybe somebody else) a comfortable and concise environment.

And you can't do this if you have to use funcall?

May I suggest you wrap some macrology around your function definitions
that define both a lexical variable and lexical macro that expands to
a funcall of the variable for functional arguments if you want to be
able to write "normal"-looking code? This should not be intractably
hard and it would be a fairly intelligent contribution to a corpus of
"domain language" techniques.

Rainer Joswig

unread,
Nov 24, 2000, 3:49:39 PM11/24/00
to
In article <31840836...@naggum.net>, Erik Naggum <er...@naggum.net>
wrote:

> * Rainer Joswig <jos...@corporate-world.lisp.de>
> | ** Now I want to write the code without using FUNCALL. **
> |
> | Just assume that I want that.
>
> I think you need a more modern Lisp, because this is just like someone
> complaining wildly about Common Lisp having upper-case symbol names
> and walking off huffing and puffing to make his own Common Lisp look-
> alike with lower-case symbol names.

An extension in this direction is just an *extension*.
The correctness of existing code is not affected.
Even then discussions of extensions and changes is
not forbidden and helps to understand the current
capabilities and limitations of Common Lisp. Just browse
the Hyperspec for "Issue FUNCTION-TYPE Writeup".

> | What I want Common Lisp to be, is a language to implement the domain
> | language and to provide the implementor of the domain specific code
> | (maybe me, maybe somebody else) a comfortable and concise environment.
>
> And you can't do this if you have to use funcall?

I can do that with FUNCALL. But I find avoiding FUNCALL
and being able to use the "usual" function calling syntax
preferrable.

> May I suggest you wrap some macrology around your function definitions
> that define both a lexical variable and lexical macro that expands to
> a funcall of the variable for functional arguments if you want to be
> able to write "normal"-looking code?

Yes, this is what I'd normally would do. The drawback
is:

a) extra effort ("maintenance costs")
b) passing the functions via (FUNCTION FOO) to other
functions does not work

Kent M Pitman

unread,
Nov 24, 2000, 4:55:12 PM11/24/00
to
Rainer Joswig <jos...@corporate-world.lisp.de> writes:

> I can do that with FUNCALL. But I find avoiding FUNCALL
> and being able to use the "usual" function calling syntax
> preferrable.

I don't see it as a goal of the language to support linguistic styles which
are not goals of the language. That is, CL is not a Lisp1, and attempts to
pretend otherwise without a translation phase are doomed to lead you into a
problem. I see this as no different than trying to program in a
side-effect-free style, which one can certainly do, but which will surprise
one if they ever accidentally call a function that isn't playing along.
You can also try to pretend that Lisp is free of alphabetic characters so
that you never get into the case debate, but even doing
(DEFUN +^%$ (X) (GENSYM X))
and forever after only doing (+^%$) won't guarantee you that (+^%$) won't
return a symbol with alphabetic characters in it, nor can you be sure that
(setf (@@$% $%) @@%) won't macroexpand into something containing symbols
whose names have both-case-p characters. Hiding your head in the sand
works only so well, and beyond that definite limit, you are exposed to the
fact that the extant rules MEAN something and that, like the US elections
of late, they are there for the purpose of getting you through the edge
effects. The meaning of saying Common Lisp is a Lisp2 is that when push
comes to shove, FUNCALL is going to sometimes be needed and arguments are
really going to be in a different namespace.

For example, you can almost[*] get away with the following:

(DEFMACRO WITH-FARGS ((&REST FARGS) &BODY FORMS)
(LET ((TEMP (GENSYM "ARGS")))
`(LABELS ,(MAPCAR #'(LAMBDA (FARG)
`(,FARG (&REST ,TEMP)
(DECLARE (DYNAMIC-EXTENT ,TEMP))
(APPLY ,FARG ,TEMP)))
FARGS)
,@FORMS)))

(DEFUN FOO (FN X)
(WITH-FARGS (FN)
(PRINT (IF (FN X) 'YES 'NO))
(SETQ FN (COMPLEMENT FN))
(PRINT (IF (FN X) 'YES 'NO))
'DONE))

(FOO #'ODDP 7)
YES
NO
=> DONE

(FOO #'ODDP 8)
NO
YES
=> DONE

[*]Extra Credit:

There is an interesting "screw case" to this WITH-FARGS I made, though,
which I think exactly exposes why you should not be trying to hide
"Lisp2"-ness inside a macro like this. That is, any caller of this macro
really must understand the implementation of this in a way that ultimately
does not hide what the macro appears to try to hide. Anyone notice what
it is?


Rainer Joswig

unread,
Nov 24, 2000, 5:32:41 PM11/24/00
to
In article <sfw1yw1...@world.std.com>, Kent M Pitman
<pit...@world.std.com> wrote:

> Rainer Joswig <jos...@corporate-world.lisp.de> writes:
>
> > I can do that with FUNCALL. But I find avoiding FUNCALL
> > and being able to use the "usual" function calling syntax
> > preferrable.
>
> I don't see it as a goal of the language to support linguistic styles which
> are not goals of the language. That is, CL is not a Lisp1, and attempts to
> pretend otherwise without a translation phase are doomed to lead you into a
> problem.

Actually I see it completely in harmony with being a Lisp2 to
be able change a local function (other than creating a new
binding).

> For example, you can almost[*] get away with the following:
>
> (DEFMACRO WITH-FARGS ((&REST FARGS) &BODY FORMS)
> (LET ((TEMP (GENSYM "ARGS")))
> `(LABELS ,(MAPCAR #'(LAMBDA (FARG)
> `(,FARG (&REST ,TEMP)
> (DECLARE (DYNAMIC-EXTENT ,TEMP))
> (APPLY ,FARG ,TEMP)))
> FARGS)
> ,@FORMS)))
>
> (DEFUN FOO (FN X)
> (WITH-FARGS (FN)
> (PRINT (IF (FN X) 'YES 'NO))
> (SETQ FN (COMPLEMENT FN))
> (PRINT (IF (FN X) 'YES 'NO))
> 'DONE))

I would more like something like that:

(DEFUN FOO (FN X)
(WITH-FARGS (FN)
(PRINT (IF (FN X) 'YES 'NO))

(FSETQ FN (COMPLEMENT FN))


(PRINT (IF (FN X) 'YES 'NO))
'DONE))

or

(DEFUN FOO (FN X)
(WITH-FARGS (FN)
(PRINT (IF (FN X) 'YES 'NO))

(SETF (FUNCTION FN) (COMPLEMENT FN))


(PRINT (IF (FN X) 'YES 'NO))
'DONE))

I would not like to SETQ a local variable and then magically
being able to call it as a function. This confuses the
programmer. I respect the Lisp2 form of function calling.

How is this related to the FUNCTION-NAME:LARGE proposal:
http://www.xanalys.com/software_tools/reference/HyperSpec/Issues/iss174-writeup.html
(for example part 9)?

Kent M Pitman

unread,
Nov 25, 2000, 3:00:00 AM11/25/00
to
Rainer Joswig <jos...@corporate-world.lisp.de> writes:

> Actually I see it completely in harmony with being a Lisp2 to
> be able change a local function (other than creating a new
> binding).

Yes, I agree with that part. As I said, this was discussed and was ruled out
for reasons I don't understand. I think the more I think about it that people
didn't really understand the lexical thing well enough and weren't familiar
with what (function foo) meant as distinct from (symbol-function 'foo). They
didn't see it as simply a variable in another namespace, requiring an fsetq.
Instead, they saw it as an attempt to modify some peculiar kind of thing that
wasn't really a data structure with a slot. SETF is peculiar in that SETQ is
the only thing that doesn't modify "slots" (and has to be special-cased as a
consequence)> I think (SETF (FUNCTION x) ...) would have likewise required
some special code that maybe we weren't (back in 1980) intellectually ready
for. It's probably hard to put yourself back into that mindset. Certainly
it's weird to think now that there was ever a reservation about going to
lexical scoping at all, yet there was--leaving the world of dynamic scoping
was regarded by some as very risky and scary. And what happens is that there
are sometimes cached, dependent fears that even when the primary fears are
more or less worked through don't have their cached-ness and/or their
dependency chain reconsidered, and people end up fearing them for what end
up being irrational reasons.

My previous remarks about functions as "constants" was merely an after-the-fact
observation that goes to say that mostly it hasn't been all bad that functions
are hard to assign. I think some good comes of it. But I do also subscribe
to the conflicting theory of good language design that says you shouldn't
introduce a "variable" into a language without a binding form, a definer, and
a setter. This says that it's too bad there's no setf of (function x) and also
it's too bad there's no deflexical. It mostly creates a table where you can
fill in and immediately see problems. But then again, there are variables in
other namespaces like the block namespace and the gotag namespace that don't
have these operations and don't generally suffer for it. One could add them,
and interesting programs might result, but considerable good comes of not
having them. So in the end I come back to the fact that the world is
complicated and full of trade-offs, and there is no hard and fast rule. Just
lots of stuff to consider, and a chance to blunder through making the best
judgment calls one can make at any given moment and then trying to live with
the result.

> > For example, you can almost[*] get away with the following:
> >
> > (DEFMACRO WITH-FARGS ((&REST FARGS) &BODY FORMS)
> > (LET ((TEMP (GENSYM "ARGS")))
> > `(LABELS ,(MAPCAR #'(LAMBDA (FARG)
> > `(,FARG (&REST ,TEMP)
> > (DECLARE (DYNAMIC-EXTENT ,TEMP))
> > (APPLY ,FARG ,TEMP)))
> > FARGS)
> > ,@FORMS)))
> >
> > (DEFUN FOO (FN X)
> > (WITH-FARGS (FN)
> > (PRINT (IF (FN X) 'YES 'NO))
> > (SETQ FN (COMPLEMENT FN))
> > (PRINT (IF (FN X) 'YES 'NO))
> > 'DONE))
>
> I would more like something like that:
>
> (DEFUN FOO (FN X)
> (WITH-FARGS (FN)
> (PRINT (IF (FN X) 'YES 'NO))
> (FSETQ FN (COMPLEMENT FN))
> (PRINT (IF (FN X) 'YES 'NO))
> 'DONE))

Ah, well, in this case it's not so hard. If you wnt to do literally what you
said. Consider:

(DEFMACRO FARGS-BINDINGS-INTERNAL ()
;; To not violate the sense of what a macro form is, always return
;; a quoted expression. Really we just use the quoted constant at
;; macroexpand time, though, for lexical communication.
;; This weird complexity is forced by the omission of COMPILER-LET
;; from the language...
''())

(EVAL-WHEN (:EXECUTE :COMPILE-TOPLEVEL :LOAD-TOPLEVEL)
(DEFUN FARGS-BINDINGS (ENV)
(LET ((EXP (MACROEXPAND-1 '(FARGS-BINDINGS-INTERNAL) ENV)))
(IF (AND (CONSP EXP) (EQ (CAR EXP) 'QUOTE))
(CADR EXP)
(ERROR "Not quoted: ~S" EXP))))
);NEHW-LAVE

(DEFMACRO WITH-FARGS-INTERNAL (&ENVIRONMENT ENV ADDITIONS &REST FORMS)
(LET ((TEMP (FARGS-BINDINGS ENV)))
`(MACROLET ((FARGS-BINDINGS-INTERNAL () `',',(APPEND ADDITIONS TEMP)))
,@FORMS)))

(DEFMACRO WITH-FARGS ((&REST FBINDINGS) &BODY FORMS)


(LET ((TEMP (GENSYM "ARGS"))

(FTEMPS (MAPCAR #'(LAMBDA (X) (MAKE-SYMBOL (SYMBOL-NAME X)))
FBINDINGS))
(FVARS (MAPCAR #'(LAMBDA (X) (ETYPECASE X (SYMBOL X) (CONS (CAR X))))
FBINDINGS))
(FVALS (MAPCAR #'(LAMBDA (X) (ETYPECASE X (SYMBOL X) (CONS (CADR X))))
FBINDINGS)))
`(LET ,(MAPCAR #'LIST FTEMPS FVALS)
(LABELS ,(MAPCAR #'(LAMBDA (FVAR FTEMP)
`(,FVAR (&REST ,TEMP)
(DECLARE (DYNAMIC-EXTENT ,TEMP))
(APPLY ,FTEMP ,TEMP)))
FVARS FTEMPS)
(WITH-FARGS-INTERNAL ,(MAPCAR #'LIST FVARS FTEMPS)
(MACROLET ((FSETQ (&ENVIRONMENT ENV FVAR NEW-FVAL)
`(SETQ ,(OR (CADR (ASSOC FVAR
(FARGS-BINDINGS ENV)))
(ERROR "Not bound by WITH-FARGS: ~A" FVAR))
,NEW-FVAL)))
,@FORMS))))))


This will let you do:

(DEFUN FOO (FN X)
(WITH-FARGS (FN)

(PRINT (FN X))
(FSETQ FN (COMPLEMENT FN))
(PRINT (FN X))
'DONE))

(FOO #'ODDP 3)
T
NIL
=> DONE

(FOO #'oddp 4)
NIL
T
=> DONE

But NOTE WELL that it still leaves you in the bizarre situation that

(DEFUN FOO (FN X)
(WITH-FARGS (FN)

(PRINT (FN X))
(FSETQ FN (COMPLEMENT #'FN)) ;<-- NOTE I CHANGED FN FROM ABOVE TO #'FN
(PRINT (FN X))
'DONE))

does not work. This is similar to the problem with closing over particular
iteration variable in a DOLIST. That is, it's not clear what:

(DEFUN FOO ()
(LET ((L '()))
(DOTIMES (I 5) (PUSH #'(LAMBDA () I) L))
L))

returns. It might return a list of functions that return 0, 1, etc.
respectively or it might return all functions that return 6 (or maybe 5).
It's beyond the scope of the language to say, if I remember right (didn't
check recently; I know it's a sore spot). Similarly with mine, you come
right up against the fact that

(FSETQ (COMPLEMENT #'FN))

might lose because

(SETF (FUNCTION FN) (COMPLEMENT #'FN)

turns into something which makes it more like:

(SETQ FN-INTERNAL (COMPLEMENT #'(LAMBDA (X) (FUNCALL FN-INTERNAL X))))

and so we're now infinitely recursing. [This was the solution to the extra
credit problem.] A similar problem arises with

(FSETQ FN #'(LAMBDA () (FN (FN X))))

So my solution is imperfect. But if you avoid any reference to (function fn)
in assigning the value side of the fsetq, you get well-formed behavior.

Again, this points to the need to really give you a way to assign the
location primitively, I suppose. But then again, only if you believe that
enabling this particular syntax is really important. Can you say why you
find the variable + funcall syntax a problem? I find the syntax you propose
quite confusing because I'm at this point used to (fn x) meaning FN is fixed
and the fsetq would probably go right by me... Maybe in a world having
FSETQ, I'd learn to have a healthy distrust for the meaning of (fn x),
like schemers do, but I don't see that as a big improvement in the language
personally...



> How is this related to the FUNCTION-NAME:LARGE proposal:
> http://www.xanalys.com/software_tools/reference/HyperSpec/Issues/iss174-writeup.html
> (for example part 9)?

Well, you can't fbind FUNCTION and we're talking about the SETF of a special
form, not the SETF of a function. There is no local binding equivalent to
DEFSETF. Again, this language design matrix I mentioned above, about needing
a definer, binder, etc. for each kind of place, would tell you that this was
a "predicted problem" for at least some users...

Kalle Olavi Niemitalo

unread,
Nov 26, 2000, 3:00:00 AM11/26/00
to
Kent M Pitman <pit...@world.std.com> writes:

> [*]Extra Credit:
>
> There is an interesting "screw case" to this WITH-FARGS I made, though,
> which I think exactly exposes why you should not be trying to hide
> "Lisp2"-ness inside a macro like this.

Is it this?

(DEFUN FOO (FN)
(WITH-FARGS (FN)
(LET ((FN #'CDR))
(FN '(THE UNSEEN UNIVERSITY)))))

(FOO #'CAR)
=> THE

Rob Warnock

unread,
Nov 27, 2000, 12:24:01 AM11/27/00
to
[Replying mainly for the sake of other "CL newbies" such as myself...]

Erik Naggum <er...@naggum.net> wrote:
+---------------
| * rp...@rigden.engr.sgi.com (Rob Warnock)


| | Hunh? What's FLET all about then?

| | (flet ((car (n) (+ 1 n)))
| | (values #'car (car 17)))
|

| Please note that you were not allowed to do what you just did if you
| also want to have a conforming ANSI Common Lisp program.

+---------------

I initially didn't understand Erik's comment at *all*, since both CMUCL &
CLISP accepted the FLET with no problems, and the HyperSpec section on FLET
specifically says that "flet can locally shadow a global function name".

So I went digging a little further (well, a *lot* further, due to my
unfamiliarity with the topic), and found some pointers in the X3J13
cleanup issues (specifically, PACKAGE-CLUTTER, LISP-SYMBOL-REDEFINITION,
and LISP-SYMBOL-REDEFINITION-AGAIN:MORE-FIXES) which pointed back to
the standard proper:

11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming
Programs

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. ...
3. Defining, undefining, or binding it as a macro or compiler macro.
[...#4-19 omitted...]

So symbols in the COMMON-LISP package are "different" from other packages,
and I stand properly corrected. Thanks for the lesson, Erik.

+---------------


| I think the proper question is "What's Scheme all about then?".
|
| With distinct function and variable namespaces, you don't need to
| create the kind of hellish environment where you never know what a
| function does that Scheme has invented for itself.

+---------------

I agree that the Scheme community has not gone into *nearly* the level of
thought/discussion/care/etc. that the above issues demonstrate about the
CL community. However, the Scheme standard (using R5RS for reference) *does*
at least promise you a (considerably weaker) guarantee on system-defined
procedures:

6 Standard procedures
...
The initial (or "top level") Scheme environment starts out with
a number of variables bound to locations containing useful values,
most of which are primitive procedures that manipulate data.
...
Built-in procedures that can easily be written in terms of
other built-in procedures are identified as "library procedures".
...
A program may use a top-level definition to bind any variable.
It may subsequently alter any such binding by an assignment
(see 4.1.6). These operations do not modify the behavior of
Scheme's built-in procedures.

That is, redefining "car" must *not* change the behavior of "map" or
"member" (say), even if they were defined using the original "car".

However, there is a "non-guarantee" as well:

Altering any top-level binding that has not been introduced by
a definition has an unspecified effect on the behavior of the
built-in procedures.

This might be thought of as another consequence of "4.1.6 Assignments",
where it says that the variable to be assigned to "must be bound either
in some region enclosing the set! expression or at top level", which
to me is a hint that the Scheme system is permitted (or indeed, required!)
to do something "magic" with standard procedures that are re-defined with
a top-level "define", and yet *not* required to guarantee the same magic
for variables that are assigned to without being top-level-(re)defined.

[I know, this is nowhere *near* CL's constraints, but I thought the
comparison might be interesting.]

Barry Margolin

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
In article <joswig-76B636....@news.is-europe.net>,

Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
>** Now I want to write the code without using FUNCALL. **
>
>Just assume that I want that.

So it's not something you *need*, just something you *want*, for esthetic
reasons. Of the criteria that X3J13 used to judge new proposals, esthetics
was last, IIRC.

>I want to be able to pass in a function
>as a parameter (in value space) and
>then be able to call the function in function
>space:

Once at an X3J13 meeting I suggested an &FUNCTION lambda-list keyword,
which would cause the name after it to receive a local functional binding
rather than a variable binding. There wasn't much interest, so it never
got written up as a full-fledged proposal.

One of the differences, it seems, between the Common Lisp and Scheme
communities is that Lispers prefer explicit FUNCALLs when variable
functions are being invoked, hence the separate function and variable
namespaces.

Rainer Joswig

unread,
Nov 27, 2000, 3:00:00 AM11/27/00
to
In article <IxxU5.16$Sx5.440@burlma1-snr2>, Barry Margolin
<bar...@genuity.net> wrote:

> In article <joswig-76B636....@news.is-europe.net>,


> Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
> >** Now I want to write the code without using FUNCALL. **
> >
> >Just assume that I want that.
>
> So it's not something you *need*, just something you *want*, for esthetic
> reasons. Of the criteria that X3J13 used to judge new proposals, esthetics
> was last, IIRC.

Barry, you are speculating about why I might want/need it.
I don't know if this leads to any useful argumentation.

> Once at an X3J13 meeting I suggested an &FUNCTION lambda-list keyword,
> which would cause the name after it to receive a local functional binding
> rather than a variable binding. There wasn't much interest, so it never
> got written up as a full-fledged proposal.

Yes, this would be similar.

> One of the differences, it seems, between the Common Lisp and Scheme
> communities is that Lispers prefer explicit FUNCALLs when variable
> functions are being invoked, hence the separate function and variable
> namespaces.

I have variable "global" functions in my Lisp system
all the time. I tend to have uptime of months of my personal
Lisp machine, using it at the same time as a development
system. Every time after loading a new version of some
software system, some of the function change. Everytime
after compiling some functions change. Global functions
are variable all the time - otherwise we could declare them
constant and remove indirection (as is possible on the Lisp
machine). It is my perception of the Lisp systems I use
that there is some unorthogonality in not being able
to change local functions, using a basic mechanism.

At the same, yes, I can live without it. As much as I can
live with all the other "ugly" parts of Common Lisp.
But I like to be aware of those weaker parts of CL.

Barry Margolin

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
In article <joswig-4E5084....@news.is-europe.net>,

Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
>In article <IxxU5.16$Sx5.440@burlma1-snr2>, Barry Margolin
><bar...@genuity.net> wrote:
>
>> In article <joswig-76B636....@news.is-europe.net>,
>> Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
>> >** Now I want to write the code without using FUNCALL. **
>> >
>> >Just assume that I want that.
>>
>> So it's not something you *need*, just something you *want*, for esthetic
>> reasons. Of the criteria that X3J13 used to judge new proposals, esthetics
>> was last, IIRC.
>
>Barry, you are speculating about why I might want/need it.

You later said "I find the introduction of the variable FN ugly." That and
the statement I quoted above seem to strongly imply that esthetics is the
basis for your request. If there's a good technical reason, why don't you
say it?

>I have variable "global" functions in my Lisp system
>all the time. I tend to have uptime of months of my personal
>Lisp machine, using it at the same time as a development
>system. Every time after loading a new version of some
>software system, some of the function change. Everytime
>after compiling some functions change. Global functions
>are variable all the time - otherwise we could declare them
>constant and remove indirection (as is possible on the Lisp
>machine). It is my perception of the Lisp systems I use

>that there is some unorthogonality in not being able
>to change local functions, using a basic mechanism.

In fact, unless you explicitly declare functions NOTINLINE, the
COMPILE-FILE is permitted to remove the indirection when compiling calls
between functions in the same compilation unit.

But even ignoring that, I think of global function definitions as "almost
constant". Function definitions represent the design of the program, and
normally only change as a result of a design change, while variables
represent state of a particular computation, and change normally as the
program progresses. Since the typical use of functions and variables is
not similar, it's not surprising that there's unorthogonality in the
operators that relate to them.

Kent M Pitman

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
Barry Margolin <bar...@genuity.net> writes:

> But even ignoring that, I think of global function definitions as "almost
> constant". Function definitions represent the design of the program, and
> normally only change as a result of a design change, while variables
> represent state of a particular computation, and change normally as the
> program progresses. Since the typical use of functions and variables is
> not similar, it's not surprising that there's unorthogonality in the
> operators that relate to them.

Yes, this is the thing I was trying to refer to before. This comes up in
the debate over macro hygiene. The reason in practice that I think CL
programmers perceive no macro hygiene problem is exactly this. Supposing
someone had functions or macros called HUSBAND and WIFE, and suppose I didn't
like those names because I speak Spanish, so I write in my package:

(DEFMACRO ESPOSO (MUJER) `(HUSBAND ,MUJER))
(DEFMACRO ESPOSA (HOMBRE) `(WIFE ,HOMBRE))

The above is considered good style in a macro, even though it uses free
variables. It would not be in a non-hygienic Scheme implementation, because
you'd have to fear that HUSBAND and WIFE were bound lexically, and in a
Lisp1, that kind of problem happens really a lot. But in Lisp, we advise
people not to rebind function names that are globally available, and so there
really is no risk of a problem because of that.

Now, the availability of (SETF (FUNCTION ...) ...) to the world does not
appear to me to injure this, in the sense that either it's going to set the
global definition [which SETF of SYMBOL-FUNCTION already has the potential
to do, and people are supposed to use restraint about already] or else it's
going to get a local copy, in which case the function having been bound
locally implies [by good style rules] that there is no global definition,
and so global macros should not be expanding into it. SO you'd think it
didn't matter.

But what Barry and I are both saying is that the practice which led us to
this style rule has other consequences as well, and one is that we've in our
heads learned that mostly function definitions don't change, and that in
itself is very handy to know. It makes the reading of code faster. Lisp
is full of thing that are utterly dynamic and where you just have to check
at runtime, but this is not presently one of them, and it seems to cause no
technical loss in expression--only an aesthetic loss, and there I think only
a minor one.

The reason I extend myself to say it's only a minor aesthetic loss is that
the guardians of functional aesthetics (that is, the Schemers) who would
want this to be a regular variable you could play with like regular variables,
don't use the operator setq, they use set!, to emphasize that they really
hate it when you do assignments to any variable. So while you're asking for
a more functional notation in some ways, you're at the same time asking for
a less functional notation in other ways (by introducing an effective SETQ
where CL asks you to work more functionally). Net change in aesthetics?
I'd say zero or close to it, but of course it's a personal matter.

Rainer Joswig

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
In article <WuQU5.4$Ha.281@burlma1-snr2>, Barry Margolin
<bar...@genuity.net> wrote:

> >I have variable "global" functions in my Lisp system
> >all the time. I tend to have uptime of months of my personal
> >Lisp machine, using it at the same time as a development
> >system. Every time after loading a new version of some
> >software system, some of the function change. Everytime
> >after compiling some functions change. Global functions
> >are variable all the time - otherwise we could declare them
> >constant and remove indirection (as is possible on the Lisp
> >machine). It is my perception of the Lisp systems I use
> >that there is some unorthogonality in not being able
> >to change local functions, using a basic mechanism.
>
> In fact, unless you explicitly declare functions NOTINLINE, the
> COMPILE-FILE is permitted to remove the indirection when compiling calls
> between functions in the same compilation unit.

But this removes the indirection only in this particular compilation
unit. The toplevel definition of a function is still changed,
thus variable. If, after loading code changing a function's
definition, you call that function (FOO ...) from the toplevel
or you look at the value of (SYMBOl-FUNCTION 'FOO), you are seeing
a new definition - that's for me the effect of a changeable, variable
toplevel function. Some code may or may not see this change,
but this does not make the global definition unchanged.
Thus global functions are far from being constant. What might
be fixed are certain uses of global functions, that capture
old definitions of global functions.

I don't use COMPILE-FILE that often.
I just load the file (which compiles everything in MCL), change the
definition from the editor, or in the case of the Lisp Machine, I
use the patch mechanism. I also use my Lisp system most of the
time in development mode (not in a delivery mode).

> But even ignoring that, I think of global function definitions as "almost
> constant".
> Function definitions represent the design of the program, and
> normally only change as a result of a design change,

Huh? Functions change all the time when you update them for
changed definitions. For example to get rid of bugs, improve
robustness, add features, remove features, improve speed, ...

Look at incremental development environments,
which is one strenghts of existing Lisp systems. You are
presenting a mode that's the traditional batch
version of edit/compile/run . But, sorry, this is really not
the way *I* use a Lisp system (and I guess quite a few people
are using Lisp interactively). So, I think your argumentation
that functions are "almost" constant - is not valid. There
are enough uses of Lisp where functions may change all
the time. In my thinking functions are as variable as
"variables".

> while variables
> represent state of a particular computation,

Functions are also used to present the state of some computation.
(closures, genetic programming, memoizing functions,
continuations, ...).

> and change normally as the
> program progresses. Since the typical use of functions and variables is
> not similar, it's not surprising that there's unorthogonality in the
> operators that relate to them.

Such a general argumentation as in your last sentence is mostly
useless.

What I want to be able to use in my software is a simple, basic, general,
efficient way to change local functions. I know that I can construct
non-simple and/or non-basic and/or non-general and/or inefficient
workarounds.

Additionally my question was why this is not in Common Lisp? The
answer up to now is: it hasn't been thought of. So it seems
there are no deep technical reasons that would make it not possible.
That's all.

Kent M Pitman

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
Rainer Joswig <jos...@corporate-world.lisp.de> writes:

> In article <WuQU5.4$Ha.281@burlma1-snr2>, Barry Margolin
> <bar...@genuity.net> wrote:

[...]

> > In fact, unless you explicitly declare functions NOTINLINE, the
> > COMPILE-FILE is permitted to remove the indirection when compiling calls
> > between functions in the same compilation unit.
>
> But this removes the indirection only in this particular compilation
> unit.

Not so. Only if you use DECLAIM. If you use PROCLAIM, the effect is
for all subsequent compilations.

> > Function definitions represent the design of the program, and
> > normally only change as a result of a design change,
>
> Huh? Functions change all the time when you update them for
> changed definitions. For example to get rid of bugs, improve
> robustness, add features, remove features, improve speed, ...

I anticipated this part of your reply. See my reply to Barry on this,
which was intended to expand on his remarks.

> Look at incremental development environments,

Incremental development is metalinguistic and is unaffected by any of this.
Barry's remarks and mine refer to the snapshot of any given running instance
of the program, not to the array of all such instances over time.

Also, the notion of "patching" a program is about changing the definition
associated with the same identity of the function, not about creating
a competing identity. While it's true that
(temporal-eq #<fn> #<fn after patching>)
might return temporal-NIL, the fact is that these are conceptually the
same function and so it's irrelevant that patching changed them. EQ
of #'foo and #'foo is the same in any given running snapshot.

I claim it's bad style to patch a running program, though obviously a
top-level loop that allows you to "load patches" is really logically a
separate program from the one you're loading. If you were dynamically
patching the patch loader as you loaded its own patch, then you'd be
in the area barry and I are talking about.

> > while variables
> > represent state of a particular computation,
>
> Functions are also used to present the state of some computation.
> (closures, genetic programming, memoizing functions,
> continuations, ...).

But fsetq defeats the ability to do this by making it harder to make closures
over current state. Any setq does this, and you're asking to extend that
problemsome effect to the functional namespace, where there was not previously
a problem. :-)

> > and change normally as the
> > program progresses. Since the typical use of functions and variables is
> > not similar, it's not surprising that there's unorthogonality in the
> > operators that relate to them.
>
> Such a general argumentation as in your last sentence is mostly
> useless.

Nonsense. The same would be true then of any declaration of a constant.
Why not just let them all be parameters? Or when looking at any variable
binding, doesn't your eye scan for SETQ to see if the variable retains its
value over a long passage? Wouldn't it be handy to know it was constant?
You do know this for flet and labels, and that's useful.

> What I want to be able to use in my software is a simple, basic, general,
> efficient way to change local functions. I know that I can construct
> non-simple and/or non-basic and/or non-general and/or inefficient
> workarounds.

I'm not saying this is unreasonable to want, but I am saying there is
measurable cost, and not just technically but aesthetically. It is not
unambiguously good what you want. It makes closures less "conceptually
reliable" and it trades declarative nature for state-changing. The
language is already powerful enough to express your technical need, but
it would take a part of the language that doesn't try to do that and would
risk cluttering it with something most CL users have not had serious
call for.

> Additionally my question was why this is not in Common Lisp? The
> answer up to now is: it hasn't been thought of.

No. That was definitely not the case. It *was* discussed and people
didn't like it. I can't remember why, and have retroactively suggested
a number of reasons why it might have been. I may have records of the
discussion and will hunt around. But if you trust my memory (and it
won't insult me if you don't 100%, certainly *I* don't trust it 100%),
then it was thought of. Now, whether the reasons were superficial or
well-thought-out, and whether people would make the same choices today,
I can't say either.

> So it seems
> there are no deep technical reasons that would make it not possible.

Heh. I'll admit this is true if you admit there are no deep aesthetic
reasons that compel it to be possible... :-)

> That's all.

I'll withhold judgment on this. ;-)

Barry Margolin

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
In article <joswig-736441....@news.is-europe.net>,

Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
>In article <WuQU5.4$Ha.281@burlma1-snr2>, Barry Margolin
><bar...@genuity.net> wrote:
>> Function definitions represent the design of the program, and
>> normally only change as a result of a design change,
>
>Huh? Functions change all the time when you update them for
>changed definitions. For example to get rid of bugs, improve
>robustness, add features, remove features, improve speed, ...

You don't consider those things to be changes to the design of the program?
We must be talking different languages, then.

jos...@corporate-world.lisp.de

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
In article <sfwd7fg...@world.std.com>,

Kent M Pitman <pit...@world.std.com> wrote:
> Rainer Joswig <jos...@corporate-world.lisp.de> writes:
>
> > In article <WuQU5.4$Ha.281@burlma1-snr2>, Barry Margolin
> > <bar...@genuity.net> wrote:
> [...]
> > > In fact, unless you explicitly declare functions NOTINLINE, the
> > > COMPILE-FILE is permitted to remove the indirection when compiling calls
> > > between functions in the same compilation unit.
> >
> > But this removes the indirection only in this particular compilation
> > unit.
>
> Not so. Only if you use DECLAIM. If you use PROCLAIM, the effect is
> for all subsequent compilations.

Sure. But Barry was not mentioning using PROCLAIM or DECLAIM.
He was saying that a file compiler is allowed to remove
indirect in a compilation unit. Without any declarations.
I said that this holds only for the **uses** of the function
in this particular compilation unit. The function itself
is changing. It is changed after/while loading the code.

> > Look at incremental development environments,
>
> Incremental development is metalinguistic and is unaffected by any of this.
> Barry's remarks and mine refer to the snapshot of any given running instance
> of the program, not to the array of all such instances over time.

I really don't understand that. I really can't see what
a "snapshot" of a program is of use in discussing SETQ and
something like FSETQ, while Common Lisp contains
such constructs as LOAD, EVAL, COMPILE, (SETF SYMBOL-FUNCTION),
EVAL-WHEN, ...
The tools of change are built-in into the language already.
In fact some programs take great advantage of being able
to change over time.

I would like to see a definition of what a "snapshot" is,
in this context.

For a fairly conventional example see Noteheads' "Igor Engraver".
If you run this program it is possible to check for patches.
It will download them from the Noteheads server and load
them into the running program.

If you are running a server system written in Lisp where
uptimes of months are needed, then the possibility to
change the running programming makes upgrades possible
without any downtime. This is all very useful and a
nice result of the ability to change functions over time.

> Also, the notion of "patching" a program is about changing the definition
> associated with the same identity of the function, not about creating
> a competing identity. While it's true that
> (temporal-eq #<fn> #<fn after patching>)
> might return temporal-NIL, the fact is that these are conceptually the
> same function and so it's irrelevant that patching changed them. EQ
> of #'foo and #'foo is the same in any given running snapshot.

Yes, but I can easily construct:

? (let ((f1 #'foo)) (do-something) (let ((f2 #'foo)) (eq f1 f2)))
NIL

It changed, it is not even the same object.

> I claim it's bad style to patch a running program,

Then we disagree here.

> though obviously a
> top-level loop that allows you to "load patches" is really logically a
> separate program from the one you're loading. If you were dynamically
> patching the patch loader as you loaded its own patch, then you'd be
> in the area barry and I are talking about.

;-)

> But fsetq defeats the ability to do this by making it harder to make closures
> over current state. Any setq does this, and you're asking to extend that
> problemsome effect to the functional namespace, where there was not previously
> a problem. :-)

To what degree is it harder to make closures? Can you elaborate on
this?

> > Such a general argumentation as in your last sentence is mostly
> > useless.
>
> Nonsense. The same would be true then of any declaration of a constant.

It's not nonsense. Look a bit closer at Barry's argumentation.

> Why not just let them all be parameters? Or when looking at any variable
> binding, doesn't your eye scan for SETQ to see if the variable retains its
> value over a long passage?

Actually I'm scanning for a myriad of constructs that might
change the value. The basic SETQ is just one of them.

> Wouldn't it be handy to know it was constant?

Sure. How do I declare local variables to be constant?
It would be useful to know, too.

> You do know this for flet and labels, and that's useful.

This is one side-effect. But for me this looks really like
trying to come up with a defense for some
behaviour which is the result of some other design descision.
I can come up with all kinds "this is helpful",
"this is a convention", but these arguments seem to be more
based on tradition or style. Sure that then the available
language influences the use/thinking of this language.
I wouldn't also generalize my programming style, code
reading habits to other programmers - not knowing
how they read code or what tools they use for code
inspection.

> I'm not saying this is unreasonable to want, but I am saying there is
> measurable cost,

I want to identify those.

> and not just technically but aesthetically. It is not
> unambiguously good what you want. It makes closures less "conceptually
> reliable" and it trades declarative nature for state-changing.

This is somewhat true. So we favor "declarative" of "changing"?!?

> The
> language is already powerful enough to express your technical need, but
> it would take a part of the language that doesn't try to do that and would
> risk cluttering it with something most CL users have not had serious
> call for.

See above.

> No. That was definitely not the case. It *was* discussed and people
> didn't like it. I can't remember why, and have retroactively suggested
> a number of reasons why it might have been. I may have records of the
> discussion and will hunt around. But if you trust my memory (and it
> won't insult me if you don't 100%, certainly *I* don't trust it 100%),
> then it was thought of. Now, whether the reasons were superficial or
> well-thought-out, and whether people would make the same choices today,
> I can't say either.

It would be interesting if you would find some traces of the
discussion - but only if you think it is useful, I don't want
to "steal" your time.

> Heh. I'll admit this is true if you admit there are no deep aesthetic
> reasons that compel it to be possible... :-)

I have to think about that. ;-)


Sent via Deja.com http://www.deja.com/
Before you buy.

Rainer Joswig

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
In article <1jUU5.16$Ha.402@burlma1-snr2>, Barry Margolin
<bar...@genuity.net> wrote:

> >In article <WuQU5.4$Ha.281@burlma1-snr2>, Barry Margolin
> ><bar...@genuity.net> wrote:

> >> Function definitions represent the design of the program, and
> >> normally only change as a result of a design change,
> >
> >Huh? Functions change all the time when you update them for
> >changed definitions. For example to get rid of bugs, improve
> >robustness, add features, remove features, improve speed, ...
>
> You don't consider those things to be changes to the design of the program?
> We must be talking different languages, then.

Yes.

They can be design changes. But they need not be.

There can be different **implementations** of a design.
I can switch between implementations without changing
the design.

Kent M Pitman

unread,
Nov 28, 2000, 3:00:00 AM11/28/00
to
jos...@corporate-world.lisp.de writes:

> To what degree is it harder to make closures? Can you elaborate on
> this?

Contrast:
(mapcar #'funcall
(flet ((foo (x) (+ x 1)))
(list #'(lambda () (foo 5))
(flet ((foo (x) (- x 1)))
#'(lambda () (foo 5))))))
with:
(mapcar #'funcall
(flet ((foo (x) (+ x 1)))
(list #'(lambda () (foo 5))
(progn (setf #'foo #'(lambda (x) (- x 1)))
#'(lambda () (foo 5))))))

[hope i got these right--i didn't bother to test them]

Adding the ability to fsetq pretty much assures that the certain closures
will fail to capture what the naive programmer may want to capture. We
already have this problem for variables, but we train people to look for it.
We don't train people to look for this in functions.

> I want to identify those [negatives]

a. The introduction of an imperative/assignment where a binding form formerly
sufficed.

b. The loss of ability to know that the function namespace is constant in
code with good style, to those of us who have my theory of good style.

c. The loss of the "declarative" use of FUNCALL as case-marking for
function calls that have a variable function being used.

Barry Margolin

unread,
Nov 29, 2000, 3:00:00 AM11/29/00
to
In article <joswig-2C9DF5....@news.is-europe.net>,

Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
>In article <1jUU5.16$Ha.402@burlma1-snr2>, Barry Margolin
><bar...@genuity.net> wrote:
>
>> In article <joswig-736441....@news.is-europe.net>,
>> Rainer Joswig <jos...@corporate-world.lisp.de> wrote:
>> >In article <WuQU5.4$Ha.281@burlma1-snr2>, Barry Margolin
>> ><bar...@genuity.net> wrote:
>> >> Function definitions represent the design of the program, and
>> >> normally only change as a result of a design change,
>> >
>> >Huh? Functions change all the time when you update them for
>> >changed definitions. For example to get rid of bugs, improve
>> >robustness, add features, remove features, improve speed, ...
>>
>> You don't consider those things to be changes to the design of the program?
>> We must be talking different languages, then.
>
>Yes.
>
>They can be design changes. But they need not be.

Well, I consider features to be part of the design, not the
implementation. If you add or remove user-visible features, you're
changing the external specification. And robustness is on the borderline
between design and implementation (ideally it should be part of the design,
but often the specification is vague about this, and it's left to the
programmer to try to get things right).

>There can be different **implementations** of a design.
>I can switch between implementations without changing
>the design.

I guess the word I was having trouble thinking of was "implementation".
But I think you get my point: function definitions are attributes of the
program, variables are attributes of the current state of the program. The
program normally only changes when you're reimplementing it (either due to
redesign, or to update the implementation of an existing design); variables
normally change all the time, since each run has different state (otherwise
there wouldn't be a need to re-run it).

0 new messages