The semantics of newLISP's if

Pondering the philosophy behind the language
Locked
rickyboy
Posts: 607
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

The semantics of newLISP's if

Post by rickyboy »

The if expression in newLISP can usually be found to have different semantics than ifs in other lisps. Lutz has chosen for it to have semantics which are in the spirit of cond.

I believe that this is a great choice, because newLISP's if is a general type of if. What do I mean by this? In the manual discussion, we are presented with the two different forms of if; but in fact, the second form (the one that takes an arbitrary number of clauses) is just a generalization of the first form.[1]

Lutz may not like for me to say this, but there is a beauty and a consistency[2] in its simple semantics. (Programming language geeks like me love it, but I think other users would too. This is something that I think can bring us all together. :)

I believe that Lutz made a great decision in choosing the semantics of newLISP's if expression, and in the following, I am going to detail why this is so.

The arguments to if are a list of clauses, which in the non-degenerate cases, are pairs of test and consequent clauses. The situation looks like this:

( if test-clause-1 consequent-clause-1 . . . test-clause-N consequent-clause-N )

These pairs are continually looped though until the first such test clause evaluates to a "truthy" value, in which case its corresponding consequent clause is evaluated and yielded as the value of the if expression itself.

The degenerate cases are when the if expression has one clause (argument) or none. But these cases can be thought of as base cases of a recursive evaluator for if. In fact, you can write such an evaluator in newLISP. Here is one.

Code: Select all

(define (eval-if EXPR)
  (if (empty? EXPR)        nil
      (= 'if (EXPR 0))     (eval-if (1 EXPR))
      (= 1 (length EXPR))  (eval (EXPR 0))      
      (let (test-clause (EXPR 0)
            consequent-clause (EXPR 1)
            rest-of-the-clauses (2 EXPR))
        (if (eval test-clause)
            (eval consequent-clause)
            (eval-if rest-of-the-clauses)))))
There is something important lurking here, and it is that this function describes the semantics of newLISP's if in newLISP itself!!! Yeah, that's cool.

Now, it is clear why the degenerate cases yield the values they do for newLISP's if. Here are some examples of these cases.

Code: Select all

(if)          ;=> nil
(if 42)       ;=> 42
(if (+ 2 40)) ;=> 42
Our evaluator treats them the same.

Code: Select all

(eval-if '(if))          ;=> nil
(eval-if '(if 42))       ;=> 42
(eval-if '(if (+ 2 40))) ;=> 42
Next, examples from the first form of if in the manual look like this.

Code: Select all

(set 'x 50)
(if (< x 100) "small" "big") ;=> "small"
(set 'x 1000)
(if (< x 100) "small" "big") ;=> "big"
(if (> x 2000) "big")        ;=> nil
Our evaluator in action now.

Code: Select all

(set 'x 50)
(eval-if '(if (< x 100) "small" "big")) ;=> "small"
(set 'x 1000)
(eval-if '(if (< x 100) "small" "big")) ;=> "big"
(eval-if '(if (> x 2000) "big"))        ;=> nil
Finally, the examples from the second form of if in the manual.

Code: Select all

(define (classify x)
  (if (< x 0) "negative"
      (< x 10) "small"
      (< x 20) "medium"
      (>= x 30) "big"
      "n/a"))

(classify 15)   ;=> "medium"
(classify 100)  ;=> "big"
(classify 22)   ;=> "n/a"
(classify -10)  ;=> "negative"
Our evaluator.

Code: Select all

(define (classify-eval-if x)
  (eval-if '(if (< x 0) "negative"
                (< x 10) "small"
                (< x 20) "medium"
                (>= x 30) "big"
                "n/a")))

(classify-eval-if 15)   ;=> "medium"
(classify-eval-if 100)  ;=> "big"
(classify-eval-if 22)   ;=> "n/a"
(classify-eval-if -10)  ;=> "negative"
__________
[1] No doubt though that the manual presents two forms of if to the user because the first form is well-known; so it will communicate its ideas (about it and the second form) best to the broadest section of readers.

[2] There you go, Lutz; I used both terms. :)
(λx. x x) (λx. x x)

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Re: The semantics of newLISP's if

Post by Lutz »

[2] There you go, Lutz; I used both terms. :)
Sigh of relief. You will get promoted from rickyboy to rickman :)

Locked