I noticed some complaints about a lack of the equivalent of Haskell's point-free programming style for Arc, I decided to implement one of Haskell's more useful operators.
The $ operator in Haskell breaks a statement into two statements. It executes the second and then uses the output as the final variable to the first.
e.g.
main = print $ "hello" ++ " " ++ "world"
is the same as
main = print ( "hello" ++ " " ++ "world )
Lacking infix operators I cannot recreate the functionality exactly. Nor, given that Arc is a lisp and doing so would be decidedly unlispy, would I want to. Instead I have created the following
chain
macro that will allow a similar form of composition. I do not believe it would be difficult to turn the following into a mutli-argument compose
macro either.;; chains similar to haskells $ operator.
(mac chain args
(if (is 0 (len args))
nil
(is 1 (len args))
(args 0)
t
(let n (uniq)
`(let ,n ,(eval `(chain ,@(cdr args)))
(eval (+ ',(args 0) (list ,n)))))))
This allows for the following :
arc> (chain (+ 3) (+ 4 5) (- 2) (+ 6) 8)
0
arc> (chain)
nil
arc> (chain (+ 4))
4
arc> (chain (+ 4) (+ 4 8))
16
arc> (chain (+ 4) (+ 5 6) (- 5) 50)
-30
arc> (chain (+ 3) ([/ _ 3]) ([- _ 2]) (+ 100) 12)
119/3
arc>
If it didn't wrap a (list ...) around each return value and required each return value to be a list in its own right ( or only wrapped non-cons structures ) it would have similar semantics to perls execution model, compressing each list into the current argument chain.
The chain macro needs all of the function calls to be wrapped in paren for it to operate properly, since it takes each value and appends it to the next function.
No comments:
Post a Comment