Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How do you map IF in CL?

68 views
Skip to first unread message

WJ

unread,
Mar 7, 2012, 4:34:19 PM3/7/12
to

* (mapc #'if (list t nil) '(222 333) '(6 7))

debugger invoked on a SB-INT:SPECIAL-FORM-FUNCTION:
Cannot FUNCALL the SYMBOL-FUNCTION of special operator IF.

What's the right way to do this?

Leandro Rios

unread,
Mar 7, 2012, 5:06:21 PM3/7/12
to
El 07/03/12 18:34, WJ escribió:
IF is not a function. IF (as the error message suggests) is a special
form, which cannot be funcalled.

This that you seem to perceive as a flaw, is by design. See, how would
you prevent this from blowing:

(if (eof file)
(warn-user)
(read-record))

if IF were a function?

On the other hand, it's easy to define a function to do what you want:

(defun fif (condition true-part else-part)
(if condition
true-part
else-part))

Leandro

WJ

unread,
Mar 7, 2012, 5:53:02 PM3/7/12
to
Yes, but as you indicated above, one can't always use a function,
because all of its arguments are expanded.

In SBCL:

(defun fif (condition true-part else-part)
(if condition
true-part
else-part))

(defvar x 0)
(fif (zerop x) 'inf (/ 1 x))

debugger invoked on a DIVISION-BY-ZERO:
arithmetic error DIVISION-BY-ZERO signalled
Operation was SB-KERNEL::DIVISION, operands (1 0).


NewLisp uses fexprs, which give you the best of both worlds.
(I'm not an expert in NewLisp, so this could be improved.)


(define-macro (fif condition true-part else-part)
(if (eval condition)
(eval true-part)
(eval else-part)))

> (setq x 0)
0
> (fif (zero? x) 'inf (/ 27 x))
inf
> (setq x 3)
3
> (fif (zero? x) 'inf (/ 27 x))
9

It works with map:

> (map fif (list true nil) '(222 333) '(6 7))
(222 7)

And the built-in "if" works with map:

> (map if (list true nil) '(222 333) '(6 7))
(222 7)

--
Premature optimization is the root of all evil.

namekuseijin

unread,
Mar 7, 2012, 6:52:27 PM3/7/12
to
On Wednesday, March 7, 2012 7:53:02 PM UTC-3, WJ wrote:
> Premature optimization is the root of all evil.

regardless, newLisp still is dogSlow.

Cor

unread,
Mar 7, 2012, 7:05:47 PM3/7/12
to
The Feisty Youngster namekuseijin <nameku...@gmail.com>
scribbled this (selectively-snipped-or-not-p) stuff

>On Wednesday, March 7, 2012 7:53:02 PM UTC-3, WJ wrote:
>> Premature optimization is the root of all evil.
>
>regardless, newLisp still is dogSlow.

So what,,, The More time for Coffee & Tobacco !

C,\

--
Dieren hebben recht op een gezonde plek, mijn bord en een bos zijn dat
Slaven hebben geen recht op zelfverdediging
Mensen, volgens de UN, ook niet
http://www.thefreeworld.net

Leandro Rios

unread,
Mar 7, 2012, 8:30:31 PM3/7/12
to
El 07/03/12 19:53, WJ escribió:
CL allows us to do silly things too:

(defun silly-fif (condition true-part else-part)
(if (eval condition)
(eval true-part)
(eval else-part)))

CL-USER> (defparameter *x* 0)
*X*
CL-USER> (silly-fif '(zerop *x*) :inf '(/ 27 *x*))
:INF
CL-USER>

But this is a terrible idea! For example, silly-fif will not see lexical
bindings, because eval evaluates its input in the null lexical
environment. I'm pretty sure you have seen the same problem with Newlisp
when... wait. How do you say? No lexical scoping? Sure? Oh, well, don't
worry. I'm sure NewLisp will have lexical scoping in another, say, 20
years. Until then, you can keep playing with fexprs and brag about self
modifying code.

Enjoy!

Leandro

PS: Google "fexpr" in this group. Don't cry.
Message has been deleted

Marco Antoniotti

unread,
Mar 7, 2012, 10:26:59 PM3/7/12
to
Or the OP can use

cl-user 40> (use-package "CLAZY")
T

cl-user 41> (deflazy ifl (condition true-part else-part)
(if condition true-part else-part)) ; Look Ma! No EVAL!
IFL

cl-user 42> (mapcar (lazy ifl) '(t nil t) '(1 2 3) '(4 5 6))
(1 5 3)


But this was written directly in plain old CL. Suuuch a boring notion :)

Cheers
--
MA

Marco Antoniotti

unread,
Mar 7, 2012, 10:29:36 PM3/7/12
to
I even forgot how conservative I am. Of course if you define via DEFLAZY then you can just do

cl-user 42> (mapcar 'ifl '(t nil t) '(1 2 3) '(4 5 6))
(1 5 3)

Of course, the MAPCAR is suuuuuuch a turn off. :)

Cheers
--
MA

namekuseijin

unread,
Mar 8, 2012, 1:16:16 AM3/8/12
to
so you define a lazy function, and somehow still has to quote the parameters such that they are not evaluated?

useless.

namekuseijin

unread,
Mar 8, 2012, 1:18:12 AM3/8/12
to
oh, forget. got it. need some sleep...

Kaz Kylheku

unread,
Mar 8, 2012, 2:10:29 AM3/8/12
to
On 2012-03-08, namekuseijin <nameku...@gmail.com> wrote:
> so you define a lazy function, and somehow still has to quote the parameters
> such that they are not evaluated?

What it can do is delay the evaluation, creating a promise object. That is not
the same thing as an unevaluated piece of source code. It's a like closure that
has not been called (together with a place to cache the result so it is only
called once).

Juanjo Garcia

unread,
Mar 8, 2012, 5:51:06 AM3/8/12
to
Clue: It's typical to use a lambda function with a map operator.

Marco Antoniotti

unread,
Mar 8, 2012, 9:16:19 AM3/8/12
to
And, if I am not mistaken, this is also called TRT :) As the Algol guys understood once they figured out the intricacies of "call-by-name".

Cheers
--
MA

Marco Antoniotti

unread,
Mar 8, 2012, 9:41:41 AM3/8/12
to
Good. See? It is rather simple....

Cheers
--
MA

Marco Antoniotti

unread,
Mar 8, 2012, 9:14:02 AM3/8/12
to
Ooops pardon me. I forgot to ensure that the system magically knows that (T NIL T) is a list depending on context. What can I do? I am constrained by what the language allows me to do. Of course, if I used newLisp.....

Cheers
--
MA

Bill

unread,
Mar 8, 2012, 1:28:52 PM3/8/12
to
> * (mapc #'if (list t nil) '(222 333) '(6 7))

There is also at least one Scheme that lets you do that:

:(map if '(#t #f) '(222 333) '(6 7))
(222 7)

or stuff like

:(map apply (map lambda '(() (a) (a b)) '(1 (+ a 1) (+ a b 1))) '(() (2) (3 4)))
(1 3 8)


Jussi Piitulainen

unread,
Mar 8, 2012, 2:03:56 PM3/8/12
to
Those are not Scheme. I could probably live with an implementation
that gives some meaning to such expressions, but I would prefer an
error message. At compile time.

WJ

unread,
Mar 8, 2012, 7:04:09 PM3/8/12
to
PicoLisp also has fexprs:

? (mapcar if '(NIL T) '(a b) '(1 2))
-> (1 b)

Marco Antoniotti

unread,
Mar 8, 2012, 10:19:01 PM3/8/12
to
Wow! A non-CL with MAPCAR! Now you have done it. I'll stay awake just to watch the rest of the sitcom.

--
MA
0 new messages