setq doesn't work inside a function ?

Discussion of Common Lisp

setq doesn't work inside a function ?

Postby Kovalev27 » Wed Nov 04, 2009 10:39 am

Hi guys.

I need some help. I have a weird problem.

If i do

(defun fctn1 (list list2)
(setq list2 (cons (car list) list2))
)

then I do
(setq list (list 'a 'b))
(setq list2 (list))
(fctn1 list list2)
I type list , i get (A B ) back
I type list2, i get NIL back??? WHY NIL ??

I think decide to do it manually without a fctn, so I just type:
(setq list2 (cons (car list) list2))
I type list, i get (A B) back
I type list2 , i get A back .

Why is setq working outside the function but not inside ? A little help please!!
Kovalev27
 
Posts: 2
Joined: Tue Nov 03, 2009 11:48 pm

Re: setq doesn't work inside a function ?

Postby findinglisp » Wed Nov 04, 2009 5:51 pm

Kovalev27 wrote:Hi guys.

I need some help. I have a weird problem.

If i do

(defun fctn1 (list list2)
(setq list2 (cons (car list) list2))
)


So here's one problem. As soon as you used LIST and LIST2 as the argument names of the function FCTN1, the SETQ form will refer to those local arguments, not the globals at the REPL. If you SETQ LIST2, it will simply set the local variable also named LIST2 inside the function; it will not alter the global value of LIST2 that you set below.

then I do
(setq list (list 'a 'b))
(setq list2 (list))


Now, your main problem is right here. LIST is the name of a function, so (LIST) calls the LIST function with no arguments, which results in NIL (the empty list) as a result. Thus, the variable LIST2 is set to NIL. If you did (setq list2 list), it would work. In that case, it would choose the variable value of LIST, not invoke the function.

What you're running into here is that Common Lisp is a "Lisp 2." That is, it allows the same symbol (LIST in this case) to be used as both the name of a function and a variable at the same time. The system distinguishes between the two using context. If LIST appears in the function call position, as the first element in a parenthesized form, the evaluation rules say to treat it as a function call.

This is useful at various times, but can be confusing, particularly to a beginning Lisp programmer. Note that Scheme doesn't work this way. All references to a particular symbol are identical. The downside to that is that it's impossible to have a variable named LIST since it always refers to the function named LIST. Thus, you'll see a lot of Scheme code that uses LST instead of LIST as a variable name, to avoid a collision with the function names LIST.

(fctn1 list list2)
I type list , i get (A B ) back
I type list2, i get NIL back??? WHY NIL ??


Because you (SETQ LIST2 (LIST)), which sets LIST2 to NIL. Calling FCTN1 doesn't do anything to the global variables named LIST or LIST2 since the SETQ in FCTN1 just changes the local value of LIST2 inside the function, not the global value.

I think decide to do it manually without a fctn, so I just type:
(setq list2 (cons (car list) list2))
I type list, i get (A B) back
I type list2 , i get A back .

Why is setq working outside the function but not inside ? A little help please!!


It is working inside, but you aren't seeing it work because it's acting on a different variable, also named LIST2, inside the function, and you don't check the value of that variable inside the function. Whenever you check LIST2 from the REPL, you're only seeing the global value.
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
findinglisp
 
Posts: 440
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX

Re: setq doesn't work inside a function ?

Postby Kovalev27 » Wed Nov 04, 2009 6:02 pm

How do I make my function change the global variables then ?
Kovalev27
 
Posts: 2
Joined: Tue Nov 03, 2009 11:48 pm

Re: setq doesn't work inside a function ?

Postby findinglisp » Wed Nov 04, 2009 6:15 pm

Kovalev27 wrote:How do I make my function change the global variables then ?


If your function arguments don't shadow the global names, then SETQ will work. So, for instance, define FCNT1 like so:
Code: Select all
(defun fctn1 () ; no arguments means no shadowing
    (setq list2 (cons (car list) list2))) ; now LIST and LIST2 will refer to the global values
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
findinglisp
 
Posts: 440
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX

Re: setq doesn't work inside a function ?

Postby findinglisp » Wed Nov 04, 2009 6:22 pm

I should also say that generally global variables use a special naming convention to distinguish them: they are surrounded by "*" characters. So, for instance you can see a bunch of global variable names in the Common Lisp spec named things like *standard-input* or *standard-output*. If you follow that convention, then you won't accidentally shadow any global variable names in your functions.

I should also note that global variables are "special," as opposed to lexical variables. This means that they behave differently when they are rebound. That's for another lesson, however. One point of the "earmuff" convention of using "*" characters on global, special variables is that it highlights their "specialness" and calls out the behavior when they are rebound. Again, that's for another less, however.

You're doing well. So far, you have gotten tripped up by issues of Lisp 2 and special variables. Not bad for a beginner. :D
Cheers, Dave
Slowly but surely the world is finding Lisp. http://www.findinglisp.com/blog/
findinglisp
 
Posts: 440
Joined: Sat Jun 28, 2008 7:49 am
Location: Austin, TX


Return to Common Lisp

Who is online

Users browsing this forum: Bing [Bot] and 3 guests