From: Ken Tilton
Subject: Poster boy for optional and keyword args together?
Date: 
Message-ID: <47cee3f7$0$5617$607ed4bc@cv.net>
CL lets us use optional and keywords together, but it is a weird way to 
run a lambda list -- or is it? Can anyone point out a sensible (or any!) 
example of this in the CL standard library? Second-place prize for any 
ideas for when a custom API might want to torture users that way.

kenny

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius

From: Kaz Kylheku
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <8808467d-1b92-4e40-8f5b-193efc092aab@z17g2000hsg.googlegroups.com>
On Mar 5, 10:18 am, Ken Tilton <···········@optonline.net> wrote:
> CL lets us use optional and keywords together, but it is a weird way to
> run a lambda list -- or is it?

Not necessarily. The reason for the &OPTIONAL might be to maintain
backward compatibility with an old version of the function that had
fewer parameters. This will be called by legacy code which was written
when the keyword parameters didn't exist in that function.

Suppose that in such a situation, the function is now documented as if
it only had required parameters. Defaulting on the optionals is a
deprecated feature which may disappear, for the old code only. In this
situation, the programmers won't even know that some of the parameters
are optional, if they go strictly by the documentation, rather than
looking at how the function is actually defined.

So the annoying problem of ``geez, I have to add all of the optional
parameters just because I now need a keyword'' won't arise.
From: Edi Weitz
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <uzltd0za9.fsf@agharta.de>
On Wed, 05 Mar 2008 13:18:31 -0500, Ken Tilton <···········@optonline.net> wrote:

> CL lets us use optional and keywords together, but it is a weird way
> to run a lambda list -- or is it? Can anyone point out a sensible
> (or any!) example of this in the CL standard library?

If /any/ will do, take READ-FROM-STRING - see [3-0] here:

  http://www.faqs.org/faqs/lisp-faq/part3/

Sensible?  I don't think so.

> Second-place prize for any ideas for when a custom API might want to
> torture users that way.

See above.

Edi.

-- 

European Common Lisp Meeting, Amsterdam, April 19/20, 2008

  http://weitz.de/eclm2008/

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Ken Tilton
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <47cef8cc$0$15174$607ed4bc@cv.net>
Edi Weitz wrote:
> On Wed, 05 Mar 2008 13:18:31 -0500, Ken Tilton <···········@optonline.net> wrote:
> 
> 
>>CL lets us use optional and keywords together, but it is a weird way
>>to run a lambda list -- or is it? Can anyone point out a sensible
>>(or any!) example of this in the CL standard library?
> 
> 
> If /any/ will do, take READ-FROM-STRING - see [3-0] here:
> 
>   http://www.faqs.org/faqs/lisp-faq/part3/

Ah, I knew there was one (cuz of course I get nailed by it regularly) 
but I could not place it, checked READ and did not see a problem.

Thx!

> 
> Sensible?  I don't think so.

As someone guessed on the Arc forum, it might be evidence of evolution, 
with the keyword args as afterthoughts and importantly a large installed 
base of non-keyword usage no one would want to revisit.

Speaking of which, if anyone looking at my code marvels at the 
horridness of certain names like install-part-ex, it means (a) I have 
been thru something similar with my own API and wanted a fresh start and 
(b) I am making fun of microsoft, cux that is what they do in the same 
situation, append "EX" to a name.

kenny

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Richard M Kreuter
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <87r6eo3mvc.fsf@progn.net>
Ken Tilton <···········@optonline.net> writes:

> As someone guessed on the Arc forum, it might be evidence of
> evolution, with the keyword args as afterthoughts and importantly a
> large installed base of non-keyword usage no one would want to
> revisit.

AFAIR, most cases of &OPTIONAL and &KEY in the same lambda list are
operators where two kinds of argument conventions are both
applicable. For example, input functions take the optional arguments
EOF-ERROR-P, EOF-VALUE, and most functions applicable to strings take
START and END keywords; put these together, and you get most of
READ-FROM-STRING's arglist.  Similarly, most character output
operations take an optional output stream, and so WRITE-LINE,
WRITE-STRING take both an optional output stream and START and END
keywords.  PARSE-NAMESTRING and WITH-OUTPUT-TO-STRING also have
&OPTIONAL and &KEY in the same lambda list; again, the keyword
arguments follow conventions used elsewhere.

--
RmK
From: Ken Tilton
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <47cf0c33$0$15197$607ed4bc@cv.net>
Richard M Kreuter wrote:
> Ken Tilton <···········@optonline.net> writes:
> 
> 
>>As someone guessed on the Arc forum, it might be evidence of
>>evolution, with the keyword args as afterthoughts and importantly a
>>large installed base of non-keyword usage no one would want to
>>revisit.
> 
> 
> AFAIR, most cases of &OPTIONAL and &KEY in the same lambda list are
> operators where two kinds of argument conventions are both
> applicable. For example, input functions take the optional arguments
> EOF-ERROR-P, EOF-VALUE, and most functions applicable to strings take
> START and END keywords; put these together, and you get most of
> READ-FROM-STRING's arglist.

Ah, that makes a lot of sense. Thx.

kenny

   Similarly, most character output
> operations take an optional output stream, and so WRITE-LINE,
> WRITE-STRING take both an optional output stream and START and END
> keywords.  PARSE-NAMESTRING and WITH-OUTPUT-TO-STRING also have
> &OPTIONAL and &KEY in the same lambda list; again, the keyword
> arguments follow conventions used elsewhere.
> 
> --
> RmK

-- 
http://smuglispweeny.blogspot.com/
http://www.theoryyalgebra.com/

"In the morning, hear the Way;
  in the evening, die content!"
                     -- Confucius
From: Steven M. Haflich
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <47D2556D.50103@alum.mit.edu>
Richard M Kreuter wrote:

> AFAIR, most cases of &OPTIONAL and &KEY in the same lambda list are
 > ...

The learned commentators have all missed the obvious case of a macro (or 
friends) lambda list which uses &optional and &key within different 
lambda sublists.  This would not run into the usual hazards cited with 
the combination in the same sublist.  I can't think of any existing 
examples, but if I had sufficient motivation (e.g. a bar bet) I could 
probably come up with one.
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <rem-2008mar08-005@yahoo.com>
>> From: Ken Tilton <···········@optonline.net>
>> As someone guessed on the Arc forum, it might be evidence of
>> evolution, with the keyword args as afterthoughts and importantly a
>> large installed base of non-keyword usage no one would want to
>> revisit.

> From: Richard M Kreuter <·······@progn.net>
> AFAIR, most cases of &OPTIONAL and &KEY in the same lambda list are
> operators where two kinds of argument conventions are both
> applicable. For example, input functions take the optional arguments
> EOF-ERROR-P, EOF-VALUE, and most functions applicable to strings take
> START and END keywords; put these together, and you get most of
> READ-FROM-STRING's arglist.  Similarly, most character output
> operations take an optional output stream, and so WRITE-LINE,
> WRITE-STRING take both an optional output stream and START and END
> keywords.  PARSE-NAMESTRING and WITH-OUTPUT-TO-STRING also have
> &OPTIONAL and &KEY in the same lambda list; again, the keyword
> arguments follow conventions used elsewhere.

Ah, this is the best explanation I've ever seen of this.
The above paragraph should be in a FAQ.

In a way, this is vaguely similar to Java's interfaces, whereby
some class might satisfy two different interfaces, so that it can
be used in two different kinds of automated contexts, so it has to
provide all the required methods for each of the interfaces even if
they follow somewhat conflicting conventions.

The difference of course is that interfaces are satisfied by OOP
classes, whereby compile-time polymorphism chooses which method to
call (and in many cases the methods have different names anyway so
there's no syntactical conflict to begin with, merely two different
names for [almost] exactly the same D/P task), and each method has
exactly the parameters needed for the corresponding interface,
whereas in these cases of legacy Lisp we have functions not methods
(not even generic functions) so we can't overload the name, we can
only process the lambda list sequentially and stop when there are
no more args, so the programmer must specify the args for
interface#1 (which uses optional arguments) before the args for
interface#2 (which uses keyword arguments).

Whether my analogy with Java interfaces is of any value to most
readers of Richard's explanation, or not, I can't estimate, so I
won't petition for my analogy to include Richard's explanation in
the FAQ. If the basic idea of my addendum would be of value, maybe
KMP can rewrite it to be more newbie-friendly?
From: Kent M Pitman
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <uabl7ofid.fsf@nhplace.com>
·······@yahoo.com (Robert Maas, see http://tinyurl.com/uh3t) writes:

> >> From: Ken Tilton <···········@optonline.net>
> >> As someone guessed on the Arc forum, it might be evidence of
> >> evolution, with the keyword args as afterthoughts and importantly a
> >> large installed base of non-keyword usage no one would want to
> >> revisit.
> 
> > From: Richard M Kreuter <·······@progn.net>
> > AFAIR, most cases of &OPTIONAL and &KEY in the same lambda list are
> > operators where two kinds of argument conventions are both
> > applicable. For example, input functions take the optional arguments
> > EOF-ERROR-P, EOF-VALUE, and most functions applicable to strings take
> > START and END keywords; put these together, and you get most of
> > READ-FROM-STRING's arglist.  Similarly, most character output
> > operations take an optional output stream, and so WRITE-LINE,
> > WRITE-STRING take both an optional output stream and START and END
> > keywords.  PARSE-NAMESTRING and WITH-OUTPUT-TO-STRING also have
> > &OPTIONAL and &KEY in the same lambda list; again, the keyword
> > arguments follow conventions used elsewhere.
> 
> Ah, this is the best explanation I've ever seen of this.
> The above paragraph should be in a FAQ.
> 
> In a way, this is vaguely similar to Java's interfaces, whereby
> some class might satisfy two different interfaces, so that it can
> be used in two different kinds of automated contexts, so it has to
> provide all the required methods for each of the interfaces even if
> they follow somewhat conflicting conventions.

Well, the complete analogy of "push comes to shove" here would be if
the interfaces require two unrelated pieces of information to be
passed along the same type signature.

The problem is that every spec, by its nature, says that the
information will be passed in SOME way.  And anytime information is passed
within the space that other info is passed, there's the potential  to
have paradigms trip over one another.  So if key args were passed in a 
different channel that positional args, that would work.  But they aren't.

In the Java interface example, the presence of a name with a type
signature is the way.  In CL's optionals, it's the presence of an
object in a certain arg position.  If you think "multiple inheritance"
can happen, then it's possible to create a collision, where
independent choice in two parents suddenly require after-the-fact
consolidation.

Back to Java (which I haven't programmed in for some years, btw, so
pardon me if something has changed), if a class wants to satisfy two
different interfaces which have the same method but offer it in
different ways, one would suppose there should be a syntax for saying
"i'll supply this method for anyone viewing me as an x, but i don't
intend to carry on the convention myself. this would allow foobar to
inherit a requirement for a blah method from interface foo and a
requirement for a blah method from interface bar, and yet require
anyone who inherits from it to not be ablet to call the blah method
without saying if the call is meant to access their foo-blah method or
their bar-blah method.")

The absence of such a facility (I'm assuming there is still such an
absence--let me know if this is fixed) makes interface clashes quite
severe.  Fortunately, people don't write so many interfaces that it
comes up a huge amount.  

In CL, this should have been resolved in the language design by making
keywords not be in the keyword package; you can do this yourself with
the complicated syntax for &key, but it isn't done by default, and
most people don't do it voluntarily because they think it must be bad
or they think it will look bad, even though it's safer.  It allows you
to say that the keyword foo:blah and bar:blah are both permissible.
But you have to plan it in.  If everyone did plan it in, clashes of
keywords wouldn't happen.

(Analogy relating to packaged keywords: It's not done for the same
reason most people look down on the linguistic constructions "y'all"
(or, in NY, "yous") as if they were substandard, rather than an
important technological fix to a long-standing problem... it just
takes some getting used to, and it offends people while the getting
used to is happening. So it doesn't happen.)

> The difference of course is that interfaces are satisfied by OOP
> classes, whereby compile-time polymorphism chooses which method to
> call (and in many cases the methods have different names anyway so
> there's no syntactical conflict to begin with, merely two different
> names for [almost] exactly the same D/P task), and each method has
> exactly the parameters needed for the corresponding interface,
> whereas in these cases of legacy Lisp we have functions not methods
> (not even generic functions) so we can't overload the name, we can
> only process the lambda list sequentially and stop when there are
> no more args, so the programmer must specify the args for
> interface#1 (which uses optional arguments) before the args for
> interface#2 (which uses keyword arguments).

The analogy has theoretical but not practical relevance to CL's arglists
only in the sense that the conceptual parents in the READ-FROM-STRING
case occur at design time.  Since READ-FROM-STRING didn't have to choose
its arg convention as it did, and could just as well have chosen to use
  &key eof-error-p eof-value
rather than
  &optional eof-error-p eof-value
the problem could have been avoided in that case.  (Although people are right
to point out that whenever the number of optional arguments is an even number,
this problem is potentially surely going to occur.)

Viewing it as if it were an interface issue is as if to say there was no
opportunity for the designers of the function to do otherwise.  Had there
been some 

 (define-function-as-if-it-were-a-class-inheriting-stuff read-from-string
     ;; These would be the function "classes" it inherits from, I guess:
     (read sequence-function))

then we could blame the combination, as you say, on something in the paradigm.

> Whether my analogy with Java interfaces is of any value to most
> readers of Richard's explanation, or not, I can't estimate, so I
> won't petition for my analogy to include Richard's explanation in
> the FAQ. If the basic idea of my addendum would be of value, maybe
> KMP can rewrite it to be more newbie-friendly?

I doubt I'm the only one who's a candidate to write such a thing.
Certainly this post is no model of newbie-friendly, since I'm alluding
for brevity to many issues probably only known to experienced
users. Sorry about that. But I'll decline the task you suggest, at
least at this time, on grounds that I don't think it's the way to
present it.

As you probably know, I tend to view such things by analogies with
other systems, too, but I might prefer the emacs command set as my
example.  It has a lot of regularity, but the regularity is not
globally regular, only locally so.  There are rivers of regularity
that are punctuated routinely, though not predictably, by unresolvable
clashes between competing conventions.
From: Lars Rune Nøstdal
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <47e51239$0$28889$c83e3ef6@nn1-read.tele2.net>
On Wed, 05 Mar 2008 13:18:31 -0500, Ken Tilton wrote:

> CL lets us use optional and keywords together, but it is a weird way to
> run a lambda list -- or is it? Can anyone point out a sensible (or any!)
> example of this in the CL standard library? Second-place prize for any
> ideas for when a custom API might want to torture users that way.
> 
> kenny

I've come up with a case where doing this _seems_ to make some sense.


(defun value-of (selector &optional callback 
                 &key (auto-sync-p t) (test #'equal))
  (if (eq callback t)
      ", the stuff after &KEY _is_ interesting (this happens 45% of the 
time)."
      (if callback
          ", the stuff after &KEY _is_ interesting (this happens 10% of 
the time)."
          ", the stuff after &KEY is _never_ interesting (this happens 
45% of the time).")))


#|
CL-USER> (value-of :something)
", the stuff after &KEY is _never_ interesting (this happens 45% of the 
time)."
CL-USER> (value-of :something t)
", the stuff after &KEY _is_ interesting (this happens 45% of the time)."
CL-USER> (value-of :something (lambda (result)))
", the stuff after &KEY _is_ interesting (this happens 10% of the time)."
|#


#|
What I mean by the % stuff is how often the function is used in that
particular way. Since the stuff after &KEY isn't interesting unless
something is supplied for CALLBACK, why should the user have to say
":CALLBACK T" 45% of the time instead of just saying "T"?


Having CALLBACK as a &KEY would mean:

  * 45% of the time the user has to say ":CALLBACK T" instead of "T"

  * 10% of the time the user has to say ":CALLBACK (LAMBDA ())"
    instead of just "(LAMBDA ())"

  * The user will wonder whether there is any point in changing
    AUTO-SYNC-P or TEST without touching CALLBACK (when it is NIL).


..while..

  * Having it &OPTIONAL forces the user to supply something for CALLBACK
    to "reach" the &KEY stuff.  
|#


..or?

-- 
Lars Rune Nøstdal
http://nostdal.org/
From: Lars Rune Nøstdal
Subject: Re: Poster boy for optional and keyword args together?
Date: 
Message-ID: <47e51335$0$28889$c83e3ef6@nn1-read.tele2.net>
 Sat, 22 Mar 2008 14:05:45 +0000, Lars Rune Nøstdal wrote:

> On Wed, 05 Mar 2008 13:18:31 -0500, Ken Tilton wrote:
> 
>> CL lets us use optional and keywords together, but it is a weird way to
>> run a lambda list -- or is it? Can anyone point out a sensible (or
>> any!) example of this in the CL standard library? Second-place prize
>> for any ideas for when a custom API might want to torture users that
>> way.
>> 
>> kenny
> 
> I've come up with a case where doing this _seems_ to make some sense.

*snip* .. FFS .. i hate these friggin nntp/news programs ..

gonna try again:


(defun value-of (selector &optional callback 
                 &key (auto-sync-p t) (test #'equal))
  (if (eq callback t)
      ", the stuff after &KEY _is_ interesting (this happens 45% of the time)."
      (if callback
          ", the stuff after &KEY _is_ interesting (this happens 10% of the time)."
          ", the stuff after &KEY is _never_ interesting (this happens 45% of the time).")))


#|
CL-USER> (value-of :something)
", the stuff after &KEY is _never_ interesting (this happens 45% of the time)."
CL-USER> (value-of :something t)
", the stuff after &KEY _is_ interesting (this happens 45% of the time)."
CL-USER> (value-of :something (lambda (result)))
", the stuff after &KEY _is_ interesting (this happens 10% of the time)."
|#


#|
What I mean by the % stuff is how often the function is used in that
particular way. Since the stuff after &KEY isn't interesting unless
something is supplied for CALLBACK, why should the user have to say
":CALLBACK T" 45% of the time instead of just saying "T"?


Having CALLBACK as a &KEY would mean:

  * 45% of the time the user has to say ":CALLBACK T" instead of "T"

  * 10% of the time the user has to say ":CALLBACK (LAMBDA ())"
    instead of just "(LAMBDA ())"

  * The user will wonder whether there is any point in changing
    AUTO-SYNC-P or TEST without touching CALLBACK (when it is NIL).


..while..

  * Having it &OPTIONAL forces the user to supply something for CALLBACK
    to "reach" the &KEY stuff.  
|#


-- 
Lars Rune Nøstdal
http://nostdal.org/