Destructuring a variadic function with an as-binding: not possible? - clojure

Until now, I had always assumed that anything you can do in let binding, you can do within the arguments vector for a defn form.
However, I just noticed this -- if I do this with a let binding, it works:
(let [[x & more :as full-list] (range 10)]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; x: 0
; more: (1 2 3 4 5 6 7 8 9)
; full list: (0 1 2 3 4 5 6 7 8 9)
But if I try to pull it out into a function, I get an exception:
(defn foo [x & more :as full-list]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
; CompilerException java.lang.RuntimeException: Unexpected parameter, compiling:(/tmp/form-init615613631940782255.clj:1:1)
Of note, this works:
(defn foo [[x & more :as full-list]]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
But then I have to pass in the argument as a collection, i.e. (foo [1 2 3]).
Is it possible to define a function that takes a variable number of arguments, and bind the entire group of arguments to a local variable, without specifically using a let binding inside? It strikes me as weird that you can't just do (defn foo [x & more :as full-list] ... Is there a particular reason why this doesn't (or shouldn't) work?

If you want a variable number of args, you are missing an &:
(defn foo [& [x & more :as full-list]]
(println "x:" x)
(println "more:" more)
(println "full list:" full-list))
Clojure param definition has only one special case that is the & char to indicate a variadic number of arguments. The rest are plain simple named arguments.
Now each simple argument can be destructured using the map or list syntax. For example:
(defn foo [ x y ] ...)
Can be destructured like:
(defn foo [[x1 x2 & x-more :as x] {:keys [y1 y2 y3]}] ...)
So we are saying that we expect the first param to be a list of at least 2 elements and the second param to be a map with some keys. Note that this will still be a fn of two params and that Clojure is not going to enforce that x actually has at least two elements. If x is an empty list, x1 and x2 will be nil.
Coming back to your question, if you look at my answer you will see that my fn has 0 mandatory params, with a variable number of arguments, while the one that you have has 1 mandatory param with a a variable number of arguments. What I am doing is just destructuring the var arg.

Related

How to pass the rest args of a variadic function to another function?

I want to write a function which simply updates a vector in a map with new value, but can take any number of args, but at least one.
Here is example:
(defn my-update [what item & items]
(update what :desired-key conj item items))
Unfortunately, this doesn't work. Despite that update do have a signature with multiple values (like [m k f x y]), all remaining arguments to my-update will be joined into one sequence, which will be passed to conj as one argument.
Instead, wrapping conj with apply in an anonymous function does work, but looks not so elegant:
(defn my-update [what item & items]
(update what :desired-key #(apply conj % item items))
What is the idiomatic way of writing such a function like my-update?
You can simply insert apply before update. That will call the function update with the arguments that follows except for the last argument which should be a sequence, whose elements become the remaining arguments in the call:
(defn my-update [what item & items]
(apply update what :desired-key conj item items))
(my-update {:desired-key [0]} 1 2 3 4)
;; => {:desired-key [0 1 2 3 4]}
(my-update {:desired-key [0]})
;; Exception: Wrong number of args (1) passed to: my-update
This way, you can keep the function argument list [what item & items] that makes it clear that at least one item needs to be provided.
In general, a call (apply f a b c ... [x y z ...]) will evaluate to the same as (f a b c ... x y z ...).
Your existing solution isn't so bad. One small improvement is to use the into function, which uses conj internally to join two sequences together:
(defn my-update [what & items]
(update what :a into items))
with result
(my-update {:a [1]} 2 3 4) => {:a [1 2 3 4]}
Another alternative is to extract out the anonymous function into a named function:
(defn append-to-seq
[seq item items]
(-> (vec seq) ; ensure it is a vector so conj adds to the end, not beginning
(conj item)
(into items)))
(defn my-update [what item & items]
(update what :a append-to-seq item items))

How does [ ] work in a function in Clojure?

How does [] work in a function in Clojure?
(def square (fn [x] (* x x)))
(square 10) ; -> 100
As I understand from the above, we pass 10 in the place of x. Shouldn't I be able to do the following?
(def square (fn [x y] (* x y)))
(square 5 10) ; -> 50
In Clojure, [] is used to represent the argument list. That is to say, the anonymous function defined in square takes a single argument and multiplies it against itself.
You can absolutely extend that, but you're probably going to want to change the name of the function to better reflect what it's actually doing instead.
(def multiply (fn [x y] (* x y)))
Some comments on Makoto's answer.
You don't need to name a function in order to use it:
((fn [x] (* x x)) 10) ; 100
((fn [x y] (* x y)) 5 10) ; 50
Anonymous functions often crop up as arguments to higher order functions such as map.
Clojure (and other Lisps) separate the act of making a function as a thing from the act of naming it. def does the naming. A subsequent def for a name erases/obliterates/overwrites an earlier one.
Nor do you need to explicate a function in order to name it. Instead of
(def multiply (fn [x y] (* x y)))
just write
(def multiply *)
There's a lovely explanation of this (for Common Lisp) in Paul Graham's On Lisp.

Destructuring function arguments in Clojure

I'm running an example in Clojure Programming by Chas Emerick et al.:
(defn make-user
[& [uid]]
{:user-id (or uid (str (java.util.UUID/randomUUID)))})
output:
=> (make-user "T-800")
{:user-id "T-800"}
Now I remove the square brackets around uid in line 2:
(defn make-user
[& uid]
{:user-id (or uid (str (java.util.UUID/randomUUID)))})
The evaluation result becomes:
=> (make-user "T-800")
{:user-id ("T-800")}
How to understand this difference?
In an argument declaration, putting arguments next to & causes them to get wraped into a list.
(defn return [x y & more]
[x y more])
(return 1 2 3 4 5 6)
;=> [1 2 (3 4 5 6)]
This wraping is useful to manipulate an undetermined number of args in a function:
(defn plus [& more] (apply + more))
(plus 3 4)
;=> 7
(plus 3 4 5 6)
;=> 18
But if we know there will only be one element as the optional argument and want to directly access it, we could use first to extract it:
(defn make-user-1 [& uid] {:user-id (first uid)})
(make-user-1 "T-800")
;=> {:user-id "T-800"}
Or, we could simply unwrap the argument element by using destructuring!
(defn make-user-2 [& [uid]] {:user-id uid})
(make-user-2 "T-800")
;=> {:user-id "T-800"}
So, here are some arg declaration and their given output:
(defn f [arg] arg) ;=> arg
(defn f [& arg] arg) ;=> (arg)
(defn f [& [arg]] arg) ;=> arg
The more you wrap args in the arg declaration, the more those unwrap in the body.
[& uid]:
& means putting all arguments together as a list named uid.
So, uid here is of type list
[& [uid]]:
putting all arguments together as [uid], which is a list (not because [] but it is after &).
In addition, do a destructuring of this list by grabbing the first element as uid
So uid here is not a list but just one element.

What is meant by destructuring in Clojure?

I'm a Java and learning clojure.
What is exactly destructuring in clojure?
I can see this blog saying:
The simplest example of destructuring is assigning the values of a
vector.
user=> (def point [5 7])
#'user/point
user=> (let [[x y] point]
(println "x:" x "y:" y))
x: 5 y: 7
what he meant by assigning the values of a vector? Whats the real use of it?
Thanks in advance
point is a variable that contains a vector of values. [x y] is a vector of variable names.
When you assign point to [x y], destructuring means that the variables each get assigned the corresponding element in the value.
This is just a simpler way of writing:
(let [x (nth point 0) y (nth point 1)]
(println "x:" x "y:" y))
See Clojure let binding forms for another way to use destructuring.
It means making a picture of the structure of some data with symbols
((fn [[d [s [_ _]]]]
(apply str (concat (take 2 (name d)) (butlast (name s)) (drop 7 (name d))) ))
'(describing (structure (of data))))
=> "destructuring"
((fn [[d e _ _ _ _ _ i n g _ _ _ _ _ s t r u c t u r e & etc]]
[d e s t r u c t u r i n g]) "describing the structure of data")
=> [\d \e \s \t \r \u \c \t \u \r \i \n \g]
Paste those ^ examples into a REPL & play around with them to see how it works.
The term "Destructuring" sounds heavier than it is.
It's like visually matching shapes to shapes. For example:
(def nums [1 2 3 4 5 6])
(let [[a b c & others] nums]
;; do something
)
Imagine the effect of the let binding as:
1 2 3 4 5 6
| | | ( )
v v v v
[a b c & others]
;; Now we can use a, b, c, others, and of course nums,
;; inside the let binding:
user=> (let [[a b c & others] nums]
(println a)
(println b)
(println c)
(println others)
(println nums))
1
2
3
(4 5 6)
[1 2 3 4 5 6]
The goal is to concisely name items of a collection, for use inside the scope of a let binding or function (i.e. within a "lexical scope").
Why "concise"? Well, without destructuring, the let binding would look like this:
(let [a (nth nums 0) ;; or (first nums)
b (nth nums 1) ;; or (second nums)
c (nth nums 2)
others (drop 3 nums)]
;; do something
)
This illustrates the basic idea. There are many details (ifs and buts, and dos and don'ts), and it's worth reading further, in depth. Here are a few resources that explain more, with examples:
My personal favourite: Jay Fields's post on Clojure Destructuring:
http://blog.jayfields.com/2010/07/clojure-destructuring.html
A gentle introduction to destructuring, from Braveclojure:
http://www.braveclojure.com/do-things/#3_3_3__Destructuring
its used to name components of a data structure, and get their values.
Say you want to have a "person" structure. In java, you would go all the way to create a class with constructors, getters and setters for the various fields, such as name, age, height etc.
In Clojure you could skip the "ceremony" and simply have a vector with 3 slots, first for name, than for age and last for height. Now you could simply name these "components" and get their values, like so:
(def person ["Fred" 30 180])
(let [[name age height] person]
(println name age height)) ;; will print: Fred 30 180
p.s - there are better ways to make a "person" in clojure (such as records etc), this is just an example to understand what destructuring does.
Destructuring is a convenience feature which allows local bindings (not variables!) to be created easily by taking apart complex data structures (seq-ables like vectors, or associatives like hash-maps), as it is described here.
Take the following example:
(let [v [1 2 3 4 5 6]
v_0 (first v)
v_1 (nth v 1)
v_rest (drop 2 v)
m {:a 1 :b 2}
m_a (get m :a)
m_b (get m :b)
m_default (get m :c "DEFAULT")]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Then the above code can be simplified using destructuring bindings like the following:
(let [[v_0 v_1 & v_rest :as v]
[1 2 3 4 5 6]
{m_a :a m_b :b m_default :c :or {m_default "DEFAULT"} :as m}
{:a 1 :b 2}]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Destructuring patterns can be used in let bindings and function parameters (fn, defn, letfn, etc.), and also in macros to return let bindings containing such destructuring patterns.
One important usage to note is with the if-letand when-let macros. The if statement is always evaluated on the whole form, even if the destructured bindings themselves evaluate to nil:
(if-let [{:keys [a b]}
{:c 1 :d 2}]
(println a b)
(println "Not this one"))
Destructuring binds a pattern of names to a complex object by binding each name to the corresponding part of the object.
To bind to a sequence, you present a vector of names. For example ...
(let [[x y] (list 5 7)] ... )
... is equivalent to
(let [x 5, y 7] ... )
To bind to a map or to a vector by index lookup, you present a map of name-to-key pairs. For example ...
(let [{x 0, y 1} [5 7]] ... )
... is equivalent to both of the above.
As others have mentioned, you can find a full description of this powerful mechanism here.

Clojure idioms: sanely pass function-value pairs

Sometimes I want to pass argument-value pairs to a higher-order function, where the value I should pass is determined by the argument I pass. I want to be able to pass the argument without explicitly specifying the accompanying value. In particular, I'm interested in the case where the argument is itself a function.
Generic Example:
Here's a very generic example, where my-foo and my-bar are functions that I'm passing to higher-foo:
(higher-foo my-foo :option4 args) ;good
(higher-foo my-bar :option13 args) ;good
(higher-foo my-foo :option13 args) ;how stupid are you?! my-foo requires :option4!
Question: Is there a "standard" method for making :option4 or :option13 to be inferable by higher-foo so that I can just write (higher-foo my-foo) and (higher-foo my-bar)?
More Specific Example:
Bear in mind that there are better alternatives to the following code, but I'm just trying to put forward a concrete example of what I'm talking about:
(defn seq-has? [f n someseq]
(every? (partial apply f)
(partition n 1 someseq)))
(defn monotonicity [a b]
(<= a b))
(defn generalized-fib [a b c]
(= c (+ a b)))
(seq-has? monotonicity 2 someseq) should return true if the sequence is monotonic, false otherwise. (seq-has? generalized-fib 3 someseq) should return true if the sequence follows the generalized Fibonacci form, false otherwise.
But the "2" and "3" bother me. I could have an arbitrary number of properties to test for, and I don't want to have to remember the appropriate "magic numbers" for such calls.
Note: I know of two ways to do this, and for my own personal use, I suppose they both work. But I'm interested in what is idiomatic or considered best practice in the community. I'll post my answers, but I'm hoping there are more solutions.
Just make the predicate function itself take variadic arguments, and have it do the partitioning / recurring. Your monotonic? for instance already exists in core, and is called <=
(<= 1 2 4 5)
=> true
(<= 1 2 1 5)
=> false
Here's the source for the 1, 2 and variadic arg versions:
(source <=)
(defn <=
"Returns non-nil if nums are in monotonically non-decreasing order,
otherwise false."
{:inline (fn [x y] `(. clojure.lang.Numbers (lte ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (lte x y)))
([x y & more]
(if (<= x y)
(if (next more)
(recur y (first more) (next more))
(<= y (first more)))
false)))
You can make a fib? work the same way, have it take variadic arguments and recur over triples:
(defn fib?
[a b & [c & r]]
(if (= c (+ a b))
(if r
(recur b c r)
true)
false))
(fib? 0 1 1)
=> true
(fib? 2 3 5 8 13)
=> true
Since you are asking for a standard way how a function determines a not passed argument from one argument:
(defn f
([arg0] (case a :foo (f a :bar)
:baz (f a :quux)))
([arg0 arg1] ...))
Depending on your use case a different dispatch construct than case may be a better fit.
For your generic example this implies that higher-foo should determine the correct :option in the desired overload like demonstrated above.
In your specific example, you can't determine the n from the passed function. You need a more specific datastructure:
(defn seq-has? [{:keys [f n]} s]
(every? (partial apply f)
(partition n 1 s)))
(def monotonicity
{:f <=
:n 2})
(def generalized-fib
{:f #(= (+ %1 %2) %3)
:n 3})
(seq-has? monotonicity [1 2 3])
;; => true
This solution seems like a hack to me. Is it considered common/idiomatic? Use meta-data on the functions that define the property you are looking for:
(defn higher-foo [foo & args]
(apply foo (:option (meta foo))
args))
(def my-foo
(with-meta
(fn [a b] (println "I'm doing something cool"))
{:option :option4}))
;using it:
user=> (higher-foo my-foo arg)