From: ········@gmail.com
Subject: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <1179579406.761308.134230@k79g2000hse.googlegroups.com>
I'm new to Common Lisp, so please forgive the dumb question.

There is simply something fundamental that I don't get about how
symbols and variables are passed to functions.  Basically, why doesn't
this work?

(defstruct range min max)

(defun range? (n rg)
  (and (<= n (range-max rg))
       (>= n (range-min rg))))

(defparameter a (make-range :min 2 :max 4))

(mapcar #'range? '(0 2 4) '(a a a))

When I run this sin SLIME/SBCL, I drop into the debugger which tells
me that value 'A' is not of type RANGE.  Well, ok, when I examine the
stack, I see that ARG-1 = A and that A...

A symbol.
 [type: SYMBOL]
--------------------
Its name is: "A"
It is a global variable bound to: #S(RANGE :MIN 2 :MAX 6)

What??  If A is a RANGE struct why am I getting a typedef error?

Thanks, and I'm sure you get this question on this list a lot, but I'm
missing something in my mental model of CL,  I don't understand what's
going on, and I'm frankly baffled.

W-

From: Dan Bensen
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <f2mvb4$70k$1@wildfire.prairienet.org>
········@gmail.com wrote:
> I'm new to Common Lisp
Welcome to c.l.l :)

> There is simply something fundamental that I don't get about how
> symbols and variables are passed to functions.  Basically, why doesn't
> this work?
> (mapcar #'range? '(0 2 4) '(a a a))

You don't need the quote before the a's.
Replace '(a a a) with (list a a a).

> When I run this sin SLIME/SBCL, I drop into the debugger which tells
> me that value 'A' is not of type RANGE.

When you quote a symbol, as you did by quoting the list full of a's,
the quote tells the compiler not to evaluate the symbol.
So the debugger is right:  'a (quoted) is not a range, it's the
original symbol.

LIST is just a function though, so in (list a a a), each A will be
evaluated as a variable.  Of course, the value of A is the range struct
that you want.

Also, if you want to avoid having to repeat A, you can define
a function that returns (range? n a) for any argument n, and
just map that function onto your list of numbers.  If you plan on
using the function later, you can give it a name with defun.
If not, you can just define it inside your mapcar form with lambda.

-- 
Dan
www.prairienet.org/~dsb/
From: Richard M Kreuter
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <87veeo3o3m.fsf@tan-ru.localdomain>
········@gmail.com writes:

> There is simply something fundamental that I don't get about how
> symbols and variables are passed to functions.  Basically, why doesn't
> this work?
>
> (defstruct range min max)
>
> (defun range? (n rg)
>   (and (<= n (range-max rg))
>        (>= n (range-min rg))))
>
> (defparameter a (make-range :min 2 :max 4))
>
> (mapcar #'range? '(0 2 4) '(a a a))
>
> When I run this sin SLIME/SBCL, I drop into the debugger which tells
> me that value 'A' is not of type RANGE.  Well, ok, when I examine the
> stack, I see that ARG-1 = A and that A...

Note that '(a a a) parses as (quote (a a a)), and that the QUOTE
special operator prevents evaluation of its argument, so (quote (a a
a)) evaluates to a list of length 3 whose elements are the symbol A.

What you want is a list of length three whose elements are the value
of A, which you can construct with the LIST function:

(list a a a)
=> (#S(RANGE :MIN 2 :MAX 4) #S(RANGE :MIN 2 :MAX 4) #S(RANGE :MIN 2 :MAX 4))

Finally, a suggestion, in case you haven't encountered it already:
DEFPARAMETER creates a special variable (i.e., a dynamically scoped
variable).  Forms that bind or evaluate variables do different things
depending on whether a variable is lexical or special, and tricky
things can happen if you inadvertently rebind a special variable.  So
in Common Lisp everybody follows the convention that special variables
defined by DEFPARAMETER and DEFVAR have asterisks around the name,
e.g., *A* instead of A.

--
RmK
From: Rob St. Amant
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <f2n7n8$2dl$1@blackhelicopter.databasix.com>
········@gmail.com writes:

> I'm new to Common Lisp, so please forgive the dumb question.
>
> There is simply something fundamental that I don't get about how
> symbols and variables are passed to functions.  Basically, why doesn't
> this work?
>
> (defstruct range min max)
>
> (defun range? (n rg)
>   (and (<= n (range-max rg))
>        (>= n (range-min rg))))

One more peripheral comment on style: the Common Lisp naming
convention for predicates is that they end in "p".  Changing range?
to rangep or range-p is likely to result in confusion or even
unexpected behavior, however, because the defstruct form above will
automatically generate a predicate, range-p, to test whether a given
object is a range.  Naming the function in-range-p rather than range?
would probably be better.
From: ········@gmail.com
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <1179595559.769664.10720@p47g2000hsd.googlegroups.com>
Wow, am I glad I asked my question here!  Thank you to everyone for
your patient and helpful replies.  I ended up learning more than the
answer to my original question.

I wasn't seeing that a symbol is not the same as a variable. I think I
was thrown off by habits learned with other languages where you don't
really have a symbol at runtime. Also the fact that LISP automatically
applies symbol-value when a symbol is evaluated (i.e. not quoted) sort
of hid this feature from my novice perspective.  Pascal's post really
clarified that for me, and everyone's example code helped me see this
as well.

Thanks also about the hint on using a lambda expression instead of a
second (redundant) list of 'a' values.  And the CL predicate naming
convention with the warning about what defstruct creates.  Clearly, I
had to get past the "symbol" concept before I'll ever start thinking
in idioms.

I'm trying to learn CL because after 10+ years of professional
programming, I'm still trying to get better :-)  I guess getting my
brain to think differently is going to take some time.  Thanks again
for the warm welcome and patient help.

W-
From: Edi Weitz
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <ups4w64kg.fsf@agharta.de>
On 19 May 2007 10:25:59 -0700, ········@gmail.com wrote:

> Also the fact that LISP automatically applies symbol-value when a
> symbol is evaluated (i.e. not quoted)

Not exactly.  There's a difference between lexical and dynamic
variables:

  CL-USER 1 > (let ((a 42)) a)
  42

  CL-USER 2 > (let ((a 42)) (symbol-value 'a))

  Error: The variable A is unbound.
    1 (continue) Try evaluating A again.
    2 Return the value of :A instead.
    3 Specify a value to use this time instead of evaluating A.
    4 Specify a value to set A to.
    5 (abort) Return to level 0.
    6 Return to top loop level 0.

  Type :b for backtrace, :c <option number> to proceed,  or :? for other options

If you haven't done so already, you should probably read "Practical
Common Lisp."  See for example the chapter about variables:

  http://www.gigamonkeys.com/book/variables.html

> I'm trying to learn CL because after 10+ years of professional
> programming, I'm still trying to get better :-)

Sounds like a very good plan... :)

> Thanks again for the warm welcome and patient help.

Many people think that comp.lang.lisp is inhabited by a bunch of
assholes... :)

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Joe Marshall
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <1179602242.384197.283020@y80g2000hsf.googlegroups.com>
On May 19, 11:39 am, Edi Weitz <········@agharta.de> wrote:

>
> Many people think that comp.lang.lisp is inhabited by a bunch of
> assholes... :)

I thought we were savages.  Go figure.
From: Ken Tilton
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <3xJ3i.34$0F7.4@newsfe12.lga>
Edi Weitz wrote:
> On 19 May 2007 10:25:59 -0700, ········@gmail.com wrote:
> 
> 
>>Thanks again for the warm welcome and patient help.
> 
> 
> Many people think that comp.lang.lisp is inhabited by a bunch of
> assholes... :)

I've been busy.

kenny
From: Wade Humeniuk
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <m2zm40rkis.fsf@telus.net.no.spam>
········@gmail.com writes:

> A symbol.
>  [type: SYMBOL]
> --------------------
> Its name is: "A"
> It is a global variable bound to: #S(RANGE :MIN 2 :MAX 6)
>
> What??  If A is a RANGE struct why am I getting a typedef error?
>
> Thanks, and I'm sure you get this question on this list a lot, but I'm
> missing something in my mental model of CL,  I don't understand what's
> going on, and I'm frankly baffled.
>

You are passing the symbol 'a to range?  Your intention was to pass
the value bound to the symbol 'a.  The symbol 'a is *bound* to the
value #s(range :min 2 :max 4).

;;; New Code

(defstruct range min max)

(defun range? (n rg)
  (<= (range-min rg) n (range-max rg)))

(defparameter a (make-range :min 2 :max 4))

(mapcar (lambda (n rg)
	  (range? n (symbol-value rg)))
	'(0 2 4) '(a a a))

CL-USER> (mapcar (lambda (n rg)
	            (range? n (symbol-value rg)))
                    '(0 2 4) '(a a a))

(NIL T T)
CL-USER> 


Wade
From: David Golden
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <RZC3i.19739$j7.373703@news.indigo.ie>
········@gmail.com wrote:

> I'm new to Common Lisp, so please forgive the dumb question.
> 
> There is simply something fundamental that I don't get about how
> symbols and variables are passed to functions.  Basically, why doesn't
> this work?
> 
> (defstruct range min max)
> 
> (defun range? (n rg)
>   (and (<= n (range-max rg))
>        (>= n (range-min rg))))
> 
> (defparameter a (make-range :min 2 :max 4))
> 
> (mapcar #'range? '(0 2 4) '(a a a))
> 

Leaving aside any fussing over wider stylistic/implementation issues and
such here - the immediate issue is because you have quoted the list
of "a"s.  Quote stops name->value in all its descendants, so you
end up passing the symbol "a" itself to "range?".

It might be a handy moment to learn about backquote (sometimes called
quasiquote): 

(mapcar #'range? '(0 2 4) `(,a ,a ,a))

Note how the quote-like mark leans backwards (it's a grave accent on its
own, really).  "`" acts very like "'" until you get to a ",". ","
then "unquotes", causing evaluation of its subforms within the
quasiquoted form, so in this case a -> value of a.

But actually, you could just:

(mapcar #'range? (list 0 2 4) (list a a a))

which you might find clearer anyway (and it helps avoid some relatively
subtle issues about shared structure which may bite if you don't keep
your code "functional")

Yes, this stuff tends to be covered in introductory lisp books.
"Practical Common Lisp" by Peter Siebel is nice if you're a hands-on
type.
From: Pascal Bourguignon
Subject: Re: Novice: symbol resolution w/ mapcar?
Date: 
Message-ID: <87abw0ltww.fsf@thalassa.lan.informatimago.com>
········@gmail.com writes:

> I'm new to Common Lisp, so please forgive the dumb question.
>
> There is simply something fundamental that I don't get about how
> symbols and variables are passed to functions.  Basically, why doesn't
> this work?
> [...]
> When I run this sin SLIME/SBCL, I drop into the debugger which tells
> me that value 'A' is not of type RANGE.  Well, ok, when I examine the
> stack, I see that ARG-1 = A and that A...
>
> A symbol.
>  [type: SYMBOL]
> --------------------
> Its name is: "A"
> It is a global variable bound to: #S(RANGE :MIN 2 :MAX 6)
>
> What??  If A is a RANGE struct why am I getting a typedef error?


A is not a range.  A is a symbol.  It's written here that A is:

> A symbol.
>  [type: SYMBOL]
> --------------------
> Its name is: "A"


It's what other programming languages call "identifier".  Only in
onther programming languages, identifiers are only a compilation time
notion, names given to variables, and aren't useful to the programmer
(but the compiler programmer).

In Lisp, "identifiers", ie. symbols are first class objects, they're
available at run-time too, and any application programmer can use them
(eg. to write a macro, a compiler, or any kind of symbolic programming
code).


As for variables, in Common Lisp, there are broadly two kinds of
variables: global dynamic variables (also called special variables),
and local lexical variables.  These variables are named by symbols of
course.  But at run-time, the lexical variables lose their name, the
association between the lexical variable and the symbol is forgotten:
the compiler maps the variable to addresses in the stack frame, and
it's not possible to find the variable from the symbol.  On the other
hand, for dynamic variables, the link between the symbol naming the
variable and the variable is kept at run-time, and we can find and
change the value of the variable knowing the symbol naming it at
run-time.

(defparameter a 1)

(let ((var-name 'a))
   (symbol-value var-name))  --> 1

(let ((var-name 'a))
   (setf (symbol-value var-name) 2))

a --> 2


(let ((a 3)
      (b 4))
  (values (boundp 'a)
          (boundp 'b)))
--> T ;                 A is bound (it has a symbol-value)
    NIL                 B is not bound (it has no symbol-value)

For this surprizing result, A is called special, and special variables
are usually named with symbols whose name starts and ends with a star:

(defparameter *a* 2)
(let ((*a* 3)
      (b   4))
  (values (boundp '*a*)
          (boundp 'b)))
--> T ;
    NIL

This way, it's less surprizing: we see clearly that *A* is special, and
B is a normal lexical variable.



You could implement your own value slot:

(defparameter *values* (make-hash-table))

(defmacro define-my-variable (variable value)
   (setf (gethash variable *values*) value))

(defun my-boundp (variable) (nth-value 1 (gethash variable *values*)))

(defun my-value  (variable) 
   (if (my-boundp variable)
      (gethash variable *values*)
      (error "~A is not my-bound" variable)))

(defun (setf my-value) (value variable)
   (unless (my-boundp variable)
      (warn "This variable is undefined: ~A" variable))
   (setf (gethash variable *values*) value))



(define-my-variable *a* 30)
(my-value '*a*) 
--> 30

(setf (my-value '*a*) 10)
(my-value '*a*)
--> 10

The only difference between symbol-value and my-value, is that
symbol-value is automatically called when you evaluate the symbol:

*a*                 --> 2
(symbol-value '*a*) --> 2
(my-value '*a*)     --> 10

and it's automatically modified and restored when you use LET:

(let ((*a* 3))
   (list  *a* (symbol-value '*a*)))  --> (3 3)


But the point here is why should the _symbol_ *A* be interpreted as 3
or as 10, or as anything else the symbol *A* may represent in other
parts of the program?  When you pass the symbol itself to a function
like RANGE?, lisp cannot know what interpretation of the symbol you
want, the special variable or your own my-value stuff or something
else.  It's just a plain symbol (and not a range value).



Finally, note that having to pass the value of the variable is usually
not a big problem, because in lisp most values are actually
references:

(defun change-min-of-range (min range) (setf (range-min range) min))

(let ((a (make-range :min 0 :max 10))
      (b (make-range :min 0 :max 10))
      (c (make-range :min 0 :max 10)))
  (mapc (function change-min-of-range) '(1 2 3) (list a b c))
  (list a b c))
--> (#S(RANGE :MIN 1 :MAX 10)
     #S(RANGE :MIN 2 :MAX 10)
     #S(RANGE :MIN 3 :MAX 10))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.