Elisp: how can I express else-if - lisp

In elisp, the if statement logic only allows me an if case and else case.
(if (< 3 5)
; if case
(foo)
; else case
(bar))
but what if I want to do an else-if? Do I need to put a new if statement inside the else case? It just seems a little messy.

Nesting if
Since the parts of (if test-expression then-expression else-expression) an else if would be to nest a new if as the else-expression:
(if test-expression1
then-expression1
(if test-expression2
then-expression2
else-expression2))
Using cond
In other languages the else if is usually on the same level. In lisps we have cond for that. Here is the exact same with a cond:
(cond (test-expression1 then-expression1)
(test-expression2 then-expression2)
(t else-expression2))
Note that an expression can be just that. Any expression so often these are like (some-test-p some-variable) and the other expressions usually are too. It's very seldom they are just single symbols to be evaluated but it can be for very simple conditionals.

Related

Introducing a Named Variable with Syntax Rules

I am trying to write a super-tiny Object-oriented system with syntax-rules, mostly just to learn it. Anyway, I am trying to introduce a "this" variable. Here is what I would like to be able to do:
(oo-class Counter
(
(attr value 0)
(attr skip 1)
)
(
(method (next) (set! value (+ value skip)) value)
(method (nextnext) (this 'next) (this 'next))
(method (set-value newval) (set! value newval))
(method (set-skip newskip) (set! skip newskip))
)
)
(define c (Counter))
((c 'set-value) 23)
((c 'next))
((c 'nextnext))
I can get everything to work except "this". It seems like syntax-rules doesn't allow variable introduction. I thought I could get it by defining it as one of the literals in syntax-rules, but this does not seem to work.
Below is my object-oriented system:
(define-syntax oo-class
(syntax-rules (attr method this)
(
(oo-class class-name
((attr attr-name initial-val) ...)
((method (meth-name meth-arg ...) body ...) ...))
(define class-name
(lambda ()
(letrec
(
(this #f)
(attr-name initial-val)
...
(funcmap
(list
(cons (quote meth-name) (cons (lambda (meth-arg ...) body ...) '()))
...
)
)
)
(set! this (lambda (methname)
(cadr (assoc methname funcmap))
))
this
)
)
)
)
)
)
This works for everything except 'nextnext, which errors out when it tries to reference "this".
Is this the right way to do this? Is there some other way to do this? I recognize that this is slightly unhygienic, but isn't that at least part of the point of specifying literals?
I've tried this in Chicken Scheme as well as DrRacket in R5RS mode (other modes get complainy about "this").
Below is the whole file. You can run it on Chicken with just "csi object.scm"
https://gist.github.com/johnnyb/211e105882248e892fa485327039cc90
I also tried to use let-syntax and use (this) as a syntax specifier to refer to the (this) variable. But, as far as I could tell, it wasn't letting me directly access a variable of my own making within the syntax rewriting.
BONUS QUESTION: What is an easy way to see the result of a syntax-rules transformation for debugging? Is there some way to get chicken (or something else) to do the transformation and spit out the result? I tried some stuff on DrRacket, but it doesn't work in R5RS mode.
I recognize that this is slightly unhygienic, but isn't that at least part of the point of specifying literals?
No, the literals exist so you can match literally on keywords, like for example the => or the else in a cond clause. It's still hygienic because if => or else is lexically bound to some value, that has precedence:
(let ((else #f))
(cond (else (display "hi!\n")))) ;; Will not print
Now, you could write a very tedious macro that matches this at any possible place and nesting level in the expansion, but that will never be complete, and it would not nest lexically, either.
It is possible to do what you're trying to do using what has become known as Petrofsky extraction, but it's a total and utter hack and abuse of syntax-rules and it does not work (consistently) in the presence of modules across implementations (for example, exactly in CHICKEN we've had a complaint that we accidentally "broke" this feature).
What I'd suggest is writing a syntax-rules macro that accepts an identifier in its input which will be bound to the current object, then write one trivial unhygienic macro that calls that other macro with the hardcoded identifier this as input.
What is an easy way to see the result of a syntax-rules transformation for debugging? Is there some way to get chicken (or something else) to do the transformation and spit out the result? I tried some stuff on DrRacket, but it doesn't work in R5RS mode.
In csi, you can use ,x (macro-call), but it will only do one level of expansion.
A common trick that works in every Scheme implementation is to change your macro definition to quote its output. So, it expands not to (foo) but to '(foo). That way, you can just call the macro in the REPL and see its result immediately.

How does `if` not evaluate all its arguments?

I'm trying to learn and understand the Lisp programming language to a deep level. The function + evaluates its arguments in applicative order:
(+ 1 (+ 1 2))
(+ 1 2) will be evaluated and then (+ 1 3) will be evaluated, but the if function works differently:
(if (> 1 2) (not-defined 1 2) 1)
As the form (not-defined 1 2) isn't evaluated, the program doesn't break.
How can the same syntax lead to different argument evaluation? How is the if function defined so that its arguments aren't evaluated?
if is a special operator, not an ordinary function.
This means that the normal rule that the rest elements in the compound form are evaluated before the function associated with the first element is invoked is not applicable (in that it is similar to macro forms).
The way this is implemented in a compiler and/or an interpreter is that one looks at the compound form and decides what to do with it based on its first element:
if it is a special operator, it does its special thing;
if it is a macro, its macro-function gets the whole form;
otherwise it is treated as a function - even if no function is defined.
Note that some special forms can be defined as macros expanding to other special forms, but some special forms must actually be present.
E.g., one can define if in terms of cond:
(defmacro my-if (condition yes no)
`(cond (,condition ,yes)
(t ,no)))
and vice versa (much more complicated - actually, cond is a macro, usually expanding into a sequence of ifs).
PS. Note that the distinction between system-supplied macros and special operators, while technically crisp and clear (see special-operator-p and macro-function), is ideologically blurred because
An implementation is free to implement a Common Lisp special operator
as a macro. An implementation is free to implement any macro operator
as a special operator, but only if an equivalent definition of the
macro is also provided.
sds's answer answers this question well, but there are a few more general aspects that I think are worth mentioning. As that answer and others have pointed out, if, is built into the language as a special operator, because it really is a kind of primitive. Most importantly, if is not a function.
That said, the functionality of if can be achieved using just functions and normal function calling where all the arguments are evaluated. Thus, conditionals can be implemented in the lambda calculus, on which languages in the family are somewhat based, but which doesn't have a conditional operator.
In the lambda calculus, one can define true and false as functions of two arguments. The arguments are presumed to be functions, and true calls the first of its arguments, and false calls the second. (This is a slight variation of Church booleans which simply return their first or second argument.)
true = λ[x y].(x)
false = λ[x y].(y)
(This is obviously a departure from boolean values in Common Lisp, where nil is false and anything else is true.) The benefit of this, though, is that we can use a boolean value to call one of two functions, depending on whether the boolean is true or false. Consider the Common Lisp form:
(if some-condition
then-part
else-part)
If were were using the booleans as defined above, then evaluating some-condition will produce either true or false, and if we were to call that result with the arguments
(lambda () then-part)
(lambda () else-part)
then only one of those would be called, so only one of then-part and else-part would actually be evaluated. In general, wrapping some forms up in a lambda is a good way to be able delay the evaluation of those forms.
The power of the Common Lisp macro system means that we could actually define an if macro using the types of booleans described above:
(defconstant true
(lambda (x y)
(declare (ignore y))
(funcall x)))
(defconstant false
(lambda (x y)
(declare (ignore x))
(funcall y)))
(defmacro new-if (test then &optional else)
`(funcall ,test
(lambda () ,then)
(lambda () ,else)))
With these definitions, some code like this:
(new-if (member 'a '(1 2 3))
(print "it's a member")
(print "it's not a member"))))
expands to this:
(FUNCALL (MEMBER 'A '(1 2 3)) ; assuming MEMBER were rewritten
(LAMBDA () (PRINT "it's a member")) ; to return `true` or `false`
(LAMBDA () (PRINT "it's not a member")))
In general, if there is some form and some of the arguments aren't getting evaluated, then the (car of the) form is either a Common Lisp special operator or a macro. If you need to write a function where the arguments will be evaluated, but you want some forms not to be evaluated, you can wrap them up in lambda expressions and have your function call those anonymous functions conditionally.
This is a possible way to implement if, if you didn't already have it in the language. Of course, modern computer hardware isn't based on a lambda calculus interpreter, but rather on CPUs that have test and jump instructions, so it's more efficient for the language to provide if a primitive and to compile down to the appropriate machine instructions.
Lisp syntax is regular, much more regular than other languages, but it's still not completely regular: for example in
(let ((x 0))
x)
let is not the name of a function and ((x 0)) is not a bad form in which a list that is not a lambda form has been used in the first position.
There are quite a few "special cases" (still a lot less than other languages, of course) where the general rule of each list being a function call is not followed, and if is one of them. Common Lisp has quite a few "special forms" (because absolute minimality was not the point) but you can get away for example in a scheme dialect with just five of them: if, progn, quote, lambda and set! (or six if you want macros).
While the syntax of Lisp is not totally uniform the underlying representation of code is however quite uniform (just lists and atoms) and the uniformity and simplicity of representation is what facilitates metaprogramming (macros).
"Lisp has no syntax" is a statement with some truth in it, but so it's the statement "Lisp has two syntaxes": one syntax is what uses the reader to convert from character streams to s-expressions, another syntax is what uses the compiler/evaluator to convert from s-expressions to executable code.
It's also true that Lisp has no syntax because neither of those two levels is fixed. Differently from other programming languages you can customize both the first step (using reader macros) and the second step (using macros).
It would not make any sense to do so. Example: (if (ask-user-should-i-quit) (quit) (continue)). Should that quit, even though the user does not want to?
IF is not a function in Lisp. It is a special built-in operator. Lisp a several built-in special operators. See: Special Forms. Those are not functions.
The arguments are not evaluated as for functions, because if is a special operator. Special operators can be evaluated in any arbitrary way, that's why they're called special.
Consider e.g.
(if (not (= x 0))
(/ y x))
If the division was always evaluated, there could be a division by zero error which obviously was not intended.
If isn't a function, it's a special form. If you wanted to implement similar functionality yourself, you could do so by defining a macro rather than a function.
This answer applies to Common Lisp, but it'll probably the same for most other Lisps (though in some if may be a macro rather than a special form).

Dynamic variables in Lisp Case statement

I wrote this piece of code in common lisp (ignore the ... as it is pointless to paste that part here).
(case turn
(*red-player* ...)
(*black-player* ...)
(otherwise ...))
red-player and black-player are variables that were defined using defvar statement, in order to "simulate" a #define statement in C.
(defvar *red-player* 'r)
(defvar *black-player* 'b)
As you can imagine, when the variable turn receives either *red-player*'s value ('r) or *black-player*'s value ('b), the case statement doesn't work properly, as it expects that turn contains *red-player* as a literal, not the content of the variable *red-player*.
I know that I can easily fix that using a cond or if + equal statements, as the content of the variable is evaluated there, but I am curious. Maybe there is a way to create something like C's macros in Lisp, or there is some kind of special case statement that allows the use of variables instead of literals only.
Thank you in advance!
You can enter the value of expressions into your forms with read-time evaluation
CL-USER 18 > (defvar *foo* 'a)
*FOO*
CL-USER 19 > (defvar *bar* 'b)
*BAR*
CL-USER 20 > '(case some-var (#.*foo* 1) (#.*bar* 2))
(CASE SOME-VAR (A 1) (B 2))
Note that read-time evaluation is not necessarily the best idea for improving code maintenance and security.
Note also that the idea that there is a variable with a descriptive name for some internal value like is not necessary in Lisp:
dashedline = 4
drawLine(4,4,100,100,dashedline)
would be in Lisp
(draw-line 4 4 100 100 :dashed-line)
In Lisp one can pass descriptively named symbols. The sort of API that uses integer values or similar is only need in APIs to external software typically written in C.
The short answer is "yes, you can do it, sort of".
And the seeds of the longer answer involve the use of defmacro to create your own version of case, say mycase, that will return a regular case form. The macro you define would evaluate the head of each list in the case body.
You would call:
(mycase turn
(*red* ...)
(*black* ...)
(otherwise ...))
which would return
(case turn
((r) ...)
((b) ...)
(otherwise ...))
to the evaluator. The returned case form would then be evaluated in the way you want.
You'd then be free to continue programming in your c-esque fashion to the dismay of lispers everywhere! Win-win?
You can abuse Lisp in any way you like. It is flexible like that, unlike C.
It doesn't always like the uses you put it to. Why push Lisp around?
Try this approach:
(defvar *turn* nil)
(cond
((eq *turn* 'red)
...
(setq *turn* 'black)))
((eq *turn* 'black)
...
(setq *turn* 'red)))
(t
.......))

About "If.." in Scheme (plt-scheme)

I had a pretty simple requirement in my Scheme program to execute more
than one statement, in the true condition of a 'if'. . So I write my
code, something like this:
(if (= 1 1)
((expression1) (expression2)) ; these 2 expressions are to be
; executed when the condition is true
(expression3))
Obviously, the above doesn't work, since I have unintentionally
created a # procedure with # arguments. So, to get my
work done, I simply put the above expressions in a new function and
call it from there, in place of the expression1, expression2. It
works.
So, my point here is: is there any other conditional construct which
may support my requirement here?
In MIT-Scheme, which is not very different, you can use begin:
(if (= 1 1)
(begin expression1 expression2)
expression3)
Or use Cond:
(cond ((= 1 1) expression1 expression2)
(else expression3))
(begin ...) is how you evaluate multiple expressions and return the last one. Many other constructs act as "implicit" begin blocks (they allow multiple expressions just like a begin block but you don't need to say begin), like the body of a cond clause, the body of a define for functions, the body of a lambda, the body of a let, etc.; you may have been using it without realizing it. But for if, that is not possible in the syntax because there are two expressions (the one for true and the one for false) next to each other, and so allowing multiple expressions would make it ambiguous. So you have to use an explicit begin construct.
you can use (begin ...) to get what you want in the true branch of your if statement. See here
You can use COND, or put the expressions into something like PROGN in Lisp (I am not sure how it is called in PLT Scheme. edit: it is called BEGIN).
COND looks like this in Scheme:
(cond [(= 1 1)
(expression1)
(expression2)]
[else
(expression3)])
Using an if statement with more than two cases involves nesting, e.g.:
(if (test-1) ; "if"
(expression-1)
(if (test-2) ; "else-if"
(expression-2)
(expression-3))) ; "else"
Using cond seems to be the preferred way for expressing conditional statements as it is easier to read than a bunch of nested ifs and you can also execute multiple statements without having to use the begin clause:
(cond ((test-1)
(expression-1))
((test-2)
(expression-2)
(expression-3))
(else
(default-expression)))

The Clojure (or Lisp) Equivalent of a Compound Boolean Test

In C++ I'd write something like this:
if (a == something && b == anotherthing)
{
foo();
}
Am I correct in thinking the Clojure equivalent is something like this:
(if (= a something)
(if (= b anotherthing)
(foo)))
Or is there another way to perform a logical "and" that I've missed? As I said the latter form seems to work correctly--I was just wondering if there's some simpler way to perform the logical and. And searching for "boolean" "logical" and "and" on the Clojure Google Group turned up too many results to be much use.
In Common Lisp and Scheme
(and (= a something) (= b another) (foo))
In Common Lisp, the following is also a common idiom:
(when (and (= a something) (= b another))
(foo))
Compare this to Doug Currie's answer using (and ... (foo)). The semantics are the same, but depending on the return type of (foo), most Common Lisp programmers would prefer one over the other:
Use (and ... (foo)) in cases where (foo) returns a boolean.
Use (when (and ...) (foo)) in cases where (foo) returns an arbitrary result.
An exception that proves the rule is code where the programmer knows both idioms, but intentionally writes (and ... (foo)) anyway. :-)
In Clojure I would normally use something like:
(if
(and (= a something) (= b anotherthing))
(foo))
It is clearly possible to be more concise (e.g. Doug's answer) but I think this approach is more natural for people to read - especially if future readers of the code have a C++ or Java background!
It's really cool! (and x y) is a macro -- you can check the source code at clojure.org -- that expands to (if x y false) equivalent to:
if (x) {
if (y) {
...
}
} else {
false
}
(or x y) is similar but reversed.