Why is it not possible to simulate "if-then-else" construct as a function in interpreter that supports function application?
Is "let" function in Scheme similar to "if-then-else"?
An if statement in Scheme looks like:
(if <predicate> <consequent> <alternate>)
and is defined such that the <consequent> is evaluated only when the <predicate> is not false and such that the <alternate> is evaluated only when the <predicate> is false. So you can see that something like
(if #t (display "okay") (shut-down-the-nsa))
would never actually shut down the NSA.
But, if if is a function, like:
(<operator> <operand> …)
then each <operand> is always evaluated. In the context of an if statement, that means both the <consequent> and <alternate> would be evaluated - not much of an if then.
Related
Given the following in one file:
(ns demo.first)
(defmacro ^:private private-macro [a] a)
And the following in another file:
(ns demo.second
(:require [demo.first :as first]))
(first/private-macro 10)
The call to the private macro in demo.second will throw: var: #'demo.first/private-macro is not public, as I expect.
Now, is there a way to have this call succeed, without making the macro public?
For functions, I can do:
(#'first/private-macro 10)
But with a macro, it throws: Wrong number of args (1) passed to: first/private-macro.
I'm looking to unit test this private macro, and personally prefer using private meta over an impl namespace. Which is why I'm hoping there's a solution to this.
Thank You.
UPDATE:
I found out that since defmacro is itself a macro, it first expands into a form which creates the symbol and Var for the macro and add its metadata to it.
Thus:
(defmacro ^:private private-macro [a] a)
First is processed by the defmacro macro, and expanded into:
(do
(clojure.core/defn ^{:private true} private-macro
([&form &env a] a))
(. (var ^{:private true} private-macro)
^{:line 487, :column 49}
(setMacro))
(var ^{:private true} private-macro))
As you can see, what then happens is that:
A private-macro fn is declared with defn, and set to private.
This function takes 3 arguments [&form &env a]. This is why we get the wrong number of argument (1) exception when using #' to call the macro.
The private-macro var is set as a macro by calling its setMacro method.
The private-macro var is returned.
In essence, what is happening is that if you call the function pointed to by the private-macro var, such as is the case when using the (#'private-macro) syntax, you're actually calling the function you see above, which takes 3 arguments. If your macro itself took more than one argument, that function would take 2 + the number of args of your macro.
So I still don't know how to call a private macro:
At first I thought stubbing out &form and &env with nils would work:
(#'first/private-macro nil nil 10)
And for my simple macro above it does, and return 10. But on more complicated macros, which need to be expanded further, it doesn't, and instead I get the macro-expansion returned to me ?!?
Then I thought I could use alter-meta! to remove the private meta from the macro temporarily before calling it. As such:
(alter-meta! #'first/private-macro
(fn [meta] (dissoc meta :private)))
(first/private-macro 10)
(alter-meta! #'first/private-macro
(fn [meta] (assoc meta :private true)))
But this only works at the REPL. Try to compile your code afterwards, and it seems the Compiler itself will throw the var: #'demo.first/private-macro is not public error, even before the alter-meta! has a chance to run, thus failing compilation.
I don't really know why #' doesn't work the same as a normal call to the macro, and why passing nil to the &form and &env doesn't work for all macros. And how to make alter-meta! work at compile time. So if someone does know, please answer away!
And for my simple macro above it does, and return 10. But on more complicated macros, which need to be expanded further, it doesn't, and instead I get the macro-expansion returned to me ?!?
Yes. As you discovered, when you write (defmacro m [x] (list x x)), you:
Define a function m that consumes forms as input and produces forms as output
Tell the compiler to look for calls like (m a) and replace them with the result of calling your m function at compile time
By calling #'m instead, you bypass step 2: there is no call to the macro m, and so the compiler does not call it at compile time or replace the calling code with the result. Since #'m is just a regular function which takes code as input and produces code, when you bypass the special compiler behavior and call it at runtime, you of course get code as a result (which you can't do much with because it's runtime already).
Good news, though: there's rarely a compelling reason to make a macro private anyway, since it can do no harm to let other namespace call it. All the private macro does is expand into code the client could have written by hand anyway. So, if you control this macro, you should probably just make it public. If you don't, then you can just write whatever code the macro would have written for you.
If you absolutely insist on calling someone else's private macro, then you can split the parts (1) and (2) up, in a way: define your own macro whose implementation delegates to the function backing the private var in the other namespace:
(defmacro cheat [& args]
(apply #'m &form &env args))
Because cheat is your own macro, you can call it in the usual way, engaging the compiler's "call this at compile time" mechanism. Then you delegate to the function that generates the code you want, passing &form and &env explicitly.
I'm trying a coding challenge that requires you to create code that compiles infinitely.
My first thought was a macro that expands to itself forever. I wrote up:
(defmacro a []
(a))
(a)
This doesn't actually produce anything, but I expected it to loop forever. Instead however, I get a nonsensical arity exception:
Wrong number of args (-2) passed to: infinite-compile/a, compiling:...
If I try to give it an argument for kicks, it now complains that the macro doesn't expect any arguments.
If I have it actually produce calls to itself:
(defmacro a []
`(a))
(a)
It fails with a StackOverflow, which I expected.
What's going on here? Why does it think I'm passing the macro "-2" arguments? The only possible thing I could think of is it has something to do with the 2 implicit & arguments that are passed to macros, but that's just a shot in the dark and doesn't actually explain what's going on.
To address the answer, this doesn't appear to be an issue with a multi-arity macro since it only has a 0-arity version. Also, explicitly passing the implicit arguments doesn't do anything:
(defmacro a []
(a &form &env))
This yields:
Compiler Exception clojure.lang.ArityException: Wrong number of args (2) passed to: infinite-compile/a, compiling:
You are expecting (a) to be macroexpanded during the definition of a, when a is not yet known to be a macro (and thus expected to be a function), whereas when you quote the form, you are effectively building a macro which expands into a call to itself.
When the compiler macroexpands a macro, it adds the implicit arguments before calling the function associated with the macro: Compiler.java#L6795. Here, you are directly calling a, which is in the scope of the implicit defn (core.clj#L452), without passing the necessary arguments.
I would expect the following to work as you wish (loop):
user=> (defmacro a[]&form)
#'user/a
user=> (a)
But unfortunately, here is the error message I get:
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'user/a, compiling:(/tmp/form-init5239882861501900074.clj:1:1)
... even though:
user=> (defmacro a[](print &form))
#'user/a
user=> (a)
(a)nil
NB. The Common Lisp equivalent is:
(defmacro w(&whole w)w) ;; 23 bytes
Existing names
Note also that once you define a, your cannot change the definition as follows:
(defmacro a[](a 0 1))
... because it complains that a accepts zero arguments. If, however, you define another macro with a name which has not yet been defined, it works:
user=> (defmacro b[](b 0 1))
#'user/b
user=> (b)
StackOverflowError user/b (form-init5239882861501900074.clj:1)
For more description of the problem see the ticket at http://dev.clojure.org/jira/browse/CLJ-1279.
In Clojure for the Brave and True, chapter 8, a function called if-valid is proposed (then rejected) to abstract away the repetitive parts of validation checks:
(defn if-valid
[record validations success-code failure-code]
(let [errors (validate record validations)]
(if (empty? errors)
success-code
failure-code)))
The author explains that the function in its above state won't work as success-code and failure-code will be evaluated on each if-valid call. My understanding is, that the if function's test will return true or false, and that dictates whether the success or failure code runs. Please can someone explain how both then and else portions of the if will be evaluated for each if-valid call?
Suppose that this function is used as follows:
(if-valid my-data validators
(println "Data accepted")
(throw (Exception. "Bad data :(")))
This is no good, because function arguments must be evaluated before they can be passed to the function. So, the side effects of first printing "Data accepted" and then throwing an exception will both be performed every time, before this function gets a chance to run validations at all.
According to spec, def should intern the var in the current ns (i.e. *ns*). However, the following code does not look anything like it:
(ns namespace-b)
(defn def_something []
(ns namespace-a)
(println *ns*) ;prints namespace-a as it should
(def something 1)
)
(def_something)
(println namespace-b/something) ; prints 1
(println namespace-a/something) ; throws
What am I missing?
Notes:
defn is used just for clarity. Defining and running anonymous function works just as well.
I know that using def inside function is probably not very idiomatic. However, this is just extracted essence of a bigger problem I ran into.
The parser already interns the var to the current namespace at compile time, although it won't be bound immediately:
(defn dd [] (def x 0))
x ;; => #<Unbound Unbound: #'user/x>
The relevant piece of code can be found here, with the second parameter to lookupVar triggering the aforementioned interning for non-existing vars here.
The parses then generates an expression that references the previously created var, so the expression logic never leaves the current namespace.
TL;DR: def is something that the compiler handles in a special kind of way.
The key thing to understand about def is that it is a macro. This means that it does not resolve the namespace or create the binding at runtime, but beforehand, while the code is being compiled.
If you call a function that calls def, that call to def was already resolved to use the namespace in which the function was defined. Similarly, if you call functions inside a function body, the functions to call are resolved at compile time within the namespace where that function was defined.
If you want to generally bind values to namespaces at runtime, you should use the function intern, which lets you explicitly set the namespace to mutate.
All this said, namespace mutation is just that, it's procedural and is not thread safe and does not have nice declarative semantics like other options Clojure makes available. I would strongly suggest finding a way to express your solution that does not involve unsafe runtime mutation.
In examples, I see
(set! *unchecked-math* true)
and then operations are done. However, what exactly in the function set! And how come it is allowed to mutate unchecked-math which is a boolean?
set! is a special form (i.e. neither a function nor a macro) which sets the value of thread-a local-bound dynamic Var, or a Java instance/static field.
set! is implemented in Java as part of the core language: Var.java on GitHub.
You should read up on Var and set! on clojure.org, as Ankur points out in his comment: http://clojure.org/vars#set
To explain why set! works on *unchecked-math*:
*unchecked-math* is a dynamic Var for which the compiler installs a thread-local binding before it actually starts compiling. It is this thread-local binding that is set to true by (set! *unchecked-math* true). *warn-on-reflection* works similarly.
The initial value of the compiler's binding is simply whatever is obtained by derefing the Var. In particular, if the compiler is called upon to compile code on a thread which already has its own bindings for the dynamic Vars relevant to the compilation process, the compiler will use the values of those bindings; that is, it will still install its own bindings, but it will use the current values.