Many other programming languages have statements and expressions, but Common Lisp has not made that distinction quite as explicit, although the value of a lot of forms are not usually used. Still, when we turn to the conditionals, it is somewhat different. Common Lisp the Language (CLtL) introduces the conditionals by talking about cond being the primary Lisp conditional, but if being like if-then-else in other languages, it would be covered first. However, there is a significant difference that has made me think that this is not accurate. Lisp's if returns a value. The ifs of other programming languages are generally _statements_ that do not return a value. If they have a conditional that can return a value, it is usually very different from the usual if statement for one significant reason: It has to have a value for both the consequent and the alternate, while the traditional if forms have an optional alternate. In Common Lisp, an else-less if form works because nil is useful value, but this is not a good thing. The if form has some properties of both statement and expression.
One question is whether a form has an implicit progn. This is a clue that it is has statement nature. So if it does not have an implicit progn, but only one value-returning form, this is a clue that it is an expression.
One question is whether a form should be used for its value or not. The forms when and unless should clearly not be used for their value. They also have implicit progns. There is no point in a progn unless you have other forms satisfying another clue to statement nature: their value(s) are discarded and ignored.
The if form is both statement and expression, and it is neither, because it does not quite have either nature. As an expression, it is not a good idea to leave out the alternate, even if you want that value to be nil. As a statement, adding explicit progns can be somewhat annoying.
The general conditional cond also has some of this dual nature. It has implicit progn, but returns values. Leaving out the final branch is a known source of annoying bugs, whether it be the unexamined fall-through case or an unexpected nil return value. Still, cond is the smartest of the conditional forms I have seen in any number of programming languages: a long chain of "else if" looks like whoever designed that excuse for a language forgot to design it for more than either-or style cases. Also, the verbosity of the conditionals in inferior languages in this style gets in the way of the task at hand, so cond is the definite winner.
The specialized conditionals case (with ccase and ecase) and typecase (with ctypecase and etypecase) cover common comparison cases that are easy to optimize and whose similarities would be totally obscured by a cond. E.g.,, a test for (<= 0 x 99) may be significantly more expensive than a test for the type (integer 0 99). A case "dispatching" on a set of characters may be implemented as a very fast table lookup that would otherwise be hard to do as efficiently.
The one-branch conditionals when and unless might seem to be redundant, but they communicate something that neither if nor cond can communicate: A promise that there will not be any other alternatives, or that if its condition is not met, nothing needs to be done. If it is merely an accident that there is one branch now, which might change in the future, do not use when or unless, because you are lying to yourself. Both when and unless communicate an expectation. I think when and unless should be used such that the condition is expected to be true, in which case when evaluates the body and unless does not. In other words, unless says that when the condition is false, that is an exceptional thing, but when says that when the condition is false, that is nothing special. That is, you should expect both (when (not/null ...)) and (unless (not/null ...)).
There are no serious coding standards that apply to the rich set of Common Lisp conditionals. I would, however, appeal to those who seek to use them all to their fullest not use if as a statement, but always as an expression with both branches specified. Even if the alternate branch is nil, specify it explicitly. (This may be read to imply that I think it was a mistake to make the alternate branch optional, but it was probably made optional because if looks so much like programming languages that had a statement-only if.) While other programming languages may have an if statement, e.g., C, Common Lisp's if is much closer in meaning to C's conditional expression, ?:, which is usually not abused to chain a whole lot of them together as you lose track of which condition must hold to reach each expression. In that case, use cond or one of the case forms as an expression, meaning: without using the option to include statements with the implicit progn in each body form, and ensure that you specify the value when none of the conditions or cases are met, even if it is nil.
For the conditional statement, I would likewise appeal to those who seek to use the most of te language to use when and unless when there is only one known branch, but not use them for their value. However, there may be an implicit alternate branch even when using when or unless: They may throw or return or signal an error. I favor using unless for this, as explained above about unless being somewhat exceptional in nature. When there are more than one branch in the conditional statement, use cond. In the statement capacity, I favor _not_ terminating it with a final alternate branch unless that branch includes some statements of its own, so as not to confuse it with an expression. A final alternate branch like (t nil) tells me the value of the whole cond is used for something and thus I need to look for the return value for each condition. To make this abundantly clear, it may be prudent in a complex form to use values forms explicitly, even if returning only a single value, but this, too, may decrease readability if it is not obviously seen as useful.
Whareas most programming language have a single conditional statement and, if you are lucky, maybe a conditional expression, Common Lisp once again proves itself as the language that communicates with programmers and captures their intent through the choice of which of several forms to use. Using only one form for a slew of different purposes is the same kind of impoverished literary style that you find in bad authors, but if you come from a language that has only one conditional, embrace the set of options you have in this new language. It may even be true that in the natural language of the programmer, even be it English, the set of conditional expressions fit the single if-then-else form of programming languages (the writing styles of many programmers may indicate that they would appreciate a limited vocabulary so as not to feel alienated), but then using Common Lisp would be an opportunity to improve both styles.
/// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
Just a few (minor) remarks added to a very insightful analysis.
On Wed, 21 Nov 2001 02:45:42 GMT, Erik Naggum <e...@naggum.net> said:
[...]
EN> Even if the alternate branch is EN> nil, specify it explicitly.
Precisely---if you omit the `else' part, you are not really returning a value (even though the language is willing to make up for it), so perhaps you want to use WHEN (or UNLESS).
EN> (This may be read to imply EN> that I think it was a mistake to make the alternate branch EN> optional, but it was probably made optional because if EN> looks so much like programming languages that had a EN> statement-only if.)
Maybe existing programs also had to be accommodated which had been written before the introduction of WHEN and UNLESS and which omitted the `else' part?
EN> While other programming languages may EN> have an if statement, e.g., C, Common Lisp's if is much EN> closer in meaning to C's conditional expression, ?:, which EN> is usually not abused to chain a whole lot of them together
Or, if we include rarely used languages, isn't Common Lisp's IF in fact closest to Algol's *if*? (As C's ?: cannot have the `else' part omitted. Though I admit my memory fails me as to what happens in e.g. ``i := if b then j''---a compile-time error?) In fact, off the top of my head I should think that Algol 60 was the first language where *if* names a conditional _expression_, a significant difference from a conditional statement viewed essentially as an abstraction hiding a couple of goto's. (I am primarily talking about the use of the _name_ `if'; otherwise, I don't know if Algol or Lisp was the first to have a conditional expression, as they were developed roughly at the same time, but Lisp had only COND in the beginning.)
One couldn't say, though, that Algol's *if* was not `abused in chains' (if I may borrow the expression). By the way, there are programmers who (in languages with C-like syntax) do not write else-if chains, but rather stuff like
if (FOO1) BAR1; if (FOO2) BAR2;
etc. where FOO1 and FOO2 will not be true at the same time. (Not that I like this too much.)
Just a few (minor) remarks added to a very insightful analysis.
On Wed, 21 Nov 2001 02:45:42 GMT, Erik Naggum <e...@naggum.net> said:
[...]
EN> Even if the alternate branch is EN> nil, specify it explicitly.
Precisely---if you omit the `else' part, you are not really returning a value (even though the language is willing to make up for it), so perhaps you want to use WHEN (or UNLESS).
EN> (This may be read to imply EN> that I think it was a mistake to make the alternate branch EN> optional, but it was probably made optional because if EN> looks so much like programming languages that had a EN> statement-only if.)
Maybe existing programs also had to be accommodated which had been written before the introduction of WHEN and UNLESS and which omitted the `else' part?
EN> While other programming languages may EN> have an if statement, e.g., C, Common Lisp's if is much EN> closer in meaning to C's conditional expression, ?:, which EN> is usually not abused to chain a whole lot of them together
Or, if we include rarely used languages, isn't Common Lisp's IF in fact closest to Algol's *if*? (As C's ?: cannot have the `else' part omitted. Though I admit my memory fails me as to what happens in e.g. ``i := if b then j''---a compile-time error?) In fact, off the top of my head I should think that Algol 60 was the first language where *if* names a conditional _expression_, a significant difference from a conditional statement viewed essentially as an abstraction hiding a couple of goto's. (I am primarily talking about the use of the _name_ `if'; otherwise, I don't know if Algol or Lisp was the first to have a conditional expression, as they were developed roughly at the same time, but Lisp had only COND in the beginning.)
One couldn't say, though, that Algol's *if* was not `abused in chains' (if I may borrow the expression). By the way, there are programmers who (in languages with C-like syntax) do not write else-if chains, but rather stuff like
if (FOO1) BAR1; if (FOO2) BAR2;
etc. where FOO1 and FOO2 will not be true at the same time. (Not that I like this too much.)
Just a few (minor) remarks added to a very insightful analysis.
On Wed, 21 Nov 2001 02:45:42 GMT, Erik Naggum <e...@naggum.net> said:
[...]
EN> Even if the alternate branch is EN> nil, specify it explicitly.
Precisely---if you omit the `else' part, you are not really returning a value (even though the language is willing to make up for it), so perhaps you want to use WHEN (or UNLESS).
EN> (This may be read to imply EN> that I think it was a mistake to make the alternate branch EN> optional, but it was probably made optional because if EN> looks so much like programming languages that had a EN> statement-only if.)
Maybe existing programs also had to be accommodated which had been written before the introduction of WHEN and UNLESS and which omitted the `else' part?
EN> While other programming languages may EN> have an if statement, e.g., C, Common Lisp's if is much EN> closer in meaning to C's conditional expression, ?:, which EN> is usually not abused to chain a whole lot of them together
Or, if we include rarely used languages, isn't Common Lisp's IF in fact closest to Algol's *if*? (As C's ?: cannot have the `else' part omitted. Though I admit my memory fails me as to what happens in e.g. ``i := if b then j''---a compile-time error?) In fact, off the top of my head I should think that Algol 60 was the first language where *if* names a conditional _expression_, a significant difference from a conditional statement viewed essentially as an abstraction hiding a couple of goto's. (I am primarily talking about the use of the _name_ `if'; otherwise, I don't know if Algol or Lisp was the first to have a conditional expression, as they were developed roughly at the same time, but Lisp had only COND in the beginning.)
One couldn't say, though, that Algol's *if* was not `abused in chains' (if I may borrow the expression). By the way, there are programmers who (in languages with C-like syntax) do not write else-if chains, but rather stuff like
if (FOO1) BAR1; if (FOO2) BAR2;
etc. where FOO1 and FOO2 will not be true at the same time. (Not that I like this too much.)
Erik Naggum <e...@naggum.net> writes: > made me think that this is not accurate. Lisp's if returns a value. The > ifs of other programming languages are generally _statements_ that do not > return a value. If they have a conditional that can return a value, it > is usually very different from the usual if statement for one significant > reason: It has to have a value for both the consequent and the alternate, > while the traditional if forms have an optional alternate.
Is the latter true? I haven't used SIMULA for 16 years so I can't really remember if the SIMULA "expression IF" worked that way, but certainly the perl "expression if" does not work that way:
ev@wallace:~ % perl -we 'print "yes\n" if (1);' yes
(perl's _unless_, which can't be mentioned often enough since some people think lisp is the only language with such an animal, can of course also be used as a "expression unless").
> One question is whether a form should be used for its value or not. The > forms when and unless should clearly not be used for their value.
I strongly disagree. I think when and unless can be perfectly well used for their value. In general I think the Common Lisp programmer should be free to use any form for it's value whenever that value can be given a meaningful interpretation. -- (espen)
Espen Vestre <espen@*do-not-spam-me*.vestre.net> writes: > Erik Naggum <e...@naggum.net> writes:
> > One question is whether a form should be used for its value or > > not. The forms when and unless should clearly not be used for > > their value.
> I strongly disagree. I think when and unless can be perfectly well > used for their value. In general I think the Common Lisp programmer > should be free to use any form for it's value whenever that value > can be given a meaningful interpretation.
The point is not about legality or conformity, but about the communication of intent. Lots of things in Common Lisp can be done in many different ways and since the programs are written more for humans than for computers, the programmer should choose the way that most clearly communicates the intent (just like some people _do_ quote nil and keywords).
If you use when or unless for value, you rely on the fact that if the test fails they will return nil and you will use it as a meaningful value. But this value does not appear anywhere and does not make this explicit. Attention to detail at this level is what makes programs beautiful and readable and approachable by non-experts in Common Lisp.
> > > One question is whether a form should be used for its value or > > > not. The forms when and unless should clearly not be used for > > > their value.
> > I strongly disagree. I think when and unless can be perfectly well > > used for their value. In general I think the Common Lisp programmer > > should be free to use any form for it's value whenever that value > > can be given a meaningful interpretation.
> The point is not about legality or conformity, but about the > communication of intent. Lots of things in Common Lisp can be done in > many different ways and since the programs are written more for humans > than for computers, the programmer should choose the way that most > clearly communicates the intent (just like some people _do_ quote nil > and keywords).
But intent is the product of a set of style rules plus a set of actions under those rules. We have no style rule for determining whether the number 42 will be returned; that is done by using a construct from the use of which it is ambiguous as to whether it returns 42 or not, plus actually reading the code and determining what it will do. Yet such code is not blocked from clearly communicating whether 42 is returned.
Nor is it the burden of every programmer to exhaust every possible cue with an associative nuance, so that if two constructs compute the same value, there must be a difference in nuance between the two. It is a legitimate style decision to simply say "I use WHEN if there is no alternative, and UNLESS if there is no consequent." It is also a legitimate style decision to code otherwise. What matters more is to know the convention than for us all to have the same convention, because on the latter point we will not agree and we will war endlessly.
And certainly no one's style rules should keep him/her from seeing the possibility that others use different rules. Style rules are merely a cue to help manage the probability of various choices being made. If one blindly infers that they assert actual meaning, one will find oneself substantially and rightfully hampered in the ability to debug code.
> If you use when or unless for value, you rely on the fact that if the > test fails they will return nil and you will use it as a meaningful > value. But this value does not appear anywhere and does not make this > explicit. Attention to detail at this level is what makes programs > beautiful and readable and approachable by non-experts in Common Lisp.
I believe your case would be better made by asserting "I prefer the style rule that says: ..." Because that leaves room for others to choose their own path without argument. Asserting a style rule as if it were true, or canonical, or right, or otherwise uniquely determined invites opposition to what should be a common sense statement if presented properly. Style rules assert a possible and useful axis of consistency from among many that are available to freely suggest.
Personally, my preferred style rule says not to omit values when they are possible to provide and when a value is required. So I might use (IF x y) when an IF is not value-producing but (IF x y NIL) if the IF is value producing. But that doesn't mean that when I use (WHEN x y) I am saying there is no value. I choose between IF and WHEN on the basis of whether I think there is a reasonable chance I might want to add an alternative. If I do, I sometimes prefer IF, whether or nto I am actually supplying an alternative at the time. When I use WHEN, I usually either mean "this supplies no value" or "this supplies a value which is either a meaningful true value, or a subordinate false value". (Think of the vowel schwa in English.) So, for example, I might commonly use:
(defun get-property (x y) (when (symbolp x) (get x y)))
In such a place, I intend this to be read "the value of GET-PROPERTY is the result of (GET X Y) when X is a symbol, but it really has no properties otherwise". This is computationally the same as, but connotationally different than:
which says "I mean to define that the value of the Y property of a symbol X is stored on its plist when X is a symbol, and is NIL otherwise." The latter gives, to me, a stronger sense that I have thought through the consequences of yielding NIL and that I think this is the right value to return, while the former gives the sense that I am merely saying "there really is no property list for non-symbols, and you'll have to assume a default". These are highly subtle matters, but that's what style rules do: convey subtlety. And to understand that subtlety, one does not consult a central table of uniquely determined subtlety, one consults the programmer (or programmer team, when programmers happen to be of pre-agreed or pre-ordained like mind) and then the code.
And, personally, I would rather convey an abstract subtlely, irrelevant to the computation per se, but very relevant to the programmer, such as the one shown above ("non-symbols don't have plists" vs "it works for the values of non-symbol properties to be assumed to be NIL, the former being a statement about the symbol, the latter a statement about the use of the symbol's properties) than a concrete cue such as "this will get used for value" or "this will not get used for value", because it conveys information about how I _think_ about the program, rather than merely information about how I perform the rather mundane act of translating my thoughts into code.
But I emphasize that this is merely a choice on my part, and that it will not by any absolute metric be possible to show it better or worse than your choice.
To understand a wise style choice, one must understand wisdom. Wisdom is not a "what" question ("what do I do?", which almost precludes choice) but a "why" question ("why would I do these various things?" and then a willful selection among consequences in a space that is most commonly not subject to linear ordering).
>> made me think that this is not accurate. Lisp's if returns a value. The >> ifs of other programming languages are generally _statements_ that do not >> return a value. If they have a conditional that can return a value, it >> is usually very different from the usual if statement for one significant >> reason: It has to have a value for both the consequent and the alternate, >> while the traditional if forms have an optional alternate. >...
>> One question is whether a form should be used for its value or not. The >> forms when and unless should clearly not be used for their value.
>I strongly disagree. I think when and unless can be perfectly well used >for their value. In general I think the Common Lisp programmer should >be free to use any form for it's value whenever that value can be given >a meaningful interpretation.
The rules are delightfully Scheme-y, with the difference being that in Scheme these are not "style rules". One has no recourse but to follow the rules, as one cannot rely on an absent branch resolving to #f, or even #t, or indeed any value that you can trust.
Looks like the CL community is about to rediscover the value (!) of the unspecified. :-)
> In such a place, I intend this to be read "the value of GET-PROPERTY is > the result of (GET X Y) when X is a symbol, but it really has no properties > otherwise".
good example, and quite representative for the kind of context in which I use the value of when myself!
* Espen Vestre | the perl "expression if" does not work that way:
Perl is not a language worth comparing anything to.
| (perl's _unless_, which can't be mentioned often enough since some people | think lisp is the only language with such an animal, can of course also | be used as a "expression unless").
Just being postfix does not make it an expression.
* Erik Naggum
> One question is whether a form should be used for its value or not. The > forms when and unless should clearly not be used for their value.
* Espen Vestre | I strongly disagree. I think when and unless can be perfectly well used | for their value. In general I think the Common Lisp programmer should be | free to use any form for it's value whenever that value can be given a | meaningful interpretation.
Well, unlike what a Perl hacker will expect,
(setq foo (when bar zot))
actually does modify foo when bar is false. I think using the one-branch conditionals when and unless for value is highly, highly misleading.
However, if they are used in a function body as the value-returning form and it is defined to return nil when "nothing happens", I think it is much more perspicuous to have an explicit (return nil) form under the appropriate conditions than let when or unless fall through and return nil by default, which can be quite invisible.
/// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
* Espen Vestre | good example, and quite representative for the kind of context in which | I use the value of when myself!
This is a sort of half-breed between a statement and an expression. I hate examples, because people attach too much meaning to their specifics, but I was trying to draw a line between statements and expressions, which I honestly assumed would be understood as directly value-returning forms. I assume from your responses that you would _not_ write
(setq foo (when bar zot))
but _would_ write
(setq foo (whatever))
in the presence of
(defun whatever () (when bar zot))
the latter of which does communicate "enough" to be defensible. However, I find it very, very strange that you think this is so representative of using when as an expression that you strongly disagree that when and unless should not be used for their value. To me, that says that you want to use when in let bindings and for arguments to functions, etc, which I think is just plain wrong. Please let me know if you want to use when in the usual expression positions, and thus make a distinction between whole function bodies inside when and unless and using them for smaller expressions.
/// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
* Dorai Sitaram | Looks like the CL community is about to rediscover the value (!) of the | unspecified. :-)
Scheme is all wrong. Making nil different from false is nuts, and letting forms have an unspecified value is also just plain wrong.
It is important that style rules be breakable. Enforcing them is wrong.
/// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
Erik Naggum <e...@naggum.net> writes: > Well, unlike what a Perl hacker will expect,
> (setq foo (when bar zot))
> actually does modify foo when bar is false.
Huh? That's exactly what a perl hacker would expect; in fact, s/he'd also expect foo = zot whenever bar is true, and foo = bar otherwise. *That* might be surprising to a lisp programmer, though :)
<ot> Both conditionals and loop constructs usually have return values in Perl; the conditional itself is returned whenever there is no successful alternative. Perl's for/foreach are the exceptions here, not the rule. </ot>
Jeez, I use when and unless for their values all the time. But then I am an expert in lisp, I know what they return. :) I guess I am also an expert because nil and '() look identical to me.
I think the big mistake in all this is thinking code should be readable. It should not be. Not by non-experts, experts or even the author. it should be understandable. anyone reading too fast to realize what when does will not understand the code anyway.
JF's premise in that astonishing coding standards bit is that code is read more often than it is written. Nah, the developer spends hours and hours on code which may never be read by anyone. Even in large teams, when code fails the pager of the author goes off. A few years later the whole system gets rewritten from scratch.
me, i do not have to understand my code because if i have to look at it I rewrite it anyway.
If I cannot use when for its value, why don't we just dump the whole language? functional programming right out the window. We can make it an error for the when conditional to evaluate to false.
And what's this about AND and OR returning the last evaluated form's value? talk about something not being explicit. let's get that sorted out immediately and return t or nil, period.
> > > One question is whether a form should be used for its value or > > > not. The forms when and unless should clearly not be used for > > > their value.
> > I strongly disagree. I think when and unless can be perfectly well > > used for their value. In general I think the Common Lisp programmer > > should be free to use any form for it's value whenever that value > > can be given a meaningful interpretation.
> The point is not about legality or conformity, but about the > communication of intent. Lots of things in Common Lisp can be done in > many different ways and since the programs are written more for humans > than for computers, the programmer should choose the way that most > clearly communicates the intent (just like some people _do_ quote nil > and keywords).
> If you use when or unless for value, you rely on the fact that if the > test fails they will return nil and you will use it as a meaningful > value. But this value does not appear anywhere and does not make this > explicit. Attention to detail at this level is what makes programs > beautiful and readable and approachable by non-experts in Common Lisp.
* Joe Schaefer | Huh? That's exactly what a perl hacker would expect; in fact, s/he'd | also expect foo = zot whenever bar is true, and foo = bar otherwise. | *That* might be surprising to a lisp programmer, though :)
Heh, not at all, because if bar is false, foo will equal bar in Common Lisp, too, although it is a slightly unusual way to look at it. Since there is but one false value in Common Lisp, and Perl has a whole range of them, I suppose there is Perlish sense in your version of this.
What I had in mind, however, was that Espen Vestre's example using a postfix if would cause the statement preceding it _not_ to be evaluated if the condition was false.
/// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
* Kenny Tilton | If I cannot use when for its value, why don't we just dump the whole | language? functional programming right out the window. We can make it | an error for the when conditional to evaluate to false.
"Should not" is different from "cannot". Grasp this and relax, please.
/// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
Erik Naggum <e...@naggum.net> writes: > I assume from your responses that you would _not_ write
> (setq foo (when bar zot))
I grepped through some thousand lines of code and found only one case of that pattern (so maybe I actually intuitively do avoid it?)
But to me, 'when' has a very strong "silent" "otherwise nil" to it, so I have absolutely no problems reading a statement like that. (And since I read 'when' that way, '(if bar zot nil)' is somewhat "noisy" to me).
I really don't see the big advantage of reserving 'when' and 'unless' to side-effects-only cases. -- (espen)
In article <3BFC0E0B.4C7DA...@nyc.rr.com>, Kenny Tilton <ktil...@nyc.rr.com> wrote:
>Jeez, I use when and unless for their values all the time. But then I am >an expert in lisp, I know what they return. :) I guess I am also an >expert because nil and '() look identical to me.
Since "when" (and "unless") must return a value, why not return a meaningful value? A return value of nil currently does not imply that the "when" failed. If we returned the value of the _test_, then the result is meaningful and usable.
Erik Naggum <e...@naggum.net> writes: > * Dorai Sitaram > | Looks like the CL community is about to rediscover the value (!) of the > | unspecified. :-)
> Scheme is all wrong. Making nil different from false is nuts, and > letting forms have an unspecified value is also just plain wrong.
I agree with the unspecified value part (which seems really weird for a language with such funcitonal aspirations, too). I'm not so sure about false, though. I don't like the pun that () is the same as boolean false. I also don't like that the empty list is a symbol. Don't get me wrong, it's easy enough to cope with, but it's conceptually sloppy. I don't even see any good reason why NIL should be false. It's a symbol; every other symbol is true. Of course, if #f were a special false value, I don't know what BLOCK should return, so that's maybe a practical argument against it. Or, maybe it should just return #F. I hate the idea of someone doing something like:
(cons 'foo (dolist ...))
so () would be a bad choice. If NIL were just another symbol, that would be a foolish choice. So the NIL that's returned now must be NIL in the boolean sense.
So, I guess what I'm saying is that you ought to explain your objection here (or point to a message where you've explained it before, since I'm sure you have).
-- /|_ .-----------------------. ,' .\ / | No to Imperialist war | ,--' _,' | Wage class war! | / / `-----------------------' ( -. | | ) | (`-. '--.) `. )----'
d...@goldshoe.gte.com (Dorai Sitaram) writes: > In article <3BFC0E0B.4C7DA...@nyc.rr.com>, > Kenny Tilton <ktil...@nyc.rr.com> wrote: > >Jeez, I use when and unless for their values all the time. But then I am > >an expert in lisp, I know what they return. :) I guess I am also an > >expert because nil and '() look identical to me.
> Since "when" (and "unless") must return a value, why > not return a meaningful value? A return value of nil > currently does not imply that the "when" failed. > If we returned the value of the _test_, then the > result is meaningful and usable.
Ahem!
* (when 3 4) 4
* (when nil 5) NIL
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 719 Broadway 12th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
"Thomas F. Burdick" wrote: > I don't even see any good reason why NIL should > be false.
Understood, but in this case the proof is in the pudding for me. By which I mean, programming with nil as false is so terrific it must be Deeply Right.
isn't there a funny essay somewhere about the consequences of porting something from Lisp to Scheme, specifically about the problem of having to then differentiate between nil and false? I recall assoc figuring prominently in the piece.
Kenny Tilton <ktil...@nyc.rr.com> writes: > "Thomas F. Burdick" wrote: > > I don't even see any good reason why NIL should > > be false.
> Understood, but in this case the proof is in the pudding for me. By > which I mean, programming with nil as false is so terrific it must be > Deeply Right.
But have you tried programming in a CL-like dialect where (), nil, and boolean false were three different objects? Otherwise, that would be somewhat like saying that lexical scoping was a bad idea because you had so much more fun in Maclisp or Interlisp than in Scheme.
> isn't there a funny essay somewhere about the consequences of porting > something from Lisp to Scheme, specifically about the problem of having > to then differentiate between nil and false? I recall assoc figuring > prominently in the piece.
Oh boy, how I hate when code depends on the pun between false and (). Bleah. Would it really kill people to put a couple (not (null ..))s here and there, and make their intentions more explicit?
-- /|_ .-----------------------. ,' .\ / | No to Imperialist war | ,--' _,' | Wage class war! | / / `-----------------------' ( -. | | ) | (`-. '--.) `. )----'
Dorai Sitaram wrote: > A return value of nil > currently does not imply that the "when" failed.
Just to be sure I understand you, are you making the point that when WHEN returns nil i do not know if the conditional or the consequent returned nil? ie, it could be (when nil t) or (when t nil)?
To save an iteration at the risk of answering a straw man: that is an interesting observation. But it should not matter; side-effects aside, every form is a black box, the only thing a client cares about is the result of evaluating the form, not its internals.
Kenny Tilton <ktil...@nyc.rr.com> writes: > "Thomas F. Burdick" wrote: > > I don't even see any good reason why NIL should > > be false.
As to the choice of the symbol, I somewhat agree. It's tradition, but one I could have done without. On the other hand, in my 20+ year career doing some fairly intensive Lisp, I've found it a minor irritation once or twice, but basically have never found it got in the way in any seriously material way ... so I guess I just don't buy any argument that it matters.
As to the choice of the empty list being false, I also don't see a problem there and actually see some virtue. I think all too much fuss has been made over this.
> Understood, but in this case the proof is in the pudding for me. By > which I mean, programming with nil as false is so terrific it must be > Deeply Right.
In the MOO programming language, which (I think by design) has a very Lispy feel, a bunch of objects are false, including 0 and "" and {}. Errors are also false. They make the mistake of making their type OBJ (sort of vaguely like our standard class) be false, and that causes problems. But the other values being false don't cause any problem to learn and it's quite handy to have these various degenerate cases all count as false. MOO is a byte compiled language and not overly obsessed with efficiency; there's probably something good about being able to do a truth test in one instruction, so maybe it's not awful that we have a single false value. But even so, I think that, if anything, we lose out by not having more false values, not by failing to jump on the Scheme bandwagon of "everything is bad but the explicit".
> isn't there a funny essay somewhere about the consequences of porting > something from Lisp to Scheme, specifically about the problem of having > to then differentiate between nil and false? I recall assoc figuring > prominently in the piece.
Well, people often do (cdr (assoc ...)) in LISP, and it's true that assoc returns false when it fails, which you can't cdr. But you also can't cdr the empty list in Scheme. So it would be a problem anyway.
I agree '() being false being nil is confusing at first. I just remembered what it was like when I was first learning Lisp. My feeling was, OK, they're making this sh*t up as they go along. But now it feels so natural I had no idea what you were going on about--until I remembered my early experience.
Which takes me back to my pudding proof. If it was Truly Confused (like some things I have worked with) it would never feel natural. But it feels natural, so the problem up front must have been with me.
Scheme worked from first principles when they "improved" on this. That is always dangerous. We are not as smart as we think. Who says we have the first principles right? One of my design rules says good design changes lead to less code; if I find myself adding code such as (not (null ...)) all over the place I back out the change. Schemers should have done the same when they saw the consequences of their change.
I believe it was David St. Hubbens (in collaboration with Nigel) who said, It's a fine line between clever and stupid.