I would like to make a macro that would create a function call in Common Lisp - function

I have a bunch of functions named as follows
(test-1)
(test-2)
(test-3)
(test-n)...
I would like to make a macro or function called '(magically-add)' that would create a function call out of a preset variable value inside the macro or function and a parameter supplied to the macro. For example the preset variable value, lets call the variable 'foo' inside the macro would be
(setf foo test-)
and to create one of the functions at the top of my post the supplied parameter would equal 1, 2, 3 or n.
so when I run it, I would run it as below, choosing '1' in this case and saving the output to a variable with 'defparameter'.
(defparameter bar (magically-add 1))
so now before I enter just "bar" without quotes at the repl I know the contents of it is a function call that looks like this,
(test-1) so when I run 'bar' at the repl
as so
REPL> bar
The output is whatever the output of the function (test-1) would have been had I ran that at the repl. so after running (magically-add) to concatenate, somehow, 'test-' from inside the macro and '"1"' without quotes the variable I supplied to the macro then 'bar' would equal '(test-1)'. So lets say the normal output of '(test-1)' would be '"Hello World"' then running 'bar' at the repl would have the same output as below
OUTPUT>"Hello World"
Anyone like to help me create this 'magical function'? Thanks in advance for any takers.
Edit:
I was wondering what would I do if , lets say this was test-1
(defun test-1 (matrix type row cols)
(find-element matrix type rows cols))
If I called
(defmacro magically-add (matrix type rows cols &optional (base 'test-))
(list (intern (concatenate 'string
(symbol-name base)
(write-to-string type)))))
then
(magically-add hypothetical-matrix double 0 0)
I get: 'Invalid number of arguments 0'
It seem that magically-add will call the function test-1 but would need updating to pass parameters to it...That my ultimate goal to actually pass parameters to magically-add and have the parameters end up as arguments to test-1. Any advice on this?? Thanks again for that genius answer btw.
Edit 2:
I do apologize I was using 'test-1 .. n' as a catch all Previously I added the type as a parameter....but its actually named 'test-double' and the name tells which one, i/e 'test-double' 'test-float' 'test-int', to run. So sorry about that, just a little pitfall of simplifying.
So with your latest edit using my '(test-double)' function as example:
(defun test-double (matrix rows cols)
(find-element matrix rows cols))
I can call '(magically-add 'test- 'double matrix 0 0)' but the only question now is in the beauty of it. I'd like to be able to call instead of
'(magically-add 'test- 'double matrix 0 0)'
just
'(magically-add 'test 'double matrix 0 0)'
So if I rename my function to (testdouble) it's possible but kinda ugly, but if I call
(defun magically-add (base number &rest args)
(apply (intern (concatenate 'string
(symbol-name base)
"-"
(write-to-string number)))
args))
It's possible...Can you give me one last piece of advice, on how would I call with keywords as below. Lisp keywords are so beautiful(different colors and all). Then I can access all my "'test-"' as below....I think that might be the ultimate...especially if its quicker, again High Performance library...but what you provided so far is just awesome I'll have to compare the two for the real winner...Thank you very much for taking the time to help me this.
(magically-add :test :double matrix 0 0)
Will post benchmarking of these functions vs running just the originals later today under this line.
On a hundred thousand runs with a dotimes and nothing else in the dotimes but the function, the original function and Frank's did about the same time 5 seconds on a fresh emacs.
On a billion runs with a dotimes and nothing else in the dotimes but the function the original function and Frank's did drastically different
the original took about 41 seconds to complete a billion iterations...not bad...
Frank's function was understandably slower - It took 41 seconds to complete 20 million iterations and as for a billion...Well I apologize but I stopped counting after 8 minutes...
So if anybody has an idea how to speed up this style of coding to make it comparable I'd love to hear it. Since these are functions for high performance library for now I'll just be craft with the names as C++ libraries do sometimes and call them (test-int) (test-float) (test-double)....etc. For a lot of functions that makes it easy to remember like in c++ doing Mat.at or Mat.cols or Mat.rows.

I hope I understand your idea right. What's about this?
(defun magically-add (number &optional (base 'test-))
(funcall (intern (concatenate 'string
(symbol-name base)
(write-to-string number)))))
It converts the number as well as the base into a string, concatenates it, then converts it back into a symbol for calling it.
Testing:
CL-USER 1 > (defun test-1 () "hello World")
TEST-1
CL-USER 2 > (magically-add 1)
"hello World"
Note that this holds only for dynamically scoped functions – that means it does not work for functions defined with labels or flet. (For a similar reason why you cannot get the value of a lexical scoped symbol – for more details have a look here) If you want to have that, you can use a macro:
(defmacro magically-add (number &optional (base 'test-))
(list (intern (concatenate 'string
(symbol-name base)
(write-to-string number)))))
Now it works for lexically scoped functions, too:
CL-USER 3 > (flet ((test-1 () "Hello again")) (magically-add 1))
"Hello again"
EDIT:
To answer to your problem after your edit – There two major things wrong.
First, you omitted the number variable and converted your new variable type to a string. So you will call a function named test-double that doesn't exist. Second, you call that function without any arguments. You must add them to the function-call.
Here is a version of magically-add that receives arbitrary number of arguments, but you MUST give the base variable to it. It doesn't default to test- anymore. It also uses the DEFUN version because of Rainer Joswigs comment below. Being restricted to only using plain numbers for the number argument (and not variables and not elements of lists) seems to be a greater inconvenience to me than not using lexically scoped functions.
(defun magically-add (base number &rest args)
(apply (intern (concatenate 'string
(symbol-name base)
(write-to-string number)))
args))
So the first two arguments are for contructing the function name and all the rest arguments used to call this function:
CL-USER 1 > (defun test-1 (foo bar baz) (list foo bar baz))
TEST-1
CL-USER 2 > (magically-add 'test- 1 "hi" 42 'symbol)
("hi" 42 SYMBOL)
If someone has an idea how to do something similar to that with not being restricted to dynamically scoped functions, I'd be interested, too.
EDIT 2:
To answer your second edit: There's quiet few to change to achieve that. write-to-string gives you a string of the printed representation of number. Of course, if it's the keyword :double, you'll get ":DOUBLE". You can just use symbol-name again to retrieve the name of the keyword – which is just "DOUBLE".
(defun magically-add (praefix postfix &rest args)
(apply (intern (concatenate 'string
(symbol-name praefix)
"-"
(symbol-name postfix)))
args))

Related

Clojure, can macros do something that couldn't be done with a function

I'm learning Clojure macros, and wonder why we can't use just functions for metaprogramming.
As far as I know the difference between macro and function is that arguments of macro are not evaluated but passed as data structures and symbols as they are, whereas the return value is evaluated (in the place where macro is called). Macro works as a proxy between reader and evaluator, transforming the form in an arbitrary way before the evaluation takes place. Internally they may use all the language features, including functions, special forms, literals, recursion, other macros etc.
Functions are the opposite. Arguments are evaluated before the call, return value is not after return. But the mirroring nature of macros and functions makes me wonder, couldn't we as well use functions as macros by quoting their arguments (the form), transforming the form, evaluating it inside the function, finally returning it's value. Wouldn't this logically produce the same outcome? Of course this would be inconvenient, but theoretically, is there equivalent function for every possible macro?
Here is simple infix macro
(defmacro infix
"translate infix notation to clojure form"
[form]
(list (second form) (first form) (last form)))
(infix (6 + 6)) ;-> 12
Here is same logic using a function
(defn infix-fn
"infix using a function"
[form]
((eval (second form)) (eval (first form)) (eval (last form))))
(infix-fn '(6 + 6)) ;-> 12
Now, is this perception generalizable to all situations, or are there some corner cases where macro couldn't be outdone? In the end, are macros just a syntactic sugar over a function call?
It would help if I read the question before answering it.
Your infix function doesn't work except with literals:
(let [m 3, n 22] (infix-fn '(m + n)))
CompilerException java.lang.RuntimeException:
Unable to resolve symbol: m in this context ...
This is the consequence of what #jkinski noted: by the time eval acts, m is gone.
Can macros do what functions cannot?
Yes. But if you can do it with a function, you generally should.
Macros are good for
deferred evaluation;
capturing forms;
re-organizing syntax;
none of which a function can do.
Deferred Evaluation
Consider (from Programming Clojure by Halloway & Bedra)
(defmacro unless [test then]
(list 'if (list 'not test) then)))
... a partial clone of if-not. Let's use it to define
(defn safe-div [num denom]
(unless (zero? denom) (/ num denom)))
... which prevents division by zero, returning nil:
(safe-div 10 0)
=> nil
If we tried to define it as a function:
(defn unless [test then]
(if (not test) then))
... then
(safe-div 10 0)
ArithmeticException Divide by zero ...
The potential result is evaluated as the then argument to unless, before the body of unless ignores it.
Capturing Forms and Re-organizing Syntax
Suppose Clojure had no case form. Here is a rough-and-ready substitute:
(defmacro my-case [expr & stuff]
(let [thunk (fn [form] `(fn [] ~form))
pairs (partition 2 stuff)
default (if (-> stuff count odd?)
(-> stuff last thunk)
'(constantly nil))
[ks vs] (apply map list pairs)
the-map (zipmap ks (map thunk vs))]
(list (list the-map expr default))))
This
picks apart the keys (ks) and corresponding expressions (vs),
wraps the latter as parameterless fn forms,
constructs a map from the former to the latter,
returns a form that calls the function returned by looking up the
map.
The details are unimportant. The point is it can be done.
When Guido van Rossum proposed adding a case statement to Python, the committee turned him down. So Python has no case statement. If Rich didn't want a case statement, but I did, I can have one.
Just for fun, let's use macros to contrive a passable clone of the if form. This is no doubt a cliche in functional programming circles, but took me by surprise. I had thought of if as an irreducible primitive of lazy evaluation.
An easy way is to piggy-back on the the my-case macro:
(defmacro if-like
([test then] `(if-like ~test ~then nil))
([test then else]
`(my-case ~test
false ~else
nil ~else
~then)))
This is prolix and slow, and it uses stack and loses recur, which gets buried in the closures. However ...
(defn fact [n]
(if-like (pos? n)
(* (fact (dec n)) n)
1))
(map fact (range 10))
=> (1 1 2 6 24 120 720 5040 40320 362880)
... it works, more or less.
Please, dear reader, point out any errors in my code.

Is there a standard argument sequence identity function in Clojure?

Is there a function in the Clojure standard library equivalent to the following?
(fn [& args] args)
If not, why?
Example usage:
(take 10 (apply (fn [& args] args) (range)))
;=> (0 1 2 3 4 5 6 7 8 9)
;; ironically, map isn't lazy enough, so let's take it up to 11
(defn lazy-map [f & colls]
(lazy-seq (cons (apply f (map first colls))
(apply lazy-map f (map rest colls)))))
(defn transpose [m]
(apply lazy-map (fn [& args] args) m))
(defn take-2d [rows cols coll]
(take rows (map (partial take cols) coll)))
(take-2d 3 3 (transpose (map (partial iterate inc) (range))))
;=> ((0 1 2) (1 2 3) (2 3 4))
Please note that I am not asking for a transformative, eager function such as vector or list.
There is no such function, you are free to implement and use it as you like:
(defn args [& args] args)
(set (map type (apply map args [[1 2 3][4 5 6][7 8 9]])))
=> #{clojure.lang.ArraySeq}
Why isn't it already available?
This is rarely fruitful question: not only we don't know what happens in the mind of implementors, it is impracticable to ask them to justify or document why they did not do something. Was adding this function ever considered? How can we know? Is there really a reason, or did it just happen?
On the other hand, I agree that args feels simpler because it passes around an already existing immutable sequence.
I also can understand if you think that not converting the arguments as a persistent list in the first place is better, if only for the sake of parcimony.
But this is not how it is implemented, and the overhead of using list is really negligible (and specialized when building from an instance of ArraySeq).
You are supposed to code to an interface and never look behind the curtain, and from this point of view, list and args are equivalent, even though they do not return identical results.
You added a remark about laziness, and you are right: if you ever need to take the arguments from a variadic function and pass it to a function which operates on sequences, The version with list will consume all the given arguments whereas args will not. In some cases, as with (apply list (range)), where you literally pass an infinite number of arguments, this might hang forever.
From that point of view, the little args function is in fact interesting: you can move from arguments to actual sequences without introducing potential problems.
I am however not sure how often this case happens in practice.
In fact, I have a hard time finding a use case where laziness in the argument list really matters as far as args is concerned.
After all, in order to pass an infinite sequence, the only way (?) is to use apply:
(apply f (infinite))
In order to have a use-case for args, that means that we want to convert from an argument list back to a single list so that another function g can use it as a sequence, like so:
(g (apply args (infinite)))
But in that case, we could directly call:
(g (infinite))
In your example, g would stand for cons inside lazy-map, but since f is given in input, we cannot write (cons (map ...) ...) directly. The example thus looks like a genuine use case for args, but you should document the function heavily because the snippet you gave is quite complex. I tend to think that giving an unbounded number of arguments to a function is a code smell: should every function with an [& args] signature avoid consuming all arguments because the given sequence might in fact be infinite, like lazy-map does? I'd rather have a single argument be a lazy sequence for this kind of usage (and pass identity where needed) instead of the whole argument list, to clarify the intent. But in the end, I am not strongly opposed to the use of args either.
So to conclude, unless you manage to convince Rich Hickey to add args as a core function, I am confident that almost nobody will want to depend on an external library which does just this1: it is unfamiliar, but also trivial to implement and mostly useless. The only reward is knowing that you skip a little transformation step which costs nothing in most cases. Likewise, do not worry about having to choose between a vector and a list: it has practically no influence on your code and you can still modify the code later if you can prove it is necessary.
Regarding laziness, while I agree that wrapping arguments in lists or vectors can be problematic with unbounded argument lists, I am not sure the problem actually arises in practice.
1. Of course, if it ever reaches clojure.core, everybody will be quick to say that is is a fundamental operation which is most useful and definitely idiomatic </cynic>
There's identity function. It takes an argument and just returns that argument. Clojure's identity is single arity though.
usage:
(identity 4) ;=> 4
(identity [1 2 3 4]) ;=> [1 2 3 4]
I don't think there's much sense in having the identity function with variable arity since Clojure functions return only one value. If you want to return multiple values from a function, then you can wrap them in a seq which you can later destructure. In that case you can have something like this:
(defn varity-identity [& args]
(map identity args))
(varity-identity 1 2 3 4 5) ;=> (1 2 3 4 5)
Hope this helps.

What is the difference between FUNCALL and #'function-name in common lisp?

I am reading through a book for homework, and I understand that using #' is treating the variable as a function instead of a variable. But I am a little hazy on FUNCALL. I understand that lisp makes object out of variables, so is the function name just a 'pointer' (may be a bad word, but hopefully you get what I mean), in which case you use #' to invoke it, or is funcall the only way to invoke them? ex.
(defun plot (fn min max step)
(loop for i from min to max by step do
(loop repeat (funcall fn i) do (format t "*"))
(format t "~%")))
couldn't I just do:
(defun plot (fn min max step)
(loop for i from min to max by step do
(loop repeat #'(fn i) do (format t "*"))
(format t "~%")))
I guess my confusion lies in what exactly is in the function names. When I read the book, it said that the variable's value is what will be the function object.
#'function-name is (function function-name). Nothing is called, evaluating either results in the function associated with function-name (the object representing the function). funcall is used to call functions.
See funcall and function in the HyperSpec.
Sample session using both:
CL-USER> (defun square (x) (* x x))
SQUARE
CL-USER> #'square
#<FUNCTION SQUARE>
CL-USER> (function square)
#<FUNCTION SQUARE>
CL-USER> (funcall #'square 3)
9
CL-USER> (funcall 'square 3)
9
The second invocation of funcall works because it also accepts a symbol as function designator (see the link for funcall above for details).
The #' and funcall notations are needed in Common Lisp because this language is a so-called "Lisp-2" where a given symbol can have two separate and unrelated main "meanings" normally listed as
When used as first element of a form it means a function
When used in any other place it means a variable
These are approximate explanations, as you will see in the following example that "first element of a form" and "any other place" are not correct definitions.
Consider for example:
the above code prints 144... it may seem surprising at first but the reason is that the same name square is used with two different meanings: the function that given an argument returns the result of multiplying the argument by itself and the local variable square with value 12.
The first and third uses of the name square the meaning is the function named square and I've painted the name with red color. The second and fourth uses instead are about a variable named square and are painted in blue instead.
How can Common Lisp decide which is which? the point is the position... after defun it's clearly in this case a function name, like it's a function name in the first part of (square square). Likewise as first element of a list inside a let form it's clearly a variable name and it's also a variable name in the second part of (square square).
This looks pretty psychotic... doesn't it? Well there is indeed some splitting in the Lisp community about if this dual meaning is going to make things simpler or more complex and it's one of the main differences between Common Lisp and Scheme.
Without getting into the details I'll just say that this apparently crazy choice has been made to make Lisp macros more useful, providing enough hygiene to make them working nicely without the added complexity and the removed expressiveness power of full hygienic macros. For sure it's a complication that makes it harder to explain the language to whoever is learning it (and that's why Scheme is considered a better (simpler) language for teaching) but many expert lispers think that it's a good choice that makes the Lisp language a better tool for real problems.
Also in human languages the context plays an important role anyway and there it's not a serious problem for humans that sometimes the very same word can be used with different meanings (e.g. as a noun or as a verb like "California is the state I live in" or "State your opinion").
Even in a Lisp-2 you need however to use functions as values, for example passing them as parameters or storing them into a data structure, or you need to use values as functions, for example calling a function that has been received as parameter (your plot case) or that has been stored somewhere. This is where #' and funcall come into play...
#'foo is indeed just a shortcut for (function foo), exactly like 'x is a shortcut for (quote x). This "function" thing is a special form that given a name (foo in this case) returns the associated function as a value, that you can store in variables or pass around:
(defvar *fn* #'square)
in the above code for example the variable *fn* is going to receive the function defined before. A function value can be manipulated as any other value like a string or a number.
funcall is the opposite, allowing to call a function not using its name but by using a value...
(print (funcall *fn* 12))
the above code will display 144... because the function that was stored in the variable *fn* now is being called passing 12 as argument.
If you know the "C" programming language an analogy is considering (let ((p #'square))...) like taking the address of the function square (as with { int (*p)(int) = &square; ...}) and instead (funcall p 12) is like calling a function using a pointer (as with (*p)(12) that "C" allows to be abbreviated to p(12)).
The admittely confusing part in Common Lisp is that you can have both a function named square and a variable named square in the same scope and the variable will not hide the function. funcall and function are two tools you can use when you need to use the value of a variable as a function or when you want a function as a value, respectively.

What is the advantage of a symbol that binds to a value and function at the same time?

In lisp, a symbol can be bound to both a value and a function at the same time.
For example,
Symbol f bound to a function
(defun f(x)
(* 2 x))
Symbol f bound to a value
(setq f 10)
So i write something like this:
(f f)
=> 20
What is the benefit of such a feature?
The symbol can have both a function and a value. The function can be retrieved with SYMBOL-FUNCTION and the value with SYMBOL-VALUE.
This is not the complete view. Common Lisp has (at least) two namespaces, one for functions and one for variables. Global symbols participate in this. But for local functions the symbols are not involved.
So what are the advantages:
no name clashes between identifiers for functions and variables.
Scheme: (define (foo lst) (list lst))
CL: (defun foo (list) (list list))
no runtime checks whether something is really a function
Scheme: (define (foo) (bar))
CL: (defun foo () (bar))
In Scheme it is not clear what BAR is. It could be a number and that would lead to a runtime error when calling FOO.
In CL BAR is either a function or undefined. It can never be anything else. It can for example never be a number. It is not possible to bind a function name to a number, thus this case never needs to be checked at runtime.
It's useful for everyday tasks, but the main reason is because of macros, you'll understand why once you study it.

Mechanism of a function in Scheme

Here it is a strange function in Scheme:
(define f
(call/cc
(lambda (x) x) ) )
(((f 'f) f) 1 )
When f is called in the command line, the result displayed is f .
What is the explanation of this mechanism ?..
Thanks!
You've just stumbled upon 'continuations', possibly the hardest thing of Scheme to understand.
call/cc is an abbreviation for call-with-current-continuation, what the procedure does is it takes a single argument function as its own argument, and calls it with the current 'continuation'.
So what's a continuation? That's infamously hard to explain and you should probably google it to get a better explanation than mine. But a continuation is simply a function of one argument, whose body represents a certain 'continuation' of a value.
Like, when we have (+ 2 (* 2 exp)) with exp being a random expression, if we evaluate that expression there is a 'continuation' waiting for that result, a place where evaluation continues, if it evaluates to 3 for instance, it inserts that value into the expression (* 2 3) and goes on from there with the next 'continuation', or the place where evaluation continues, which is (+ 2 ...).
In almost all contexts of programming languages, the place where computation continues with the value is the same place as it started, though the return statement in many languages is a key counterexample, the continuation is at a totally different place than the return statement itself.
In Scheme, you have direct control over your continuations, you can 'capture' them like done there. What f does is nothing more than evaluate to the current continuation, after all, when (lambda (x) x) is called with the current continuation, it just evaluates to it, so the entire function body does. As I said, continuations are functions themselves whose body can just be seen as the continuation they are to capture, which was famously shown by the designers of Scheme, that continuations are simply just lambda abstractions.
So in the code f first evaluates to the continuation it was called in. Then this continuation as a function is applied to 'f (a symbol). This means that that symbol is brought back to that continuation, where it is evaluated again as a symbol, to reveal the function it is bound to, which again is called with a symbol as its argument, which is finally displayed.
Kind of mind boggling, if you've seen the film 'primer', maybe this explains it:
http://thisdomainisirrelevant.net/1047