Clojure : Documentation syntax, regarding when-let and if-let - syntax

I've been looking at the if-let and when-let macros, Im having trouble determining what exactly it is that they "do". In particular, the documentation sais :
clojure.core/when-let
([bindings & body])
Macro
bindings => binding-form test
When test is true, evaluates body with binding-form bound to the value of test
I thus am somewhat confused about the way macros are documented.
1) What does the "=>" symbol mean ?
2) What does "test" refer to ?

Direct answer to your questions:
=> means "expands to", as in BNF notation. In this case it means that you need two forms: binding-form and the test.
"test" means anything that can be evaluated as bool.
By the way, I think that the docs are unclear or even maybe erroneous here. It is hard (or impossible) to deduce that the two forms constituting the bindings need to be enclosed in a vector. IMHO it should be either when-let ([[bindings] & body]) (the vector shown in the args) or bindings => [binding-form test] (the vector shown in the BNF-like expansion.)

It's often helpful when dealing with a macro to call macroexpand and see what the generated code is.
(macroexpand
'(if-let [x (myfunc)]
(foo x)
(bar))
; expands to
(let* [temp__3695__auto__ (myfunc)]
(if temp__3695__auto__ (clojure.core/let [x temp__3695__auto__]
(foo x))
(bar)))
; the generated symbols are necessary to avoid symbol
; capture but can confuse. The above is equivalent to:
(let* [ t (myfunc)]
(if t
(let [x t]
(foo x))
(bar))
So you can see that if-let is a shorthand for "bind local variable to the result of a function call and if that variable is truthy call the first form, else call the other form. The value returned by your function is only available in the 'truthy' branch."
wrt documentation convention
bindings => binding-form test
=> reads something like 'is equivalent to'
test is some form that returns a value
For most of these functions, clojuredocs is your friend, example usage often clarify things. If the clojuredocs example doesn't cut it for you, you can add your own

Consider the following code:
(if-let [x (a-function)]
(do-something-with x) ;; (a-function) returned a truthy result
(do-something-else) ;; (a-function) returned nil or false
This is like let, in that x will be bound to the return value of (a-function). This function could return nil or false. In that case, the implicit test fails and (do-something-else) will be evaluated. If x is not nil and not false, (do-something-with x) will be evaluated.
A scenario where this could be useful:
(if-let [user (find-logged-in-user)]
(do something with logged in user) ;; a user was found
(redirect to login page) ;; no user was found
I sometimes use something like the following, to conditionally add keys to a map of options:
(apply merge {:username "joe"
:email "joe#example.com"}
(when-let [name (find-full-name)] {:name name})
(when-let [dob (find-date-of-birth)] {:dob dob}))
This results in a map with :username and :email keys, and a :name key if the users' full name was found, plus a :dob key if a date of birth was found.
I hope that makes the use of if-let and when-let clearer.

Related

What happened in scheme when defining a symbol to be something else?

I'm a beginner of the Scheme language.
Recently I found that the data type symbol can be displayed using quote, like this:
> 'E
E
> (quote E)
E
However, if the code below executed, every kind of quote may fail:
> (define 'E 123)
> 'E
E: undefined;
cannot reference an identifier before its definition
> 'abc
abc: undefined;
cannot reference an identifier before its definition
So what happend when code (define 'E 123) being executed?
First you asked Scheme to evaluate (define 'E 123). Let's put a quote in front of that, to see what it looks like without the ' shorthand. You can always do this: quote any expression to ask Scheme, "What do you think this value is?"
> '(define 'E 123)
=> (define (quote E) 123)
Well, in Scheme, (define (x ...) ...) is a shorthand for (define x (lambda (...) ...)): it's just a convenient shorthand for defining a function. So in this case (define (quote E) 123) is the same as (define quote (lambda (E) 123)). Thus, the symbol you are redefining is quote, and you define it to be a function of one parameter which always returns 123.
Next you asked to evaluate 'E. Again let's expand that to look through the shorthand:
> ''E
=> (quote E)
You now call the quote function you defined, and pass it the variable E as an argument. But E has not previously been defined, so this fails. If you wanted to, you could first define E to have any value, and then perhaps 'E would return 123. It rather depends on what Scheme evaluator you are using: the one I found does not much appreciate it when you try to redefine quote, but apparently yours does not mind, so I suspect you would get 123, and that you would get the same result if you defined abc and then evaluated 'abc.
in general (define name ...) is converted in (bind name) at the beginning of the scope and in the place where define appears, it is executed (set! name ...). You need to define a symbol, not a (quote name). Because define is a special form, the rules of evaluation are particular, not general application -- define is not a function call.

Expression that returns all currently scoped symbols in Clojure?

Assume the following,
(in-ns silly.fun)
(def a 1)
(defn fx [b]
((fn [c] (return-all-symbols)) (first b)))
I was wondering if it is possible to have a return-all-symbols function that would return the map of symbols/values currently scoped at its invocation. So, assuming the above was compiled and we were in the 'silly.fun namespace, we could run something like the following.
(fx [:hello]) => {"a" 1, "b" [:hello], "c" :hello}
I would like to use return-all-symbols for debugging purposes. Is return-all-symbols at all possible? If so, what is its implementation?
It's possible, but as you've defined it you'd be pretty sad: you don't want a map with hundreds of entries referring to all the functions in clojure.core! And even if you only look in the current namespace, you forgot to include fx, which is a symbol whose value is a function. Plus there will often be lexical symbols you don't want, introduced by macros. eg, (let [[x y] foo]) would show four symbols available: foo, x, y, and something like vec__auto__4863.
Anyway, you probably have to live with some compromise over those issues, or else (and really I think this is better) specify which symbols you actually want a map of. But to automatically get values for those symbols which are either (a) lexical or (b) defined in the current namespace, and also (c) not mapping to a function, you could use:
(defmacro return-all-symbols []
(let [globals (remove (comp :macro meta val) (ns-publics *ns*))
syms (mapcat keys [globals, &env])
entries (for [sym syms]
[`(quote ~sym) sym])]
`(into {}
(for [[sym# value#] [~#entries]
:when (not (fn? value#))]
[sym# value#]))))
(def a 1)
(defn fx [b]
((fn [c] (return-all-symbols)) (first b)))
(fx [:hello])
;=> {a 1, c :hello, b [:hello]}
Namespaces contain a map with all the currently scoped vars, which gives you part of what you want. It would miss lexicaly scoped symbols from expressions like (let [x 4] (return-all-symbols)) though may still be useful for debugging:
core> (take 2 (ns-map *ns*))
([sorted-map #'clojure.core/sorted-map] [read-line #'clojure.core/read-line])
if you need more than this then you may need a real debugger that uses the java debugging
interface. check out the clojure debugging toolkit
(ns-interns) might be what you want, but using (ns-map) wrapped in (lazy-seq) works good for a big namespace.
1 (ns-map 'clojure.core)
2 {sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, keyword? #'clojure.core/keyword?, ClassVisitor clojure.asm.ClassVisitor, asm-type #'clojure.core/asm-type, val #'clojure.core/val, ...chop...}

Access Java fields dynamically in Clojure?

I'm a novice in clojure and java.
In order to access a Java field in Clojure you can do:
Classname/staticField
which is just the same as
(. Classname staticField)
(correct me if I'm wrong)
How can I access a static field when the name of the field in held within a variable? i.e.:
(let [key-stroke 'VK_L
key-event KeyEvent/key-stroke])
I want key-stroke to be evaluated into the symbol VK_L before it tries to access the field.
In this case you might want to do something like the following:
user=> (def m 'parseInt)
#'user/m
user=> `(. Integer ~m "10")
(. java.lang.Integer parseInt "10")
user=> (eval `(. Integer ~m "10"))
10
If you feel like it's a bit hack-ish, it's because it really is such. There might be better ways to structure the code, but at least this should work.
I made a small clojure library that translates public fields to clojure maps using the reflection API:
(ns your.namespace
(:use nl.zeekat.java.fields))
(deftype TestType
[field1 field2])
; fully dynamic:
(fields (TestType. 1 2))
=> {:field1 1 :field2 2}
; optimized for specific class:
(def-fields rec-map TestType)
(rec-map (TestType. 1 2))
=> {:field1 1 :field2 2}
See https://github.com/joodie/clj-java-fields
Reflection is probably the proper route to take, but the easiest way is
(eval (read-string (str "KeyEvent/" key-stroke)))
This will just convert the generated string into valid clojure and then evaluate it.
You can construct the right call as an s-expression and evaluate it as follows:
(let [key-stroke 'VK_L
key-event (eval `(. KeyEvent ~key-stroke))]
....do things with your key-event......)
However, if what you are trying to do is test whether a particular key has been pressed, you may not need any of this: I usually find that it is easiest to write code something like:
(cond
(= KeyEvent/VK_L key-value)
"Handle L"
(= KeyEvent/VK_M key-value)
"Handle M"
:else
"Handle some other key")

How to inspect/export/serialize a (guile) Scheme environment

I'd like to export or replicate a scheme environment in another guile process. The algorithm I'm imagining would do something like this to serialize:
(map (lambda (var val) (display (quasiquote (define ,var ,val))
(newline))
(get-current-environment))
And then I'd read/eval that on the other end.
However, while there are functions that return the current environment, they are in some internal format that I can't just map across. How can I "walk" the environment as the above? Alternatively, how else can I replicate an environment into another process?
you may decompose the so-called "current-environment" like this:
(define (get-current-binding-list)
(let* ((e (current-module)) ;; assume checking current-module
(h (struct-ref e 0)) ;; index 0 is current vars hashtable
)
(hash-map->list cons h) ;; return a vars binding list
))
and you can call (get-current-binding-list) to get variables binding list in current-module.
Please note that each element in this list is a pair of symbol and variable type, say, (symbol-name . variable-type). So you may print it like this:
for a instance ,you got a var binding:
(define abc 5)
then:
(let ((vl (get-current-binding-list)))
(assoc-ref vl 'abc)
)
==> #<variable 9bb5108 value: 5>
This result is a "variable type" of variable "abc". You can get it's value with variable-ref procedure.
So you can trace all the bindings and do something ,in your code ,it's simply print var-name and var-value.
I know my answer is too brief, but I think there's enough information to help you to find more details in the manual.
Hope this will help you.
You can't really serialize Scheme environment. I don't known even it's possible to (portably) serialize continuations. Oh, and don't forget about FFIs. Ports and threads are unserializable too.

Should the behaviour of a function depend on the name of its variable?

Here is a short elisp code which shows that the behaviour of a function depends on the name of its variable. Is this a bug?
A function is declared using a variable x. When that function is called with a variable named anything other than x, it works as expected. But if it is called with a variable named x, it fails!
My system is GNU Emacs 22.2.1 (powerpc-apple-darwin8.11.0, Carbon Version 1.6.0) of 2008-04-05 on g5.tokyo.stp.isas.jaxa.jp
Paste this on an emacs buffer, put the cursor after the last parehthesis and press \C-x\C-e to see that the function make-zero does now work correctly when called the second time.
(progn
(defun make-zero (x)
"Simple function to make a variable zero."
(set x 0))
(setq x 10)
(insert "\n Variable x is now equal to " (number-to-string x))
(setq y 20)
(insert "\n Variable y is now equal to " (number-to-string y))
(insert "\n\n Let us apply make-zero to y")
(make-zero 'y)
(insert "\n Variable y is now equal to " (number-to-string y))
(insert "\n\n Let us apply make-zero to x")
(make-zero 'x)
(insert "\n Variable x is now equal to " (number-to-string x))
(insert "\n\n Why make-zero had no effect on x? Is it because the name of the
variable in the definition of make-zero, namely 'x', is the same as the name of
the variable when make-zero was called? If you change the name of the variable
in the definition of make-zero from x to z, this strange behaviour will
disappear. This seems to be a bug in elisp."))
It's not a bug so much as the nature of Elisp's (and Lisp in general) dynamic binding. ' doesn't pass a reference (that is, it's not like & in C/C++), it passes an unevaluated symbol; what it then evaluates to depends on the scope in which it's evaluated, which means it gets the x that's in scope inside the function.
In Lisp-think, the normal way around this would be to use a macro.
(defmacro make-zero (x) (list 'set x 0))
or
(require 'cl)
(defmacro make-zero (x) `(set ,x 0))
It's not a bug. It'd be worth your while reading the manual entry for Scoping Rules For Variable Bindings.
The function you wrote calls set, which takes a symbol (the value of the first argument) and changes its value to the value of the 2nd argument. The make-zero you wrote binds x locally to its input argument, so when you pass in the symbol x, set changes the first binding for x it finds, which happens to be the local binding.
Here's a different example, let's say you just had the following:
(defun print-something (something)
(set 'something "NEW VALUE")
(insert something))
(print-something "OLD") ; inserts "NEW VALUE"
Looking at that snippet of code, does it make sense that the set line changes the local value of something?
It doesn't matter whether or not there's a global setting for the symbol something.
Another example is the following:
(defvar x "some global value") ;# could have used setq here
(let ((x "local binding"))
(set 'x "new value"))
Which binding would you expect the set line to change? The one created by the let or the global one created by defvar?
The function you wrote is (pretty much) doing exactly the same thing as the let, you're creating a local binding for a variable which is seen before the global one.
If you want to pass around a reference to a variable then the only safe way to do that is via macros, which I recommend, but not until you've grasped the basics of lisp (b/c macros are definitely more complicated). That said, don't let me stop you from diving into macros if that's your passion.
A good introduction to programming Emacs lisp can be found here.
geekosaur's answer does a nice job of showing how you'd achieve what you want.

Resources