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"]
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/