not sure how to express this..
I've written a macro which takes two arguments. The first one essentially contains identifiers for generating a let expression. The second is the code to use inside the let expression (it wants to have access to these identifiers).
An example:
(match (Add {ast-> x}) (println x))
When the second argument is raw code, things work nicely. x binds to the x defined in the let expression (when macroexpanded it just shows as x). However, when the second argument is a macro which generates (println x), x expands to something like user/x.
Any good ideas on how to fix this?
It sounds like your second macro is defined as:
(defmacro foo
[]
`(println x))
This is incorrect as x will be namespace qualified. The correct version of the second macro in this case would be:
(defmacro foo
[]
`(println ~'x))
Now the x in the println call will be a literal x symbol and not namespace qualified.
Related
I have made a simple implementation of LISP using SICP metacircular evaluator as a reference, but even though I know and see the code I don't quite understand something about it. In the apply function that applies a closure to its arguments there is a piece of code that calls eval on each of it's arguments. If I quote an argument, then eval of that argument will give the raw form of that argument.
For clarity of the nature of the question and to present my current understanding of what is happening I will walk through an example.
(define f (lambda (x) (print x)))
(define g (lambda (x) (f x)))
; prints "bar" into the console
(g (quote bar))
First we call g with (quote bar) as the first parameter. The argument to g is evaluated to a symbol bar.
When g is evaluated, it passes it should evaluate it's argument and pass it to function f. But evaluating a symbol will cause a lookup from the environment, which doesn't seem to happen (if it did I should have printed an error, or something like that).
So what I want to know is why does the code print bar and not an error.
I walked through the code with the debugger and now I believe I understand. When g was called, a new environment was created with x associated with the symbol bar. And when a function is executed it's parameters are being evaluated to the things that are stored in the environment. So it's not bar that got evaluated, it's x that got evaluated to bar. And after x is evaluated there's no second-time evaluation.
The reason why quoted things appear to stay quoted is because they actually do get unquoted, but they don't get evaluated as arguments (they only get evaluated once you explicitly call eval on them).
Lets say i have fn begin: (begin "hello"). The result of `(begin "hello") will be (my-ns/begin "hello"). It's good. But now I do this: (def x '(begin "hello")). How can I expand x with backquote to get (my-ns/begin "hello"), not just (begin "hello")?
In the first example you used ` which is a reader macro named "syntax-quote", In the second example you used ' Which is a reader macro named "quote". Syntax-quote offers a couple of features beyond what quote offers:
unquoting with ~, ~#, etc
namespace expansion of symbols for use in writing hygenic macros.
Plain old quote does neither of these. So if you want namespace expansion in both examples use ` in both places. If you want to get an un-namespaced symbol in a syntax-quooted list you can use both of them together `(println ~'symbol-name) which will evaluate to simply (println symbol-name). (in this case symbol-name needs to be defined in the namespace where this is called (this process in known as "symbol capture")). The syntax-quote evaluates first to a call to quote, when in turn evaluates to the symbol.
If you are looking to expand a symbol that already exists for some reason, or you want to expand it in several different namespaces that both define it, you can use the ns-resolve function:
(ns-resolve *ns* 'begin)
so in your example you can map this over the list to print it with the NS qualified symbols:
user> (map #(if (symbol? %) (ns-resolve *ns* %) %) x)
(#'user/begin "hello")
Though this is not exactly the desired output because it refers to the var in that namespace rather than the symbol that resolves to this var. Things get a little dicey here because ` is a reader macro and we can't build calls to it in other macros. For instance I can think of no way to write:
(defmacro expand-x [thing]
`(syntax-quote-here ~thing)
Because as far as I know syntax-quote doesn't have a name (again because it is a reader macro) so there is nothing to use in place of syntax-quote-here in the above example. Though never fear, in a language with eval nothing is impossible, things just get arbitrarily ugly:
user> (eval (read-string (str "`" x)))
(user/begin "hello")
PS: don't actually use this last example or gremlins will inhabit your code for all time
I have a simple macro:
(defmacro macrotest [coll]
`(let [result# ~(reduce + coll)]
result#))
Why, if this code works:
(macrotest [1 2 3])
doesn't this code work?
(def mycoll [1 2 3])
(macrotest mycoll)
Symbols are not the same as the value they point to.
One of the important considerations about macros is not just how they create new code, but also how they handle the arguments you pass in.
Consider this:
(def v [1 2 3])
(somefunction v)
The argument v passed to this function does not arrive inside the function as a symbol, v. Instead, because this is a function call, the arguments are evaluated first, then their resulting value is passed into the function. So the function will see [1 2 3].
But macros are not like this, though it is easy to forget. When you call:
(somemacro v)
v is not evaluated and does not pass in [1 2 3]. Inside the macro, all you get is a symbol, v. Now, your macro can emit the symbol you passed in, in the code the macro creates, but it cannot do anything with the value of v unless you add an extra level of evaluation using eval (see footnote -- not recommended).
When you unquote the macro argument, you get a symbol, not a value.
Consider this example:
user> (def a 5)
#'user/a
user> (defmacro m [x] `(+ ~x ~x))
#'user/m
user> (m a)
10
user> (macroexpand '(m a))
(clojure.core/+ a a)
user> (defmacro m [x] `~(+ x x))
#'user/m
user> (m a)
ClassCastException clojure.lang.Symbol cannot be cast to java.lang.Number clojure.lang.Numbers.add (Numbers.java:126)
This would be like trying to do this at the REPL: (+ 'a 'a) Adding symbols, not adding the values those symbols point to.
You might look at these two different definitions of the macro m and think they are doing the same thing. But in the second one, there is an attempt to do something with the symbol x, to do addition with it. In the first macro, the compiler is not asked to do anything with x. It merely is told to emit the addition operation, which will then be actually processed at runtime.
Remember that the point of a macro is to create code not perform runtime activity that a function would do. The code that is created is then immediately run (via implicit eval), so it's easy to forget this separation, but they are two distinct steps.
As a final exercise, pretend you are a compiler. I want you to tell me right now what is the resulting value of this code:
(* t w)
Well? It's impossible. There is no way you can tell me the answer to this question because you have no idea what t and w are. However, later, at runtime, when these presumably have a value, then it will be easy.
And that's what macros do: they output stuff for the runtime to handle.
(Very much not recommended but to help further describe what's happening, this works:)
user> (def a 1)
user> (defmacro m [x] `~(+ (eval x) (eval x)))
user> (m a)
2
Imagine the following code to dynamically create a macro:
(def a (list '+ 1 2))
(def b (list '- 10 5))
(def c (list '/ 22 2))
(defmacro gg [h]
(let [k# `~h]
k#))
The intent is to pass a vector of symbols to a macro, do some evaluation on each element of the vector such that it returns a nice macro-esque form, then have the macro combine them into a nice macro and evaluate it. The above example works all except the actual evaluation.
When I run it I get:
(gg [a b c])
=> [(+ 1 2) (- 10 5) (/ 22 2)]
What is the secret to passing a symbol that is a list of symbols and getting a macro to evaluate them? I have tried lots of combinations of quoting and have yet to hit the right one.
The real purpose of this question is to build an Archimedes Ogre query based on a definition of a path through the graph. If someone has an example of that, I would be grateful.
EDIT:
(defmacro gg2 [h]
`(do ~#(map identity h)))
(macroexpand '(gg2 [a b c]))
=> (do a b c)
(gg2 [a b c])
=> (/ 22 2)
I was hoping to get 11 rather than the form.
You don't need a macro. Macros don't do what you're looking for here. What you are looking for is eval.
(def a '/)
(def b 22)
(def c 2)
(eval (list* [a b c]))
=> 11
Of course, you can write a macro which expands into (eval (list* ...)) if you want. It could just as well be a function though.
This is a very common mistake when starting out with macros; trying to write a macro which depends on the run-time value of its arguments. Macros run at compile-time, and generally the values of the symbols which you pass to a macro are not yet available when the macro is expanded.
About the use of eval, some cautions are in order. No one said it better than Paul Graham:
Generally it is not a good idea to call eval at runtime, for two reasons:
It’s inefficient: eval is handed a raw list, and either has to compile it on the spot, or evaluate it in an interpreter. Either way is slower than compiling the code beforehand, and just calling it.
It’s less powerful, because the expression is evaluated with no lexical context. Among other things, this means that you can’t refer to ordinary variables visible outside the expression being evaluated.
Usually, calling eval explicitly is like buying something in an airport gift-shop. Having waited till the last moment, you have to pay high prices for a limited selection of second-rate goods.
I'm trying to pass a function as an argument and call that function within another function.
A piece of my code looks like this:
(defun getmove(strategy player board printflag)
(setq move (funcall strategy player board))
(if printflag
(printboard board))
strategy is passed as a symbol represented in a two dimensional list as something such as 'randomstrategy
I keep getting the error:
"FUNCALL: 'RANDOMSTRATEGY is not a function name; try using a symbol instead...
When I replace strategy with 'randomstrategy it works fine.
I can also call randomstrategy independently.
What is the problem?
The problem is that the variable strategy does not contain the symbol randomstrategy but rather the list (!) 'randomstrategy (which is a shorthand notation for (quote randomstrategy)).
Now, you could, of course, extract the symbol from the list by way of the function second, but that would only cover the real problem up, which is probably somewhere up the call chain. Try to determine why the argument that is passed to function getmove is 'randomstrategy, not randomstrategy as it should be. (Maybe you erroneously used a quote inside of a quoted list?)
Oh, and don't let yourself be confused by the fact that (funcall 'randomstrategy ...) works: the expression 'randomstrategy does not, after all, evaluate to itself, but to the symbol randomstrategy.
Is strategy a variable with a functional value? If not, then use the #' syntax macro before it, i.e. #'strategy, or just (if the function is global) 'strategy.
WHY? Because arguments of a funcall call are evaluated. And your strategy symbol is just a variable name in this case. Variable this value 'RANDOMSTRATEGY. But you should give to funcall a function. How to access function if we have a symbol?
Three cases:
Symbol may denote a variable with functional value.
Symbol may denote a global function (symbol-function is the accessor in this case.
Symbol may denote a local function (flet, labels and so on).
It looks like you forgot to define RANDOMSTRATEGY function.
(defun RANDOMSTRATEGY …)
Hmm
FUNCALL: 'RANDOMSTRATEGY
Maybe you have (setq strategy ''RANDOMSTRATEGY)?
Then strategy will evaluate to 'RANDOMSTRATEGY.
Did you notice ' before the symbol name? 'RANDOMSTRATEGY <=> (quote RANDOMSTRATEGY); it is not a proper function name.
Have you set strategy anywhere? It looks like a scoping issue.
Try this
(setq strategy 'randomstrategy)
(setq move (funcall strategy player board))
Not seeing the code, I'm imagining you're doing something like this:
(defun randomstrategy (a b c) ...)
and then doing this:
(getmove 'randomstrategy x y z)
What you want to do is pass the function "randomstrategy" to getmove using #':
(getmove #'randomstrategy x y z)
In CommonLisp, #' yields the function bound to the symbol, which is
what you want to pass to getmove.