4 ms·
There 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://
by ClashTheBunny 11y ago
There 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.
- lisper 11y ago> I am nitpicking You certainly are. > can you perform the elementary exercise using only special forms? I don't even need any special forms. All I need to do is use the default argument to GET.
- lispm 11y agoCL-USER 16 > (defparameter a 0) A CL-USER 17 > (if (foo) (foo) (foo)) T CL-USER 18 > a 4 CL-USER 19 > (defparameter a 0) A CL-USER 20 > (_if (->altboolean (foo)) (foo) (foo)) T CL-USER 21 > a 5 Given that foo is defined as: (defmacro foo () (incf a) '(progn (incf a) t)) 4 vs. 5 Does not look like a true replacement for IF in Common Lisp...