Let's say I have a vector defined like this:
(def v '[test 1])
How can I use this vector in a let statement? I want to do something like this:
(let v
test)
and return 1. Everything I've tried so far just gives me:
java.lang.IllegalArgumentException: let requires a vector for its binding in user:1
You can't do it like that because let is a macro/special form that introduces bindings in its body. In normal clojure semantics var v can have any value at runtime and that would make it impossible to compile the let block. In other words, the bindings vector must be known and fixed at compile time. Also, since body of the let block is static, there is no reason to make the list of bindings variable.
The normal way of setting local bindings "dynamically" when evaluating "static" expressions is to use functions, i.e.
(defn let-v [v]
v)
(def test 1)
(let-v test)
If you want to generate let bindings (and probably also the let body), you'd need a macro. Though this sounds more like an X-Y problem. So maybe you want to expand on why you think you need this construct if functions won't work for you.
The proper way to get at only the value of 1 (as in your sample):
As an extraction of the value in a function call - Add destructuring:
(def v [x 1])
(defn let-v
[[_ i]]
i)
(let-v v) ; => 1
Pretty much the same thing in a let statement:
(dev v [x 1])
(let [[_ i] v]
i)
And, obviously, to pass the vector into a function but the destructure happens on the let within the function:
(def v [x 1])
(defn let-v
[v]
(let [[_ i] v]
i))
Related
I'm trying to do a really basic problem in clojure and having some trouble wrapping my head around how vectors/lists work.
First off when I am defining the arguments of a function that has a vector as an argument, how do you represent that as an argument.
Would you just have it as a single variable say
(defn example [avector] (This is where the function goes) )
Or do you have to list each element of a vector or list beforehand?
(defn example [vectorpart1 vectorpart2 vectorpart3 vectorpart4 ] (This is where the function goes) )
Also, in terms of vectors and lists, does anyone know of commands that allow you to figure out the length of a vector or get the first/last/or nth element?
To remove the element at index n from vector v:
(defn remove-indexed [v n]
(into (subvec v 0 n) (subvec v (inc n))))
For example,
(remove-indexed (vec (range 10)) 5)
;[0 1 2 3 4 6 7 8 9]
Lots can go wrong:
v might not be a vector.
n might not be a whole number.
n might be out of range for v (we require (contains? v n).
Clojure detects all these errors at run time. A statically typed language would detect 1 and 2 but not 3 at compile time.
Your first example defines a function that takes a single argument, regardless of type. If you pass a vector then that argument will be set to a vector.
(example [1 2 3 4]) ;; (= avector [1 2 3 4])
Your second example defines a function which takes four arguments. You need to pass four separate values for calls to this function to be valid.
(example [1] [2] [3] [4])
;; (= vectorpart1 [1])
;; (= vectorpart2 [2])
;; (= vectorpart3 [3])
;; (= vectorpart4 [4])
It sounds like you might be thinking about the destructuring syntax, which allows you to destructure values directly from an argument vector.
(defn example [[a b c d]]
())
The literal vector syntax in the argument definition describes a mapping between the items in the first argument and symbols available in the function scope.
(example [1 2 3 4])
;; (= a 1)
;; (= b 2)
;; (= c 3)
;; (= d 4)
The other function that also sits in this space is apply. Apply takes a list or vector of arguments and calls a function with them in-place.
(defn example [a b c]
(assert (= a 1))
(assert (= b 2))
(assert (= c 3)))
If we call this function with one vector, you'll get an arity exception.
(example [1 2 3])
;; ArityException Wrong number of args (1) passed ...
Instead we can use apply to pass the vector as arguments.
(apply example [1 2 3])
;; no errors!
You'll find all the methods you need to work with vectors in the Clojure docs.
If you want to remove a specific element, simply take the elements before it and the elements after it, then join them together.
(def v [1 2 3])
(concat (subvec v 0 1) (subvec v 2))
The short answer is that your first example is correct. You don't want to have to name every piece of your vector because you will commonly work with vectors of indeterminate length. If you want to do something with that vector where you need its parts to be assigned, you can do so by destructuring.
The slightly longer answer is that the list of parameters sent into any clojure defn already is a vector. Notice that the parameter list uses [] to wrap its list of args. This is because in Clojure code and data are the same thing. From this article...
Lisps are homoiconic, meaning code written in the language is encoded as data structures that the language has tools to manipulate.
This might be more than you're looking for but it's an important related concept.
Here'a a quick example to get you going... Pass a vector (of strings in this case) to a functions and it returns the vector. If you map over it however, it passes the contents of the vector to the function in succession.
user=> (def params ["bar" "baz"])
#'user/params
user=> (defn foo [params] (println params))
#'user/foo
user=> (foo params)
[bar baz]
nil
user=> (map foo params)
bar
baz
(nil nil)
Additionally, look at the Clojure cheatsheet to find more about things you can do with vectors (and everything else in Clojure).
What's the idiomatic way to return value only if test succeeds, and return default otherwise? I suppose it's trivial to build one, but I wanted to know if there was a built-in function for that purpose.
(def a {:name "foo"})
(if (map? a) a {})
; {:name "foo"}
(def b "bar")
(if (map? b) b {})
; {}
; is there a built-in function that looks like this?
(get-if map? b {})
Usually it is preferable to use functions instead of macros if it is possible:
(defn get-if [pred v default]
(if (pred v) v default))
The macro is pretty trivial to write. I don't believe this is idiomatic in that it adds an extra layer of abstraction without increasing readability. Someone reading a code like that has to look at the macro to figure out what is going on as opposed to a simple if.
The macro:
(defmacro get-if
[p v d]
`(let [val# ~v]
(if (~p val#)
val#
~d)))
Perhaps if you tell more about what is your use case I can help you more?
Basically, I need to do something like map, but instead of applying a function to all elements in a collection, I need to apply the same (set of) value(s) to a collection of functions (does this operation have a name?). This might seem like a simple question, but I haven't found an idiomatic way to do it in Clojure. For the special case where I need to apply only one value to each function, for example, I have used
(for [f funs] (f value))
where value is, of course, the value I need each function to take as an argument, and funs is the collection of functions which need to be called with value as the argument.
My question is, then, is there a function in Clojure that does this, but is also generalised for arbitrary numbers of arguments? Or is the above indeed idiomatic Clojure?
You're looking for juxt
juxt
Takes a set of functions and returns a fn that is the juxtaposition
of those fns. The returned fn takes a variable number of args, and
returns a vector containing the result of applying each fn to the
args (left-to-right).
((juxt a b c) x) => [(a x) (b x) (c x)]
From a section of CLOJURE for the BRAVE and TRUE
Another fun thing you can do with map is pass it a collection of
functions. You could use this if you wanted to perform a set of
calculations on different collections of numbers, like so:
(def sum #(reduce + %))
(def avg #(/ (sum %) (count %)))
(defn stats
[numbers]
(map #(% numbers) [sum count avg]))
(stats [3 4 10])
; => (17 3 17/3)
(stats [80 1 44 13 6])
; => (144 5 144/5)
What is the "simplest"/shortest way to ensure a var is a vector? Self-written it could look like
(defn ensure-vector [x]
(if (vector? x)
x
(vector x))
(ensure-vector {:foo "bar"})
;=> [{:foo "bar"}]
But I wonder if there is already a core function that does this? Many of them (seq, vec, vector, list) either fail on maps or always apply.
I also wonder what would be the best name for this function. box, singleton, unit, v, cast-vector, to-vector, ->vector, !vector, vector!, vec!?
I further wonder if other languages, like Haskell, have this function built-in.
I think the function you want to use when the value is a collection is vec which turns any collection into a vector. The vector function receives the items of the resulting vector as its arguments, so you could use it when the value is neither a vector or a collection.
This is a possible approach:
(defn as-vector [x]
(cond
(vector? x) x
(sequential? x) (vec x)
:else (vector x)))
(map as-vector [[1] #{2 3} 1 {:a 1}])
I chose the name for the function based on the ones from the Coercions protocol in clojure.java.io (as-file and as-url).
I want to repeatedly apply some function to some state until a condition holds true.
Function f takes a state, modifies it and returns it. Apply f again to the returned state and so on.
I think this would work.
(first (filter pred (iterate f x)))
But it's a bit ugly. Plus memory consumption is not ideal since iterator would be forced to evaluate and keep intermediate states until the state on which pred holds true is returned, at which point intermediate states should be garbage collected.
I know you can write a simple recursive function:
(loop [f x p] (if (p x) x (recur f (f x) p))
But I'm looking for a core library function (or some combination of functions) that does the same thing with the same memory efficiency.
What you really want is take-while:
take-while
function
Usage: (take-while pred coll)
Returns a lazy sequence of successive items from coll while
(pred item) returns true. pred must be free of side-effects.
EDIT
A way to use higher order functions to achieve the result you want might be to wrap your function into something to be consumed by trampoline, namely a function that will either return the final result or another function which will execute the next step. Here's the code:
(defn iterable [f] ; wraps your function
(fn step [pred x] ; returns a new function which will accept the predicate
(let [y (f x)] ; calculate the current step result
(if (pred y) ; recursion stop condition
(fn [] (step pred y)) ; then: return a new fn for trampoline, operates on y
y)))) ; else: return a value to exit the trampoline
The iterative execution would go as follows:
(trampoline (iterable dec) pos? 10)
Not sure what you mean by iterator - you're using it as if it were iterate, and I just want to be sure that's what you mean. At any rate, your solution looks fine to me and not at all ugly. And memory is not an issue either: iterate is free to throw away intermediate results whenever it's convenient because you aren't keeping any references to them, just calling filter on it in a "streaming" way.
I think you should just make your loop a simple recursive function:
(defn do-until [f x p]
(if (p x) x (recur f (f x) p)))
(do-until inc 0 #(> % 10)) ; => 11
How about drop-while
(first (drop-while (comp not pred) (iterate f x))
I don't think there is a core function that does this exactly and efficiently. Hence I would do this with loop/recur as follows:
(loop [x initial-value]
(if (pred x) x (recur (f x))))
Loop/recur is very efficient since it requires no additional storage and is implemented as a simple loop in the JVM.
If you're going to do this a lot, then you can always encapsulate the pattern in a macro.
Sounds like you want the while macro.
http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/while
Usage: (while test & body)
Repeatedly executes body while test expression is true. Presumes
some side-effect will cause test to become false/nil. Returns nil
In a slightly different use case the for macro supports :when and :while options too.
http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/for
Usage: (for seq-exprs body-expr)
List comprehension. Takes a vector of one or more
binding-form/collection-expr pairs, each followed by zero or more
modifiers, and yields a lazy sequence of evaluations of expr.
Collections are iterated in a nested fashion, rightmost fastest,
and nested coll-exprs can refer to bindings created in prior
binding-forms. Supported modifiers are: :let [binding-form expr ...],
:while test, :when test.
(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))