From: basi
Subject: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <1104737229.280521.320580@c13g2000cwb.googlegroups.com>
How do I convert the value of a string variable to a quoted symbol that
I can use as key to a property list?

(defvar name-age-list '(joe 22 jane 21 john 12))

Now I'd like to say:

(getf name-age-list name)

where name is a string variable.

I'm afraid I've taken a wrong turn somewhere here and I find myself in
a foggy forest going around in circles. The answer should be obvious
and I'm prepared to be embarrassed. 

Basi

From: David Sletten
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <Jl7Cd.44751$Ew6.2023@twister.socal.rr.com>
basi wrote:

> How do I convert the value of a string variable to a quoted symbol that
> I can use as key to a property list?
> 
> (defvar name-age-list '(joe 22 jane 21 john 12))
> 
> Now I'd like to say:
> 
> (getf name-age-list name)
> 
> where name is a string variable.
> 
> I'm afraid I've taken a wrong turn somewhere here and I find myself in
> a foggy forest going around in circles. The answer should be obvious
> and I'm prepared to be embarrassed. 
> 
> Basi
> 
3 ways to get a symbol out of a string:
INTERN
FIND-SYMBOL
READ-FROM-STRING

INTERN and FIND-SYMBOL also take an optional package arg. Be careful 
since INTERN and READ-FROM-STRING will _create_ a symbol with the given 
name if it doesn't exist yet. Also note the difference here:
(intern "list")
vs.
(read-from-string "list")

David Sletten
From: Guybrush Treepwood
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <41d8f5be$0$313$ba620e4c@news.skynet.be>
basi wrote:


> (getf name-age-list name)
> 
> where name is a string variable.

Is there a specific reason why <name> should be a string?
Just pass a symbol as argument. 
From: Pascal Bourguignon
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <87k6quam36.fsf@thalassa.informatimago.com>
"basi" <··········@yahoo.com> writes:

> How do I convert the value of a string variable to a quoted symbol that
> I can use as key to a property list?
> 
> (defvar name-age-list '(joe 22 jane 21 john 12))
> 
> Now I'd like to say:
> 
> (getf name-age-list name)
> 
> where name is a string variable.
> 
> I'm afraid I've taken a wrong turn somewhere here and I find myself in
> a foggy forest going around in circles. The answer should be obvious
> and I'm prepared to be embarrassed. 

Either use a property list and symbols (or EQL objects):

(getf name-age-list
      (with-standard-io-syntax (intern (string-upcase "jane") *package*)))
--> 21


Or use ASSOC and pass a :TEST function:

(second (member "jane" name-age-list
                :test (lambda (a b) (and (or (symbolp a) (stringp a))
                                         (or (symbolp b) (stringp b))
                                         (string-equal a b))))
--> 21


Or use a-lists:

(defparameter name-age-list '((joe 22) (jane 21) (john 12)))
(cadr (assoc "jane" name-age-list :test (function string-equal)))
--> 21


-- 
__Pascal_Bourguignon__               _  Software patents are endangering
()  ASCII ribbon against html email (o_ the computer industry all around
/\  1962:DO20I=1.100                //\ the world http://lpf.ai.mit.edu/
    2001:my($f)=`fortune`;          V_/   http://petition.eurolinux.org/
From: basi
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <1104780889.868673.163420@f14g2000cwb.googlegroups.com>
Thanks again for the ideas.


So far, I've beeing guided by a single syntatic form:

(x a b c)

where, if x can be interpreted as a function, the form is a function
application, and if x is not a function, the form is a data list.

Given the statement:

(assoc "jane" name-age-list :TEST (FUNCTION STRING-EQUAL))


I can't fit the highlighted materials into the canonical form (it
certainly is not c in (x a b c)). What is :test a keyword of -- the
function assoc or the result of the application of assoc on "jane"
name-age-list? So it is an enhancement/extension to the basic syntactic
form. If I expect that every part of the canonical form can have
keywords, for example:

(x :1 (s-expr) a :2 (s-expr) b :3 (s-expr) c :4 (s-expr))

would I be off-the-mark?

Also, what other syntactic *extensions* are there to the basic (x a b
c) form? New structures are easier to learn, I find, if they are
anchored on what's there already.

Thanks again.
Basi
From: David Sletten
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <QVkCd.45135$Ew6.19459@twister.socal.rr.com>
basi wrote:

> Thanks again for the ideas.
> 
> 
> So far, I've beeing guided by a single syntatic form:
> 
> (x a b c)
> 
> where, if x can be interpreted as a function, the form is a function
> application, and if x is not a function, the form is a data list.
> 
> Given the statement:
> 
> (assoc "jane" name-age-list :TEST (FUNCTION STRING-EQUAL))
> 
> 
> I can't fit the highlighted materials into the canonical form (it
> certainly is not c in (x a b c)). What is :test a keyword of -- the
> function assoc or the result of the application of assoc on "jane"
> name-age-list? So it is an enhancement/extension to the basic syntactic
> form. If I expect that every part of the canonical form can have
> keywords, for example:
> 
> (x :1 (s-expr) a :2 (s-expr) b :3 (s-expr) c :4 (s-expr))
> 
> would I be off-the-mark?
> 
> Also, what other syntactic *extensions* are there to the basic (x a b
> c) form? New structures are easier to learn, I find, if they are
> anchored on what's there already.
> 
> Thanks again.
> Basi
> 
You seem to be winging it while exploring Lisp. There's nothing wrong 
with experimenting, but in the long run you'll probably be better off 
following a text that provides you with a clearer conceptual 
understanding of the fundamentals. Here are three free online books:
http://www.gigamonkeys.com/book/
http://psg.com/~dlamkins/sl/cover.html
http://www-2.cs.cmu.edu/afs/cs.cmu.edu/user/dst/www/LispBook/index.html

As you've mentioned above, when a list is evaluated, the first 
expression is interpreted as an operator--either a symbol or a lambda 
expression which directly specifies a function:
(+ 2 3) vs. ((lambda (x y) (+ x y)) 2 3)

If it is a symbol, then it must name a function, special operator, or macro:
http://www.lispworks.com/reference/HyperSpec/Body/03_abab.htm
Special operators and macros have different evaluation models than 
functions. I'll stick with functions here.

Lisp function definitions are extremely flexible. In addition to typical 
required parameters, a function may be defined to take optional, 
keyword, or an arbitrary number of parameters. These are specified in 
the function definition using "lambda list keywords" which start with 
'&'. For example,
(defun foo (a &optional b (c 3) &rest args &key (test #'eql)) ...

Here A is a required parameter. B and C are optional. C has a defined 
default value. If the corresponding args are not supplied B will be NIL 
and C will be 3. Any arguments passed beyond the first three will end up 
in the list ARGS, specified by the &REST keyword. This is how functions 
such as + or MAX can handle any number of arguments. Finally, following 
required and optional args, FOO may also take keyword arg :TEST, whose 
default value here is #'EQL, i.e., (FUNCTION EQL). When calling a 
function, the keyword precedes the value that will be associated with 
that keyword parameter.

These calls are equivalent:
(foo 1 2 3) and (foo 1 2 3 :test #'eql)
This specifies a different test:
(foo 1 2 3 :test #'equal)

In your example, ASSOC takes two required arguments and several possible 
keyword arguments:
http://www.lispworks.com/reference/HyperSpec/Body/f_assocc.htm
The keyword args tailor the specific behavior of ASSOC. By default, 
ASSOC (and most functions which take a :TEST argument) uses #'eql. 
Different string objects will not be EQL even if they contain the same 
sequence of characters:
(eql "pung" "pung") => NIL
(defvar *foo* "pung")
(defvar *bar* *foo*)
(eql *foo* *bar*) => T ;Same string object
Instead, use STRING= (case-sensitive) or STRING-EQUAL (case-insensitive):
(string= "pung" "pung") => T
(string-equal "Pung" "pung") => T

Putting it all together we see:
(assoc "jane" '(("joe" 20) ("alexandra" 25) ("kenny" 8) ("jane" 12))) => NIL
(assoc "jane" '(("joe" 20) ("alexandra" 25) ("kenny" 8) ("jane" 12)) 
:test #'string=) => ("jane" 12)
(assoc "Jane" '(("joe" 20) ("alexandra" 25) ("kenny" 8) ("jane" 12)) 
:test #'string=) => NIL
(assoc "Jane" '(("joe" 20) ("alexandra" 25) ("kenny" 8) ("jane" 12)) 
:test #'string-equal) => ("jane" 12)

Your hypothesis above is not correct:
 > If I expect that every part of the canonical form can have
 > keywords, for example:
 >
 > (x :1 (s-expr) a :2 (s-expr) b :3 (s-expr) c :4 (s-expr))
 >
Arguments must be passed just as parameters must be defined in DEFUN in 
this order:
-Required
-Optional
-Rest
-Keyword

Typically, not all 4 types of parameters are used simultaneously. It can 
be confusing if optional/keyword parameters are used together (see 
READ-FROM-STRING). Furthermore, it is inevitable but odd that keyword 
arguments also wind up in the catchall &REST list as well if both are used.

David Sletten
From: Pascal Bourguignon
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <87acrpa4cy.fsf@thalassa.informatimago.com>
"basi" <··········@yahoo.com> writes:

> Thanks again for the ideas.
> 
> 
> So far, I've beeing guided by a single syntatic form:
> 
> (x a b c)
> 
> where, if x can be interpreted as a function, the form is a function
> application, and if x is not a function, the form is a data list.
> 
> Given the statement:
> 
> (assoc "jane" name-age-list :TEST (FUNCTION STRING-EQUAL))
> 
> 
> I can't fit the highlighted materials into the canonical form (it
> certainly is not c in (x a b c)). What is :test a keyword of -- the
> function assoc or the result of the application of assoc on "jane"
> name-age-list? So it is an enhancement/extension to the basic syntactic
> form. 

Yes, you can fit it. Just ignore for a moment the colon.

This:
    (somefun "jane" name-age-list 'test (function string-equal))
would fit your frame, wouldn't it?

It's the same for all functions that accept variable number of
arguments (that are declared with &rest, &optional and &key):

    (assoc "jane" name-age-list 'test (function string-equal))

Now a keyword is a symbol like any other (only its value is itself,
but you can do that to any symbol:
    (setf test 'test)
)

    (assoc "jane" name-age-list :test (function string-equal))

So what we have here, is a list of 4 arguments. You could write it as:

    (let ((arg-2 :test) (arg-3 (function string-equal)))
       (assoc "jane" name-age-list arg-2 arg-3))

Or:

    (let ((args (list name-age-list :test (function string-equal))))
      (apply (function assoc) "jane" args))


Now, the point is that the lambda list in declaration of the function
or macro does not specify the way you pass arguments, it specifies the
way the function/macro will _parse_ the argument list it receives.

Syntactically, there's absolutely nothing special with keyword.
They're used only because they're practical for they're self
evaluated. But note that you can use any symbol for a key argument:
        
http://www.lispworks.com/reference/HyperSpec/Body/03_dad.htm


    Thus

        (defun foo (&key radix (type 'integer)) ...)

    means exactly the same as

        (defun foo (&key ((:radix radix)) ((:type type) 'integer)) ...)


You could write:

    (defun foo (&key (k v)) (print v))
    (foo 'k "value")

instead of:

    (defun foo (&key k) (print k))
    (foo :k "value")


> If I expect that every part of the canonical form can have
> keywords, for example:
> 
> (x :1 (s-expr) a :2 (s-expr) b :3 (s-expr) c :4 (s-expr))
> 
> would I be off-the-mark?

Yes.

 
> Also, what other syntactic *extensions* are there to the basic (x a b
> c) form? New structures are easier to learn, I find, if they are
> anchored on what's there already.

None.  The only "syntax" is in the special operators, and in the
macros, but ultimately the macros expand to special operators and
function calls.


-- 
__Pascal_Bourguignon__               _  Software patents are endangering
()  ASCII ribbon against html email (o_ the computer industry all around
/\  1962:DO20I=1.100                //\ the world http://lpf.ai.mit.edu/
    2001:my($f)=`fortune`;          V_/   http://petition.eurolinux.org/
From: Jeff
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <ZbNCd.75388$k25.38983@attbi_s53>
basi wrote:

> So far, I've beeing guided by a single syntatic form:
> 
> (x a b c)
> 
> where, if x can be interpreted as a function, the form is a function
> application, and if x is not a function, the form is a data list.

This is a common misconception. Try and think of it more like this:
they are all lists. There is no distinction between a functional form
and a data list. They are just lists. The difference lies in how you
want to use them.

For example:

(print '(+ 1 2)) => (+ 1 2)
(eval  '(+ 1 2)) => 3

In the above examples, (+ 1 2) is just a list containing a symbol and 2
fixnums. When passed to the PRINT function, the list is printed.
However, when sent to the EVAL function, EVAL expects that the first
symbol in the list is bound to a function:

(fboundp '+) => #<function + 2013494A>

It then executes this function, sending it the arguments which make up
the CDR of the list:

(cdr '(+ 1 2)) => (1 2).

> Given the statement:
> 
> (assoc "jane" name-age-list :TEST (FUNCTION STRING-EQUAL))
> 
> I can't fit the highlighted materials into the canonical form (it
> certainly is not c in (x a b c)). What is :test a keyword of -- the
> function assoc or the result of the application of assoc on "jane"
> name-age-list? So it is an enhancement/extension to the basic
syntactic
> form. 

Again, try to remember that there is nothing special about the symbol
:TEST, other than the fact that it is part of the KEYWORD package. The
: character is special (like '), in that it reads the next symbol, and
either gets it from or adds it to the KEYWORD package and then returns
it. Symbols in the KEYWORD package always evaluate to themselves. Try
it out:

:foo         => :FOO
:lisp-is-fun => :LISP-IS-FUN

Now, 

(assoc "jane" name-age-list :test (function string-equal))

is still just a list. It is a list consisting of a symbol, a string, a
symbol, another symbol (which happens to be in the KEYWORD package) and
finally another list.

Since this list is to be evaluated like our first example, the first
symbol is looked at to see if it is a function:

(fboundp 'assoc) => #<function ASSOC 20198172>

It is, so, now the arguments to the function are evaluated in order and
passed to the function found. (If it wasn't, an error would now occur).

"jane" is a string, which evaluates to itself. name-age-list is a
symbol which (hopefully) is bound as a value, and is returned. :test is
a symbol, which is slightly special since it is part of the KEYWORD
package; it always evaluates to itself. Finally we will evaluate the
last argument, which is itself a list.

Things get a little trickier under-the-hood here (FUNCTION is special),
and perhaps someone else can better explain this than I. For now, you
can just assume that it works relatively the same, and a pointer to a
function (string-equal) is returned.

I really wouldn't bother trying to delve into what's happening
under-the-hood right now, though. While it is fairly simple, it can
distract from the actual language. Just do it :)

IMO, the first step is truely coming to grips with the fact that there
is no "code" in Lisp. Just data. The data can be evaluated (treated
like code), but it is still just data. This is a key concept before
moving onto macros.

HTH,

Jeff M.

-- 
http://www.retrobyte.org
··············@gmail.com
From: basi
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <1104992232.278800.43860@z14g2000cwz.googlegroups.com>
It is the "unexpectedness" of the role of :TEST (FUNCTION STRING-EQUAL)
in the form

(assoc "jane" name-age-list :test (function string-equal))

that caught my attention. It appears to receive an input to which a
function is applied and a result is passed back. Nothing in the syntax
of

( x a b c d)

says that the meaning of this juxtaposition of elements is that you can
consider c and d as a sub-structure, thus: (x a b (c d)) and you can
pass the result of (x a b) to it and to which you can apply the
function d (or however it is done internally). There already are forms
that do that.

Thanks all for the explanations. 

Basi
From: Wade Humeniuk
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <WOeCd.50233$KO5.42481@clgrps13>
basi wrote:
> How do I convert the value of a string variable to a quoted symbol that
> I can use as key to a property list?
> 
> (defvar name-age-list '(joe 22 jane 21 john 12))
> 
> Now I'd like to say:
> 
> (getf name-age-list name)
> 
> where name is a string variable.
> 

It is a little annoying that one cannot specify a test function
for comparing keys for GETF.  You can use a function like this instead.
(Use STRING-EQUAL to compare (case-insensitive) a symbol and a string)

(defun my-getf (plist key &key (test #'eql))
   (let ((tail (member key plist :test test)))
     (if tail
         (values (second tail) t)
       (values nil nil))))

CL-USER 1 > (defvar name-age-list '(joe 22 jane 21 john 12))
NAME-AGE-LIST

CL-USER 2 > (my-getf name-age-list "joe" :test #'string-equal)
22
T

CL-USER 3 >

Wade
From: Wade Humeniuk
Subject: Re: Newbie Question: How do I convert the value of a string variable to a quoted symbol?
Date: 
Message-ID: <7VeCd.50234$KO5.21560@clgrps13>
Wade Humeniuk wrote:


> 
> It is a little annoying that one cannot specify a test function
> for comparing keys for GETF.  You can use a function like this instead.
> (Use STRING-EQUAL to compare (case-insensitive) a symbol and a string)
> 
> (defun my-getf (plist key &key (test #'eql))
>   (let ((tail (member key plist :test test)))
>     (if tail
>         (values (second tail) t)
>       (values nil nil))))
> 

Oops, this will not work when a value happens to be the same as one
of the keys.  This is better:

(defun my-getf (plist key &key (test #'eql))
   (loop for (pkey pvalue) on plist by #'cddr
     when (funcall test key pkey) return (values pvalue t)
     finally (return (values nil nil))))

Wade