Page 1 of 2
Defining a lexically scoped function.
Posted: Mon Feb 08, 2010 11:44 pm
by Jesdisciple
I want to alias a function as another lexically scoped function. The function to be aliased is returned by another function, which is the reason I want to alias it - so it can be cached. I think this was working but I abandoned it when I read somewhere that fdefinition returns a global:
This could probably work, maybe with some inspection to accept the correct arguments, but doesn't really solve anything:
Code: Select all
(labels (foo (&rest args) (bar @,args)))
Grr...
Is there some obscure macro that does what I'm wanting, or maybe I can use whatever such a macro would use?
Re: Defining a lexically scoped function.
Posted: Tue Feb 09, 2010 1:53 am
by ramarren
Jesdisciple wrote:Is there some obscure macro that does what I'm wanting, or maybe I can use whatever such a macro would use?
I don't really understand what you want... if you want to establish a lexical function calling a function stored in variable, the you can just do:
Code: Select all
(flet ((lexical-alias (&rest args)
(apply variable-holding-your-function args)))
...)
But that is neither a macro nor obscure.
Re: Defining a lexically scoped function.
Posted: Tue Feb 09, 2010 6:42 pm
by Jesdisciple
JavaScript was my first language and it's the best way I know to demonstrate what I mean. This makes `baz' a global variable, which is what `setf' allows me to do in CL:
Code: Select all
function foo(){
function bar(){
return function (){
alert(70 * 7);
}
}
baz = bar();
}
This makes `baz' local to `foo', which is what I want:
Code: Select all
function foo(){
function bar(){
return function (){ // anonymous function
alert(70 * 7);
};
}
var baz = bar();
}
And here is what `labels'/`flet' allows me to do. I don't like it because I still have to call a function (an
extra function - wrong direction!) every time I want that other function (the anonymous one).
Code: Select all
function foo(){
function bar(){
return function (){
alert(70 * 7);
}
}
function baz(){
return bar();
}
}
Re: Defining a lexically scoped function.
Posted: Wed Feb 10, 2010 12:02 am
by ramarren
Jesdisciple wrote:This makes `baz' a global variable, which is what `setf' allows me to do in CL:
SETF doesn't create variables, global or otherwhise. SETF sets places. Using SETF on an undefined place, in particular nonexistent variable, is undefined. Most implementations will create a special-dynamic variable, but many will signal a warning. The reason for that is that it allows catching typos in variable names. Creating global variables is done with
DEFPARAMETER/DEFVAR and shouldn't really be done at runtime anyway.
Jesdisciple wrote:JavaScript was my first language and it's the best way I know to demonstrate what I mean.
Javascript is essentially a mutated version of Scheme. Scheme is Lisp-1, and Common Lisp is not. You either have to assign functions to variables bound by
LET, and call them with
FUNCALL/
APPLY, or establish a local wrapping function with
FLET/LABELS.
I don't really see why the latter would be insufficient. I suppose it would be a little more verbose, but that is just a macro away. There is no performance hit from the additional function call if the wrapping function is declared
INLINE.
Re: Defining a lexically scoped function.
Posted: Wed Feb 10, 2010 1:55 pm
by Jesdisciple
Ramarren wrote:SETF doesn't create variables, global or otherwhise. SETF sets places. Using SETF on an undefined place, in particular nonexistent variable, is undefined.
I get the difference between places, variables and functions, but I was using JS terminology at the time, where they all get muddled together. But anyway, this is where I got the idea that (setf fdefinition) makes a new function symbol:
I guess I read too much into that?
Ramarren wrote:Javascript is essentially a mutated version of Scheme. Scheme is Lisp-1, and Common Lisp is not. You either have to assign functions to variables bound by
LET, and call them with
FUNCALL/
APPLY, or establish a local wrapping function with
FLET/LABELS.
I don't really see why the latter would be insufficient. I suppose it would be a little more verbose, but that is just a macro away. There is no performance hit from the additional function call if the wrapping function is declared
INLINE.
`bar' is a function factory which returns essentially the same function every time, but the returned function has a state in its closure which is to be modified by user code. Unless I can cache this returned function, my objective is impossible.
But you mentioned that `let' can also define a function symbol...?
Re: Defining a lexically scoped function.
Posted: Wed Feb 10, 2010 2:22 pm
by ramarren
Jesdisciple wrote:new function symbol
There are no function symbols. A symbol is conceptually a structure with a number of fields. It is usually no implemented like that because for a majority of symbols some of those fields will be empty, so it would be a waste of space. But however they are implemented the
specification defines five accessors, one of which is
SYMBOL-FUNCTION, which holds a function. A symbol with a function in this field names the function, but there is nothing special about it.
FDEFINITION is different from
SYMBOL-FUNCTION in that it take a
function name, which can be more than a symbol, but when given a symbol it is more or less equivalent.
What I am trying to say is that function are first class values independent of symbols. You can bind them to variables, put then in list, arrays, hashtables, objects or whatever directly. The wrapper function would only be there in order to avoid using
FUNCALL/
APPLY when calling it, but there is not much point.
Code: Select all
(defun make-accumulator ()
(let ((total 0))
(lambda (x)
(incf total x))))
(let ((variable1 (make-accumulator))
(variable2 (make-accumulator)))
(print (funcall variable1 3))
(print (funcall variable2 2))
(print (funcall variable1 4))
(print (funcall variable2 8)))
Re: Defining a lexically scoped function.
Posted: Wed Feb 10, 2010 4:19 pm
by Jesdisciple
I guess I was thinking of "field" rather than "symbol" then. I've seen many new terms this past week.

But I was actually thinking the symbol was an index in one of several hash tables (scopes) - function scope being one. Or am I misusing "scope" as well?
But yes, LET is what I was looking for, so thanks! I can't believe I didn't see (or notice, rather) anything about that, as much as I looked.
EDIT: The workaround I developed for the global scope is:
Code: Select all
(defun foo () )
(setf (fdefinition `foo) ((lambda ()
#| ... |#)))
(foo)
Would this work with LABELS/FLET as well?
Re: Defining a lexically scoped function.
Posted: Thu Feb 11, 2010 12:01 am
by ramarren
Jesdisciple wrote:I guess I was thinking of "field" rather than "symbol" then. I've seen many new terms this past week.
Well, "field" might not actually be a Common Lisp term, I just thought it would be clearer than "slot", which applies to objects anyway. I am not sure what name to whatever is that symbols contain is. They are accessible only by accessor functions, anyway.
Jesdisciple wrote:But I was actually thinking the symbol was an index in one of several hash tables
It might be implemented somewhat like that, but that is an implementation detail.
Jesdisciple wrote:(scopes) - function scope being one. Or am I misusing "scope" as well?
In this case I think you mean "function namespace". Scope is, more or less, the area of code where an identifier refers to a variable. You can read more about scope and extend in
CLTL chapter 3.
Jesdisciple wrote:Would this work with LABELS/FLET as well?
Not directly. You cannot actually directly bind a lambda this way, you have to create a wrapping function, possibly inline, which will go through some variable, likely established by LET. This either a concession to implementing effective compilation or because CL was designed by committee, I don't know which.
Re: Defining a lexically scoped function.
Posted: Thu Feb 11, 2010 9:40 am
by Jesdisciple
Ramarren wrote:In this case I think you mean "function namespace". Scope is, more or less, the area of code where an identifier refers to a variable. You can read more about scope and extend in
CLTL chapter 3.
D'oh, I knew that.
Ramarren wrote:Not directly. You cannot actually directly bind a lambda this way, you have to create a wrapping function, possibly inline, which will go through some variable, likely established by LET.
Ew... But what do you mean by "a wrapping function ...
[going] through some variable"?
Re: Defining a lexically scoped function.
Posted: Thu Feb 11, 2010 9:47 am
by ramarren
Jesdisciple wrote:Ew... But what do you mean by "a wrapping function ... [going] through some variable"?
I just mean what I did in the example in the first reply of this thread. Create a local function which only calls the function stored in a variable, then you can store the lambda in the variable but call the function without FUNCALL/APPLY.