4 ms·
> It doesn't have to be built into the language; it could be a macro based on COND or even on WHEN/UNLESS. But… In Common Lisp IF is built in and COND is a mac
by lispm 11y ago
> It doesn't have to be built into the language; it could be a macro based on COND or even on WHEN/UNLESS. But…
In Common Lisp IF is built in and COND is a macro. One of the conditionals needs to be built-in.
http://www.lispworks.com/documentation/HyperSpec/Body/s_if.htm#if http://www.lispworks.com/documentation/HyperSpec/Body/s_if.h...
> One has to have some special forms in order to build everything else as macros.
For conditionals, one conditional needs to be there, into which the other macro-based conditionals can be expanded.
> And in practice, of course, there can be some big efficiency gains to having lots of special forms vice having only a few and lots of macrology.
Not really. Common Lisp has a minimum of special forms and usually has some of the faster Lisp implementations.
- lisper 11y ago> One of the conditionals needs to be built-in. That's actually not true. IF can be implemented in terms of LAMBDA. (defun _true (then else) then) (defun _false (then else) else) (defmacro _if (condition then else) `(funcall (funcall (function ,condition) (lambda () ,then) (lambda () ,else)))) ? (_if _true (print 123) (print 456)) 123 123 ? (_if _false (print 123) (print 456)) 456 456 ?
- ClashTheBunny 11y agoThere are problems with infinite recursion if you do that, no? http://stackoverflow.com/questions/1171252/whats-the-explanation-for-exercise-1-6-in-sicp http://stackoverflow.com/questions/1171252/whats-the-explana...
- lisper 11y agoNope. That's the reason for wrapping THEN and ELSE inside lambdas, to delay the evaluation until after one of them is selected. Try it. [UPDATE] You have to make some minor tweaks to my original code to make it work. Here's a fully tested version: (defun _true (then else) then) (defun _false (then else) else) (defmacro _if (condition then else) `(funcall (funcall ,condition (lambda () ,then) (lambda () ,else)))) (setf (get t 'altboolean) '_true) (setf (get nil 'altboolean) '_false) (defun ->altboolean (condition) (get condition 'altboolean)) (defun _fact (n) (_if (->altboolean (<= n 1)) 1 (* n (_fact (1- n)))))
- junke 11y agoDoes "fully tested" means it is supposed to work as a replacement of IF in Common Lisp? Or is it just a toy example in a made-up Lisp/Scheme to beat that dead horse? >> In Common Lisp IF is built in and COND is a macro. One of the conditionals needs to be built-in. > That's actually not true. The context was about Common Lisp, not Haskell nor Scheme (of course other languages do things as they wish, including lazy evaluation). There need to be at least one conditional built-in in CL in order to map generalized booleans to {T, NIL}. This conditional could even be eager, but there has to be a construct which selects the approprate value. Which of the other 24 special forms is suitable?
- lisper 11y agoFully tested means that it solves the problem of infinite recursion cited in the stackoverflow question. As implemented, it's not quite a drop-in replacement for IF, but it can be made so by rolling the call to ->ALTBOOLEAN in to the _IF macro. > The context was about Common Lisp Yes, I know that. The example code is written in Common Lisp. > there has to be a construct which selects the approprate value Yes. LAMBDA can do that. > Which of the other 24 special forms is suitable? LAMBDA. It can be used both to select the appropriate value and to delay evaluation. LAMBDA is really all you need. Making IF a special form is just an optimization.
- lispm 11y agoIn Common Lisp everything not NIL is true.
- lisper 11y agoIt's a pretty elementary exercise to fix ->altboolean so that this invariant is maintained.
- junke 11y ago>> Which of the other 24 special forms is suitable? > LAMBDA. I am nitpicking, but LAMBDA is not a special form, FUNCTION/FLET/LABELS are: http://www.lispworks.com/documentation/HyperSpec/Body/03_ababa.htm#clspecialops http://www.lispworks.com/documentation/HyperSpec/Body/03_aba... > It's a pretty elementary exercise to fix ->altboolean so that this invariant is maintained. And how do you map generalized booleans to your functions? Right now, I can think of two possible ways. You can map NIL to #'_false in a hash-table, and use (gethash nil table #'_true) to provide a default value. Or you can also write a generic function: (defgeneric ->altboolean (x) (:method ((x null)) #'_false) (:method (x) #'_true)) There could be other ways, but as far as I know, none of them are portable, because even though it is allowed for all defined CL operators to be implemented as built-ins, you generally cannot expect or assume that it is done so (see gethash in CCL and SBCL). As far as you know, and even though it would be terribly inefficient, they could all be implemented only by combining special forms. If you discard IF, can you perform the elementary exercise using only special forms? I cannot imagine how, but I honestly would like to be shown a working approach.
- lispm 11y agoWelcome to the real world. I'm not talking about Lambda Calculus and related. I'm talking about Lisp implementation. Real world Lisp implementation.