Racket: inner reduction vs. lazy evaluation? - racket

I thought racket does inner reduction always for evaluation but I found out e.g. "if" (and cond?!) is lazy evaluation in racket...why is this needed?
Is it impossible to realize an if-statement via inner reduction?
I can not figure out where lazy evaluation is better than inner and vice versa? Could someone supply an example?

if and cond are not "lazy", they just have different evaluation rules. For example, in the following expression only the consequent part of the if is executed, because the condition happens to be true:
(if (= 1 1)
'ok
(/ 1 0))
=> 'ok
If the alternative part were executed, we'd have a division by zero error. This is not lazy evaluation, it's just the way an if expression works in Scheme. Compare the above example with this one:
(define (my-if condition consequent alternative)
(if condition
consequent
alternative))
(my-if (= 1 1) 'ok (/ 1 0))
=> /: division by zero
Now we're using the standard evaluation rules for procedures, which in a non-lazy interpreter specify that all the arguments are evaluated before executing the procedure's body - hence an error is raised. That's why if can not be implemented as a normal procedure, it has to be a special form because it requires different evaluation rules.

Related

Difference between `do` and `do*` in Lisp?

I am working on these two functions that differ only in how ret and curr are assigned their value while the loop runs. In the first function ret and curr are bound in parallel; in the second function they are bound sequentially.
parallel binding
(defun maxpower (base maximum)
"returns base ^ k such that it is <= maximum"
(do ((ret 1 curr) ; parallel
(curr base (* base curr))) ; binding
((> curr maximum) ret)))
sequential binding
(defun maxpower* (base maximum)
"returns base ^ k such that it is <= maximum"
(do* ((ret 1 curr) ; sequential
(curr base (* base curr))) ; binding
((> curr maximum) ret)))
Question: is the 1st function is somehow wrong (*) because curr is both updated and evaluated at the same time (in parallel)?
IOW: if I change the order of the bindings there should be no difference in the parallel version?
How does Lisp decide about the parallelization of the bindings?
In my tests, both functions return the same value, as they are.
(*): I come from C background; I'd say 1st function invokes Undefined Behaviour.
It's probably best to look at let versus let* first. If you understand that, then do versus do* follows from that, except for the additional consideration of the step-forms.
Common Lisp is a strictly evaluated language. In both let and let*, the variable init-forms are evaluated left to right. The difference is in the scope and binding. Under let, all of the init forms are evaluated in a scope in which none of the variables are visible, whereas under let*, the forms are evaluated in an environment under which all the previous variables are visible. Secondly, since under let*, the previous variables are visible, their values are also established.
Using let we can create a scope in which the values of two variables appear swapped:
(let ((x y)
(y x))
...)
The initializing expressions y and x are evaluated first, in that order, and then the new values x and y are bound to the resulting values, which makes this possible.
On the other hand:
(let* ((a 1)
(b (+ a 2)))
Here, 1 is evaluated, and a is bound. This a is then visible to the (+ a 2) expression whose value is computed, and bound to b.
Now, onto do/do*. These macros perform, prior to the first iteration, binding of the variables that is exactly like let/let*. In binding the variables, the difference between do and do* is exactly like between let and let*.
The do/do* macros also have step-forms, which give the next value to their corresponding iteration variables. These step-forms are all in the scope of all of the variables, regardless of whether the macro operator is do or do*. Whether you're using do or do*, you can refer to any variable in any step form. The difference is when the assignment takes place. Under do, all of the step forms are evaluated from top to bottom, and then their corresponding variables are assigned new values for the next iteration. Under do*, the behavior is "assign as you go". As each step-form is evaluated, the corresponding variable is assigned. Therefore under do, when the step-form refers to any variable, it refers to its value from the prior iteration. Under do*, if the step-form refers to a lexically earlier variable, it's picking up the new value. If it refers to a lexically later variable, it's still seeing the old value from the prior iteration.
We have to emphasize that although let and do have some "parallel" behavior, in a sense, there is no parallel evaluation. All visible effects are performed left to right. What appears to happen in parallel is the variables coming into existence, or being assigned new values in the new iteration. But this is only parallel in the sense that the program cannot observe the intermediate progress. For instance, the passage of function arguments into a function is likewise "parallel"; the program doesn't observe a state in which the function call is partially in progress, and only half the arguments have been passed.
In the case of maxpower it is not correct that "curr is both updated and evaluated at the same time". The step forms in do are all evaluated before any assignment takes place. For do, the Hyperspec says that "the assignment of values to vars is done in parallel, as if by psetq," and for psetq it says that "first all of the forms are evaluated, and only then are the variables set to the resulting values."
In the posted code, both definitions should produce the same results because the step forms are evaluated before any assignments are done. But, if the order of the bindings were reversed things would be different:
(defun maxpower (base maximum)
(do ((curr base (* base curr))
(ret 1 curr))
((> curr maximum) ret)))
(defun maxpower* (base maximum)
(do* ((curr base (* base curr))
(ret 1 curr))
((> curr maximum) ret)))
Now for the first function, (* base curr) and curr are evaluated at the same time, and the values of curr and ret are updated in parallel. But, for the second function, (* base curr) is evaluated and the result assigned to curr, and then curr is evaluated and assigned to ret.
For these new definitions you can see that the results differ, where in the original definitions both functions would have returned 4 for both (maxpower 2 5) and (maxpower* 2 5):
CL-USER> (maxpower 2 5)
4
CL-USER> (maxpower* 2 5)
8

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).

Scheme - my gcd() always returns zero

I just start to learn Scheme today.
I wrote a function gcd(), but it always returns 0.
(define (gcd a b)
(cond (= b 0)
(a)
(else ((gcd b (modulo a b))))
)
)
Why I am wrong?
This should fix the problems:
(define (gcd a b)
(cond [(= b 0) a]
[else (gcd b (modulo a b))]))
You were incorrectly surrounding some expressions between parenthesis, and some parenthesis were missing from the cond expression.
Notice that in Scheme, when you surround something in parenthesis, say (a) you're telling the interpreter: a is a procedure with no arguments and I want to call it, and this was not the case in here, a is just a number.
Also, for readability's sake, it's a good idea to use [] instead of () to separate each of the conditions in a cond expression, as shown in my code above - but don't forget them, they're mandatory and in your code you forgot them in the first condition.
Other people have described what your mistake is and what you should do.
It is also instructive to consider how your code is actually run and why it produces the output you see. Because of your missing parentheses, the first case for your cond is (= b 0). The first thing (=) is taken as the condition. Everything in Scheme except #f is true, so this is always true. Since it is true, this case is evaluated. Specifically, the rest of the things in the parentheses is taken as (possible multiple) expressions to evaluate, as an implicit begin. So basically it evaluates (begin b 0). The result is the result of the last expression, 0.

What would the consequences be of allowing special forms to be treated as normal values?

I discovered that special forms can not be passed as arguments or saved in variables, both in Clojure:
user=> (defn my-func
[op]
(op 1 2 3))
#'user/my-func
user=> (my-func +)
6
user=> (my-func if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:5)
user=> (def my-if if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:9)
and in Racket/Scheme:
> (define (my-func op)
(op 1 2 3))
> (my-func +)
6
> (my-func if)
if: bad syntax in: if
> (define my-if if)
*if: bad syntax in: if
That's cool, I'm fine with that, I know that I can just write a function to wrap a special form and then pass that function.
But I'd like to know why Lisps have this restriction, and what negative consequences allowing this would have. Are they any major dialects that do allow that?
It makes evaluation more complicated and compilation hard.
If you have a form (a b c), then you need to resolve at runtime the value of a and then apply it somehow to the forms b and c.
The simpler model of a few limited number of special forms and otherwise strict evaluation is then gone.
See also: FEXPR
Special forms are not functions: functions take values as arguments, whereas special forms take forms. For example, look at your example of if:
(if 1 2 3)
Okay, that's easy, since 2 and 3 are already values. But what about this?
(define (modadd a b n)
(if (zero? n) #f (modulo (+ a b) n)))
In this case, the if is actually receiving the #f and (modulo (+ a b) n) as forms, not as values. And this is important! (modulo x n) will fail if n is 0: that is why it's left unevaluated until we know that n is not 0.
The trouble with being able to pass special forms as first-class objects is that higher-order functions cannot call those objects using predictable semantics: is it a function object, so that you're passing in values, or is it a special form, so that you're passing in forms? This gets to be a huge mess.
Yes, you can write a wrapper function, like my modadd, that encapsulates if. However, there is no way you can just reimplement if as a function, while still preserving the only-evaluate-one-of-the-branches behaviour.

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)))