From: ·············@gmail.com
Subject: Accessing plist's value from a defun
Date: 
Message-ID: <1184966742.782983.206900@g4g2000hsf.googlegroups.com>
Hi,

I have short data structures for which I would like to use plists.  My
question has to do with returning the plilst's value from a defun by
passing a symbol.  I have one solution (described below), but I wonder
if there is a more elegant way.  Here is my solution:

(defun get-var (sym)
  (getf  (:a 1 :b 2 :c 3) sym))

with a call

(get-var :a)

But this call exposes the internals of the data structure (the
colon).  I would really like to make a call (get-var a).  Is this
possible outside of a macro implentation?

Thanks,

Mirko

PS let's see how long it takes google to post this  :-)

From: Pillsy
Subject: Re: Accessing plist's value from a defun
Date: 
Message-ID: <1184970199.365640.58450@o61g2000hsh.googlegroups.com>
On Jul 20, 5:25 pm, ·············@gmail.com wrote:

> (defun get-var (sym)
>   (getf  (:a 1 :b 2 :c 3) sym))

[I think you're missing a QUOTE here.]

[...]
> But this call exposes the internals of the data structure (the
> colon).

It does?

(defun get-var (sym)
  (cdr (assoc sym '((:a . 1) (:b . 2) (:c . 3) :test #'eql)))

Using :keywords as, well, keywords is cool. That's what they're there
for, isn't it?

Cheers,
Pillsy
From: ·············@gmail.com
Subject: Re: Accessing plist's value from a defun
Date: 
Message-ID: <1184979859.928760.192680@n60g2000hse.googlegroups.com>
On Jul 20, 6:23 pm, Pillsy <·········@gmail.com> wrote:
> On Jul 20, 5:25 pm, ·············@gmail.com wrote:
>
> > (defun get-var (sym)
> >   (getf  (:a 1 :b 2 :c 3) sym))
>
> [I think you're missing a QUOTE here.]

Yep.  I mis-copied from my slime session.
>
> [...]
>
> > But this call exposes the internals of the data structure (the
> > colon).
>
> It does?
>
> (defun get-var (sym)
>   (cdr (assoc sym '((:a . 1) (:b . 2) (:c . 3) :test #'eql)))
>
> Using :keywords as, well, keywords is cool. That's what they're there
> for, isn't it?
>
Oh, I did not think of it that way.  That is one positive (and quite
acceptable) way of looking at it.

> Cheers,
> Pillsy

Thanks,

Mirko
From: Kent M Pitman
Subject: Re: Accessing plist's value from a defun
Date: 
Message-ID: <ur6n2brmu.fsf@nhplace.com>
·············@gmail.com writes:

> Hi,
> 
> I have short data structures for which I would like to use plists.  My
> question has to do with returning the plilst's value from a defun by
> passing a symbol.  I have one solution (described below), but I wonder
> if there is a more elegant way.  Here is my solution:
> 
> (defun get-var (sym)
>   (getf  (:a 1 :b 2 :c 3) sym))
> 
> with a call
> 
> (get-var :a)
> 
> But this call exposes the internals of the data structure (the
> colon).  I would really like to make a call (get-var a).  Is this
> possible outside of a macro implentation?

Well, keep in mind that there's an issue of efficiency here.

Using a known symbol means that you can use EQ, which is fast.
If you use any symbol with the same name, you are forced to do 
name comparison.  e.g.,

 (defvar *the-data* (list :a 1 :b 2 :c 3))

 (defun get-var (sym-name &optional default)
   (loop for (ind val) on *the-data* by #'cddr
         when (string-equal sym-name ind)
           return (values val t)
         finally (return (values default nil))))

However, the problem here is all those calls to STRING-EQUAL are 
(a) function calls at all [EQ tests are probably inlined] and 
(b) slow [have to iterate down an array looking for string match].
So all in all, that's a big performance hit for a bit of syntax
convenience.

To use 'a, you have to either agree that the internals will use the
same package name (which still reveals the package) or else do the
string comparison above.

The REAL question here is why you think you're revealing the internals.
The WHOLE POINT of keywords is to let you have interfaces that are
independent of package, since the keyword package is effectively a flat
namespace that you can access easily from any package.  It's vaguely like
a non-package packaged-symbol (implemented by a specially named package).
As such, it's a natural interface, and there's no reason you have to admit
that it's that internally.  If you wanted to change your internal 
representation, that is, if you had:

 (defvar *the-data* (list :a 1 :b 2 :c 3))

 (defun get-var (sym-key &optional default)
   (getf *the-data sym-key default))

and wanted to reimplement the list to contain packaged symbols, you could
still do something like:

 (defvar *the-data* (list 'a 1 'b 2 'c 3))

 (defun get-var (sym-key &optional default)
   (getf *the-data* (or (get sym-key 'var-key)
                        (setf (get sym-key 'var-key)
                              (intern (symbol-name sym-key) "KEYWORD")))
                    default))

(I'm not sure I recommend that particular approach for various reasons,
 but my point is that it illustrates a separation between the internal
 and external representation, and it shows that just because you advertise
 that keywords are used doesn't mean you're exposing implementation.  As
 long as you're committed to the external implementation, you can continue
 to support it.)

A final footnote: Packages exist because the space of names that
people need often collide.  I wouldn't necessarily run from packages
so quickly.  The other way to go is simply to make your get-var keys
relatively unique if there are a fixed number of them and then put
them in a package and USE-PACKAGE of that package in any clients, so
they can be named without package prefix, and yet shared across client
packages.
From: ·············@gmail.com
Subject: Re: Accessing plist's value from a defun
Date: 
Message-ID: <1184980118.260628.199980@w3g2000hsg.googlegroups.com>
On Jul 20, 7:08 pm, Kent M Pitman <······@nhplace.com> wrote:
> ·············@gmail.com writes:
> > Hi,
>
> > I have short data structures for which I would like to use plists.  My
> > question has to do with returning the plilst's value from a defun by
> > passing a symbol.  I have one solution (described below), but I wonder
> > if there is a more elegant way.  Here is my solution:
>
> > (defun get-var (sym)
> >   (getf  (:a 1 :b 2 :c 3) sym))
>
> > with a call
>
> > (get-var :a)
>
> > But this call exposes the internals of the data structure (the
> > colon).  I would really like to make a call (get-var a).  Is this
> > possible outside of a macro implentation?
>
> Well, keep in mind that there's an issue of efficiency here.
>
> Using a known symbol means that you can use EQ, which is fast.
> If you use any symbol with the same name, you are forced to do
> name comparison.  e.g.,
>
>  (defvar *the-data* (list :a 1 :b 2 :c 3))
>
>  (defun get-var (sym-name &optional default)
>    (loop for (ind val) on *the-data* by #'cddr
>          when (string-equal sym-name ind)
>            return (values val t)
>          finally (return (values default nil))))
>
> However, the problem here is all those calls to STRING-EQUAL are
> (a) function calls at all [EQ tests are probably inlined] and
> (b) slow [have to iterate down an array looking for string match].
> So all in all, that's a big performance hit for a bit of syntax
> convenience.
>
> To use 'a, you have to either agree that the internals will use the
> same package name (which still reveals the package) or else do the
> string comparison above.
>
> The REAL question here is why you think you're revealing the internals.

Because, as a new lisper, I failed to recognize my mechanism as
keyword arguments.  If I look at it as keywords, of-course, no
internals are revealed.


> The WHOLE POINT of keywords is to let you have interfaces that are
> independent of package, since the keyword package is effectively a flat
> namespace that you can access easily from any package.  It's vaguely like
> a non-package packaged-symbol (implemented by a specially named package).
> As such, it's a natural interface, and there's no reason you have to admit
> that it's that internally.  If you wanted to change your internal
> representation, that is, if you had:
>
>  (defvar *the-data* (list :a 1 :b 2 :c 3))
>
>  (defun get-var (sym-key &optional default)
>    (getf *the-data sym-key default))
>
> and wanted to reimplement the list to contain packaged symbols, you could
> still do something like:
>
>  (defvar *the-data* (list 'a 1 'b 2 'c 3))
>
>  (defun get-var (sym-key &optional default)
>    (getf *the-data* (or (get sym-key 'var-key)
>                         (setf (get sym-key 'var-key)
>                               (intern (symbol-name sym-key) "KEYWORD")))
>                     default))
>
> (I'm not sure I recommend that particular approach for various reasons,
>  but my point is that it illustrates a separation between the internal
>  and external representation, and it shows that just because you advertise
>  that keywords are used doesn't mean you're exposing implementation.  As
>  long as you're committed to the external implementation, you can continue
>  to support it.)
>
> A final footnote: Packages exist because the space of names that
> people need often collide.  I wouldn't necessarily run from packages
> so quickly.  The other way to go is simply to make your get-var keys
> relatively unique if there are a fixed number of them and then put
> them in a package and USE-PACKAGE of that package in any clients, so
> they can be named without package prefix, and yet shared across client
> packages.

Thanks Kent,

Mirko

PS.  I wonder if (some) people over 45 should be forced to learn
scheme, and not lisp :-)