From: William James
Subject: Macro unnecessary
Date: 
Message-ID: <8c8e8050-017a-45d0-ac8b-ba704bea3e05@p31g2000prf.googlegroups.com>
 André Thieme wrote

> I will take one of the first macro examples form "On Lisp".
> Let's say for some reason you want to analyse some numbers
> and do something depending on their sign. We want a function
> "numeric if":
>
> def nif(num, pos, zero, neg):
>    if num > 0:
>      return pos
>    else:
>      if num == 0:
>        return zero
>      else:
>        return neg
>
>
> In Lisp very similar:
> (defun nif (num pos zero neg)
>    (case (truncate (signum num))
>      (1 pos)
>      (0 zero)
>      (-1 neg)))
>
>
> Now one example Graham gives is:
> (mapcar #'(lambda (x)
>              (nif x 'p 'z 'n))
>          '(0 2.5 -8))
>
> which results in the list (Z P N).
> You can do the same thing in Python.
> But it gets hairier if we want to make function calls that
> have side effects.
> Let me add these three functions:
>
> (defun p ()
>    (print "very positive")
>    "positive")
>
> (defun z ()
>    (print "no no")
>    "zero")
>
> (defun n ()
>    (print "very negative")
>    "negative")
>
>
> And now see what happens:
>
> CL-USER> (mapcar #'(lambda (x)
> 		     (nif x (p) (z) (n)))
> 		 '(0 2.5 -8))
>
> "very positive"
> "no no"
> "very negative"
> "very positive"
> "no no"
> "very negative"
> "very positive"
> "no no"
> "very negative"
> ("zero" "positive" "negative")
>
> The messages were printed in each case.
> To stop that I need lazy evaluation:
> CL-USER> (mapcar #'(lambda (x)
> 		     (funcall
> 		      (nif x
> 			   #'(lambda () (p))
> 			   #'(lambda () (z))
> 			   #'(lambda () (n)))))
> 		 '(0 2.5 -8))
>
> "no no"
> "very positive"
> "very negative"
> ("zero" "positive" "negative")
>
>
> I put the calls to the functions p, z and n into a function object.
> In some languages it would look a bit cleaner, for example Ruby.
> They have a single name space and don't need funcall and lambda is
> shorter. But still, we need to add several tokens. Maybe Haskell has
> built in support for that.
>
>
> Now with nif as a macro:
> (defmacro nif (expr pos zero neg)
>    `(case (truncate (signum ,expr))
>       (1  ,pos)
>       (0  ,zero)
>       (-1 ,neg)))
>
> It is a bit more complex as the function. It has one ` and 4 ,s
> extra.
> But now we can express the problem very well:
>
> CL-USER> (mapcar #'(lambda (x)
> 		     (nif x (p) (z) (n)))
> 		 '(0 2.5 -8))
>
> "no no"
> "very positive"
> "very negative"
> ("zero" "positive" "negative")
>
> And the first example also still works the same way.

Ruby:

def p
  puts "very positive"
  "positive"
end
    ==>nil
def z
  puts "only zero"
  "zero"
end
    ==>nil
def n
  puts "very negative"
  "negative"
end
    ==>nil
def nif num, pos, zero, neg
  x = [ zero, pos, neg ][ num <=> 0 ]
  x.call
  rescue
  x
end
    ==>nil
[0, 2.5, -8 ].map{|x| nif(x, :p, :z, :n)}
    ==>[:z, :p, :n]
[0, 2.5, -8 ].map{|x| nif(x, proc{p}, proc{z}, proc{n})}
only zero
very positive
very negative
    ==>["zero", "positive", "negative"]
From: André Thieme
Subject: Re: Macro unnecessary
Date: 
Message-ID: <gfftbl$3o9$1@news.eternal-september.org>
William James schrieb:
>  Andr� Thieme wrote
> 
> Ruby:
> 
> def p
>   puts "very positive"
>   "positive"
> end
>     ==>nil
> def z
>   puts "only zero"
>   "zero"
> end
>     ==>nil
> def n
>   puts "very negative"
>   "negative"
> end
>     ==>nil
> def nif num, pos, zero, neg
>   x = [ zero, pos, neg ][ num <=> 0 ]
>   x.call
>   rescue
>   x
> end
>     ==>nil
> [0, 2.5, -8 ].map{|x| nif(x, :p, :z, :n)}
>     ==>[:z, :p, :n]
> [0, 2.5, -8 ].map{|x| nif(x, proc{p}, proc{z}, proc{n})}
> only zero
> very positive
> very negative
>     ==>["zero", "positive", "negative"]

Why not calling it like this?
[0, 2.5, -8].map{|x| nif(x, p(), z(), n()}

Or
[0, 2.5, -8].map{|x| nif(x
                          print "A"
                          print "B"
                          print "C"}

When you use �if� in Ruby you don�t have to put a comma between the
arguments. What fits your programming style better?

{if myObj == 15,
   proc(print "myObj has the value 15")}

vs.

if myObj == 15
   print "myObj has the value 15"

Please offer the Ruby version that allows you to use �nif� as if you
were using �if�.


Andr�
-- 
Lisp is not dead. It�s just the URL that has changed:
http://clojure.org/