Choosing/evaluating macro argument forms - function

The Common Lisp case macro always defaults to eql for testing whether its keyform matches one of the keys in its clauses. I'm aiming with the following macro to generalize case to use any supplied comparison function (although with evaluated keys):
(defmacro case-test (form test &rest clauses)
(once-only (form test)
`(cond ,#(mapcar #'(lambda (clause)
`((funcall ,test ,form ,(car clause))
,#(cdr clause)))
`,clauses))))
using
(defmacro once-only ((&rest names) &body body)
"Ensures macro arguments only evaluate once and in order.
Wrap around a backquoted macro expansion."
(let ((gensyms (loop for nil in names collect (gensym))))
`(let (,#(loop for g in gensyms collect `(,g (gensym))))
`(let (,,#(loop for g in gensyms for n in names collect ``(,,g ,,n)))
,(let (,#(loop for n in names for g in gensyms collect `(,n ,g)))
,#body)))))
For example:
(macroexpand '(case-test (list 3 4) #'equal
('(1 2) 'a 'b)
('(3 4) 'c 'd)))
gives
(LET ((#:G527 (LIST 3 4)) (#:G528 #'EQUAL))
(COND ((FUNCALL #:G528 #:G527 '(1 2)) 'A 'B)
((FUNCALL #:G528 #:G527 '(3 4)) 'C 'D)))
Is it necessary to worry about macro variable capture for a functional argument (like #'equal)? Can such arguments be left off the once-only list, or could there still be a potential conflict if #'equal were part of the keyform as well. Paul Graham in his book On Lisp, p.118, says some variable capture conflicts lead to "extremely subtle bugs", leading one to believe it might be better to (gensym) everything.
Is it more flexible to pass in a test name (like equal) instead of a function object (like #'equal)? It looks like you could then put the name directly in function call position (instead of using funcall), and allow macros and special forms as well as functions?
Could case-test instead be a function, instead of a macro?

Variable capture
Yes, you need to put the function into the once-only because it can be created dynamically.
The extreme case would be:
(defun random-test ()
(aref #(#'eq #'eql #'equal #'equalp) (random 4)))
(case-test foo (random-test)
...)
You want to make sure that the test is the same in the whole case-test form.
Name vs. object
Evaluating the test argument allows for very flexible forms like
(case-test foo (object-test foo)
...)
which allows "object-oriented" case-test.
Function vs. macro
Making case-test into a function is akin to making any other conditional (if and cond) into a function - how would you handle the proverbial
(case-test "a" #'string-equal
("A" (print "safe"))
("b" (launch missiles)))

Related

Common Lisp: Is there a version of `labels` with a type specifier?

Is there a Common Lisp construct that is to labels what defmethod is to defun? That is, I would like to use labels (or something similar) to define several local functions that would have the same name but differ in parameters they accept and let the compiler choose among them.
As an MWE, I would like to achieve the following functionality
(defmethod write-first-item-type ((lst list))
"Writes the type of the first item in lst."
(labels ((write-single ()
(format t "a single float"))
(write-double ()
(format t "a double float")))
(format t "The first item is: ~A.~%"
(cond ((eql (type-of (car lst)) 'single-float)
(write-single))
((eql (type-of (car lst)) 'double-float)
(write-double))
(t
(format t "unknown"))))))
with something like
(defmethod write-first-item-type ((lst list))
"Should write the type of the first item in lst but does not compile."
(label-method ((write-type ((item single-float))
(format t "a single float"))
(write-type ((ifem double-float))
(format t "a double float")))
(format t "The first item is: ~A.~%"
(write-type (car lst)))))
Admitably, my MWE is rather silly. My actual motivation is that while cleaning up my source code I would like to put bunches of little helper functions (created with defmethod) into the one big function that uses them. Feel free to comment on this motivation as well!
See here why the initial proposal for local generic bindings were removed from CLOS:
Issue GENERIC-FLET-POORLY-DESIGNED Writeup
I am not aware of a built-in functionality of that kind. However, such kind of feature is not hard to build from scratch, as long as other parts of OOP are not required (i.e., inheritance and other dispatching orders).
If you would never call (call-next-method) in you method-labels code (as you won't do in labels code, it is just a matter of defining a dispatch table and dispatch "methods" accordingly. To break it down, it should be a local macro that:
defines a local variable (gensym) as the dispatch table;
registers functions as closures together with its specialized lambda list into the dispatch table;
register a local "generic" function, that when called, find the function to call from the dispatch table according to the parameters supplied.
And to find the function, you may or may not need to:
sort the dispatch table (but if there is not eql specifier nor inheritance, this can be avoided)
write dedicated code to match against the specialized parameters for &optional, &key, and other options of the lambda list (or you can use destructuring-bind, but you'll need to transform the specialized lambda list into a lambda list) - there might be tools for that, but I am unaware of.
In the simplest case where the number of parameters in the lambda list is fixed, the dispatch can be as plain as a few (e)typecase.
The local/global methods are for you probably a matter of namespaces.
That you don't want to pollute the current namespace with this matter.
How about to create on-the-fly small namespace/packages and use therein the "global" methods of CLOS?
It would have nearly the same effect of having local functions which are "invisible" for other functions.
(defpackage my-sub
(:use :cl)
(:export #:write-type))
(in-package :my-sub)
(defgeneric write-type (x)
(:documentation "write type of x"))
(defmethod write-type ((x float))
(typecase x
(single-float "single float")
(double-float "double float")))
(defmethod write-type ((x string))
"string")
(defpackage my-main
(:use :cl
:my-sub))
(in-package :my-main)
(defmethod write-first-item-type ((lst list))
(format nil "first item is: ~A." (my-sub:write-type (car lst))))
(write-first-item-type '("a" b c))
;; "first item is: string."
(write-first-item-type '(1.0 2 3))
;; "first item is: single float."
(write-first-item-type '(1.0d0 2 3))
;; "first item is: double float."
defmethod anyway can only dispatch for classes - builtin or self-made.
But you want to dispatch for types.
So I put example for members of class float (single-float and double-float) - dispatch them manually useing typecase.
And of built-in class string.
Use packaging for namespace separation.
However just manual dispatch is better in this case.
(defmethod write-first-item-type ((lst list))
(labels ((write-type (x)
(typecase x
(single-float "single float")
(double-float "double float")
(string "string")
(t "unkown"))))
(format nil "The first item is: ~A." (write-type (car lst)))))

Common Lisp references to functions

There seems to be a number of different ways of referring to a function in Common Lisp:
via symbol, where the symbol appears (unquoted) as the car of a form as in (1+ 2) => 3, or in a functional argument position as in (mapcar '1+ '(1 2 3)) => (2 3 4);
via function object, where the (interpreted or compiled) function object can appear in functional argument position as in (mapcar #'1+ '(1 2 3)) => (2 3 4) or (mapcar (symbol-function '1+) '(1 2 3)) => (2 3 4), but not as the car of a form as in (#'1+ 2) => error or ((symbol-function '1+) 2) => error;
via lambda expression, where the lambda expression appears as the car of a lambda form as in ((lambda (x) (1+ x)) 2) => 3, or in a functional argument position as in (mapcar (lambda (x) (1+ x)) '(1 2 3)) => (2 3 4) [However, the Hyperspec does not recognize lambda expression as a "function designator"].
Of these three "ways", to me the first seems somewhat out of place, because it seems to complicate the fundamental guideline that Common Lisp operators evaluate their arguments only once. And if, in the example above, '1+ is evaluated, it would produce the symbol 1+, not the function named by the symbol. In this case, there must be an additional evaluation, possibly symbol-function, to get at the function object. Evidently, this is simply a convenience, but it seems to break with consistency. (The consistent form #'1+ is almost as simple.) My question is 'Are there any examples where using a symbol for a function is required (other than as the car of a form--although even this is not required, given lambda expressions), so that you cannot fully avoid expressions as in item 1 above?.
Symbols as names for objects: Designators
Often symbols are names for objects and can be used instead of these objects.
The concept that something like a symbol (or a string, a character) may stand for something else is called in Common Lisp a designator.
Some example for designators:
Function designator:
(funcall 'list 1 2 3)
<->
(funcall (symbol-function 'list) 1 2 3)
Class, or symbol that names a class:
(make-instance 'my-class)
<->
(make-instance (find-class 'my-class))
Package designator:
(package-use-list 'cl-user)
<->
(package-use-list (find-package 'cl-user))
<->
(package-use-list "CL-USER")
String designator:
(string-upcase 'f)
<->
(string-upcase (symbol-name 'f))
<->
(string-upcase #\f)
The first argument to FUNCALL thus is not defined as a function, but as a function designator. In this case either a function object or a symbol. If it is a symbol, then the global symbol function is retrieved.
Historically Lisp uses symbols as names for various kinds of objects. This is less prominent in some later dialects or derived languages.
function object vs. calling a named function vs. calling a symbol function
...(funcall (function foo) 1 2 3)...
...(funcall #'foo 1 2 3)...
Above calls the lexical function named foo. If there is no lexical function foo, it calls the symbol function of foo. The Lisp file compiler may assume that this is the same named function in the same file.
...(foo 1 2 3)...
Above calls the lexical function named foo. If there is no lexical function foo, it calls the symbol function of foo. The Lisp file compiler may assume that this is the same named function in the same file.
...(funcall 'foo 1 2 3)...
Above calls the global symbol function of foo. Thus there will be a lookup through the symbol.

In Lisp, how do you call a function from a macro, by name passed as an argument?

In Lisp, how do you call, from a macro, a function whose name is the symbol value of a symbol? I might be wrong but I think I'm right that a symbol is a variable.
Here is what I currently have:
(defmacro cfunc (a b) (list a b))
(defparameter foo 'my-func)
(defun my-func (data) '(some-code))
(cfunc foo data) ;does not work
(cfunc my-func data) ;works
I'm thinking I need to add some special character in front of foo to evaluate to its symbol value before being treated as a function. (cfunc foo data) creates and calls the function (foo data) instead of (my-func data). I suppose I could change the function defining in cfunc instead.
#'foo doesn't work, that gives (function foo) which cfunc returns and calls ((function foo) data). (symbol-value foo) can't work either. So I'm thinking I can't change what is given to cfunc but I can change the code of the function cfunc makes.
If someone has a specific page of a resource that tells me about evaluation and expansion using defmacro or the specifics of the special characters like # and ' or know the keywords I should be looking up, I'd appreciate it if that could be shared as well.
First, in the form (cfunc foo data), to what do you expect that data refers? I don't see any definition of it here. It's only mentioned incidentally as a parameter to the my-func function, which doesn't come into play for your expansion of cfunc. Perhaps you expect data to be available later as a special variable.
In any case, the problem you're running into is that Common Lisp is a "Lisp-2"; a variable present at the head of a function form doesn't automatically have its function cell accessed to coerce it to a function. In your case, foo is not a function bound in the environment; it's a variable whose value is a symbol (my-func)—one that in turn is bound to a function. To navigate this extra level of indirection, you have to request that that symbol's function cell be accessed, either via funcall or, in other cases, function.
Here are a few observations from the REPL:
> (symbol-value 'foo)
MY-FUNC
> (ignore-errors (symbol-function 'foo))
NIL
#<UNDEFINED-FUNCTION FOO {1004E22D23}>
> (fboundp 'foo)
NIL
> (ignore-errors (symbol-value 'my-func))
NIL
#<UNBOUND-VARIABLE MY-FUNC {1005324E93}>
> (symbol-function 'my-func)
#<FUNCTION MY-FUNC>
> (fboundp 'my-func)
T
Here we see that the symbol foo has a value binding—meaning it's a variable—but it has no function binding. Following foo through to my-func, we see that my-func has no value binding, but it does have a function binding.
To wrap up, your cfunc macro needs be written as follows:
(defmacro cfunc (a b)
(list 'funcall a b))
Alternately, you can write it like this:
(defmacro cfunc (a b)
`(funcall ,a ,b))
You mentioned originally that the form
(cfunc my-func data)
works as intended. With my proposed revision above, it won't work any longer, because now my-func is being treated as a value to be evaluated as an argument to funcall, when in fact it has no value cell (as it's a function). Hence, you'll have to adapt the form to the following:
(cfunc #'my-func data)
That's saying, "Look up the symbol 'my-func' in the function namespace, grab its value, and supply that function as an argument."
For a more precise treatment on the difference in handling such symbols-pointing-to-functions in Lisp-1 and -2, see Gabriel's Technical Issues of Separation in Function Cells and Value Cells—in particular, section 5, "Notational Simplicity".

Function application in Haskell

OK, it's been a long day and my brain may not function at Haskell level, but I just cannot understand one example from 'Learn You a Haskell'.
The section is called Function Application with $, and there is example of how $ may be defined:
($) :: (a -> b) -> a -> b
f $ x = f x
So far everything is clear. I understand all examples in the section, except for the last one:
ghci> map ($ 3) [(4+), (10*), (^2), sqrt]
[7.0,30.0,9.0,1.7320508075688772]
Here we map ($ 3) across list of functions and get result of application of those functions to 3. But how is this possible?
From the first code snippet it's clear that first argument is a function, we can even write:
*Main> ($) sqrt 4
2.0
Now ($ 3) is a partial application of function $, but 3 goes on function's position! So 3 is supposed to be a function or what?
There is another mystery: what the heck is (4+)? I know that (+4) is a partial application of function +, so (4+) should be partial application of function 4? Nonsense. What sort of trick works here?
($ 3) and (+ 4) aren't partial applications - they're operator sections. A partial application would look like (($) 3) or ((+) 4).
An operator section of the form (? x) (where ? stands for an arbitrary infix operator) binds the right operand of the operator, i.e. it is equivalent to \y -> y ? x. Likewise the operator section (x ?) binds the left operand and is thus equivalent to partial application.
I think what's tripping you up is operator sections. These let you partially apply an operator with either one of its arguments, so you can have the operators (+4) and (4+), where 4 is the the second then the first argument to + respectively. A more clear example might be ("Hello" ++) versus (++ "world"), the former prepends "Hello" onto the front of a string, while the latter appends "world" onto the end of a string.
This is contrasted with using operators in prefix form with just parens around it. In this form, the following are equivalent:
> let join = (++)
> join "Hello, " "world"
"Hello, world"
> (++) "Hello, " "world"
"Hello, world"
In prefix form, you treat the operator as a normal function and it accepts its first then second argument in order. In operator sections, it matters which side of the operator the argument is on.
So in your example, you have the partial application of ($ 3), you can reduce it as
map ($ 3) [(4+), (10*), (^2), sqrt]
[($ 3) (4+), ($ 3) (10 *), ($ 3) (^ 2), ($ 3) sqrt]
[4 + 3, 10 * 3, 3 ^ 2, sqrt 3]
[7.0, 30.0, 9.0, 1.7320508075688772]
You are getting confused with sections. A good way to grasp the concept of sections is playing with an example:
(<^>) :: Int -> Float -> Int
a <^> b = a
The above function is an useless function which returns the first parameter no matter what the second parameter is. But it accepts Int and then Float as input.
Now, because of sections you can apply with any one of their arguments:
λ> let a = (3 <^>)
λ> :t a
a :: Float -> Int
λ> let b = (<^> 3.0)
λ> :t b
b :: Int -> Int
See how the type of a and b are different because of sections.

How do I perform a function with side-effects over a vector?

The say-hello-to-first-person works fine, why doesn't say-hello-to-everyone?
(defpartial greeting [name]
[:p.alert "Hello " name ", how are you?"])
(defn say-hello [name]
(append $content (greeting name)))
(defn say-hello-to-first-person [names]
(say-hello (first names)))
(defn say-hello-to-everyone [names]
(map say-hello names))
(say-hello-to-first-person ["Chris" "Tom" "Jim" "Rocky"])
(say-hello-to-everyone ["Chris" "Tom" "Jim" "Rocky"])
You want doseq, Clojure's "foreach":
(doseq [name names]
(say-hello name))
map doesn't work because it produces a lazy sequence: Until you actually access the items in the sequence (which you don't here), none of them will be evaluated, and side effects won't occur.
Another option is to force evaluation by wrapping dorun around the map. Thinking about why this works may help your understanding (although doseq is the idiomatic approach here).
As #edbond says in his comment, map fn don't evaluate until necessary moment because map fn returns a lazy seq.
This is the doc of map fn
Returns a lazy sequence consisting of the result of applying f to the
set of first items of each coll, followed by applying f to the set
of second items in each coll, until any one of the colls is
exhausted. Any remaining items in other colls are ignored. Function
f should accept number-of-colls arguments.
If you need to be sure that the values are evaluate in one specific part of your code you can use doall or dorun