Re: Poster boy for optional and keyword args together?
- From: Kent M Pitman <pitman@xxxxxxxxxxx>
- Date: 09 Mar 2008 15:37:30 -0400
rem642b@xxxxxxxxx (Robert Maas, see http://tinyurl.com/uh3t) writes:
From: Ken Tilton <kennytil...@xxxxxxxxxxxxx>
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 <kreu...@xxxxxxxxx>
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.
.
- References:
- Poster boy for optional and keyword args together?
- From: Ken Tilton
- Re: Poster boy for optional and keyword args together?
- From: Edi Weitz
- Re: Poster boy for optional and keyword args together?
- From: Ken Tilton
- Re: Poster boy for optional and keyword args together?
- From: Richard M Kreuter
- Re: Poster boy for optional and keyword args together?
- From: Robert Maas, see http://tinyurl.com/uh3t
- Poster boy for optional and keyword args together?
- Prev by Date: Re: LISA
- Next by Date: Re: strange behavior when using nconc
- Previous by thread: Re: Poster boy for optional and keyword args together?
- Next by thread: Re: Poster boy for optional and keyword args together?
- Index(es):
Relevant Pages
|