2 ms·
> It is also clear that you actually need the delay-evaluation mechanism in order to get something like "if" out of the language and into the library. In a fun
by lispm 8y ago
> It is also clear that you actually need the delay-evaluation mechanism in order to get something like "if" out of the language and into the library.
In a functional programming language one can just use functions.
(defun l-true (a b) a)
(defun l-false (a b) b)
(defun l-if (f a b) (funcall f a b))
True is a function, false is a function and if is a function.
Now we can do conditional execution:
CL-USER 57 > (l-if #'l-true 1 2)
1
CL-USER 58 > (l-if #'l-false 1 2)
2
CL-USER 59 > (funcall (l-if #'l-true
(lambda () (print 'true-case) nil)
(lambda () (print 'false-case) nil)))
TRUE-CASE
NIL
But Lisp doesn't do that. It provides one conditional as a primitive.
- mpweiher 8y ago>> need delay-evaluation [for "if" in lib] > one can just use functions Yes. Obviously. Of course. That's how Smalltalk does it, though it doesn't have general functions, it only has anonymous functions aka (roughly) blocks. Any other language that can pass functions or some sort of equivalent as arguments can obviously also do this. Heck, you can even do this, horribly, in C: #include <stdio.h> void a() { printf("true\n"); } void b() { printf("false\n"); } typedef void (*fnfn) (); void fnif(int cond, fnfn trueCase, fnfn falseCase ) { fnfn switcher[2]={ falseCase, trueCase }; switcher[cond](); } int main(int argc, char *argv[] ) { fnif( 0, a,b ); } (A little surprised that this compiled on the first try. More surprised that clang didn't show any warnings, even with -Wpedantic. Shows you how well I understand C/C compilers ¯\_(ツ)_/¯ ). And function definitions, lambdas, blocks etc. all delay the evaluation of their bodies.
- chriswarbo 8y ago`if` has two distinguishing features: - It selects between two possibilities - The non-selected possibility isn't evaluated/executed (i.e. the evaluation of the possibilities is delayed until after one has been selected) This is very important for imperative languages, since executing both branches would have observable effects even if we only returned one result. This is also true in functional programming languages, even pure ones, since it's needed to e.g. terminate recursive calls. For example, if we define factorial by branching on whether the argument is 0 (base case) or not (recursive case), then evaluating both branches before selecting one would cause an infinite recursion for all arguments. In the case of your Lisp code, we couldn't implement a recursive function like factorial unless we delay the evaluation e.g. by using macros to do the selection, or by switching from Lisp's default evaluation order (call-by-value) to something non-eager like call-by-name or call-by-need.