Trying to find a more appropriate macro than cond to perform matching for predicate functions.
At the moment, I'm doing something like this:
(cond
(map? x) (do-map-code x)
(sequential? x) (do-seq-code x)
(keyword? x) (do-kw-code x)
:else (do-generic-code x))
In an ideal world, I'd like to apply data as the first argument for each of the left hand conditions, allowing me to write this instead.
(cond x
map? (do-map-code x)
sequential? (do-seq-code x)
keyword? (do-kw-code x)
:else (do-generic-code x))
Sort of like a backwards condp.
For reference, I know I could use condp with type and check against the type values. I just want to know whether this macro exists.
You can use condp to do this:
(condp #(%1 %2) x
map? (do-map-code x)
sequential? (do-seq-code x)
keyword? (do-kw-code x)
(do-generic-code x))
Related
In the same way you can convert
(if (something)
something
fallback)
into the shorter version :
(or something fallback)
I was wondering if there is a composition function/elegant builtin for threading a value into the validation of a predicate like :
(when (pred x)
x)
Into something like
(thread-pred pred x)
I could easily build some function or macro to do it, but I'd rather not go NIH here.
It took me way longer than I care to admit - but here you go:
Beware this might explode.
(defmacro -pred->
[pred body]
`(when (~pred ~body) ~body))
(macroexpand-1 '(-pred-> odd? 3))
=> (clojure.core/when (odd? 3) 3)
(-pred-> odd? 3)
=> 3
(-pred-> odd? 2)
=> nil
EDIT: as the comments correctly pointed out it would be wiser to let-bind the body to an autogensym like so:
(defmacro -pred->
[pred body]
`(let [b# ~body]
(when (~pred b#) b#)))
This is an extension to my previous question here.
The purpose is demonstrated as below:
(defn foo
[x a-map]
(assoc a-map x "value"))
(defn -main
[x]
(let [[x1 x2 x3 ... xn] x]
(-> {}
(partial foo x1)
(partial foo x2)
(partial foo x3)
...
(partial foo xn))))
The complexity of this problem lies that I have to populate a variable number of partial functions so I cannot use -> nor 'comp'. The real mechanism of the foo function is not an assoc of course so I cannot simplify the problem as a zipmap.
I'm not sure if this matter, but the input argument x is actually a cartesian product of two sequences. So each element of x is a two-element vector that iterates through the cartesian product space of two sequences. It is generated using a for loop, or rather, list comprehension.
What do you suggest to handle this problem? Let me know if I failed to give some important info.
Cheers
First of all, your usage of thread first -> macro is incorrect (see this question for more info). Here is the right syntax using thread last ->> macro:
(->> {}
(foo x1)
(foo x2)
(foo x3)
(foo x4))
Though, it won't work unless the length of vector x is determent.
But you could use reduce function here to process any sequence of elements:
(reduce #(assoc %1 %2 "value") {} x)
Here is a complete example (with slightly redefined foo function):
(defn foo
[a-map x] ; reversed order of arguments
(assoc a-map x "value"))
(defn -main
[x]
(reduce foo {} x))
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).
Say I want to make a Clojure macro that does the following:
If x is a list calling the function "bar"
return :foobar
else
return x as a string
However, bar is not defined; rather, it is only used internally in the macro, like so:
(foo (bar))
:foobar
(foo 1)
"1"
One could do something like this:
(defmacro foo [x]
(if (and (coll? x) (= (first x) 'bar))
:foobar
(str x)))
This works great for the (bar) case, as well as for literals. However, symbols do not work as intended, giving the symbol name instead of its associated value:
user=> (def y 2)
#'user/y
user=> (foo y)
"y"
One could call the eval function on x before passing it to str, but this causes problem when using the function in let:
user=> (let [a 3 b (foo a)] b)
java.lang.UnsupportedOperationException: Can't eval locals (NO_SOURCE_FILE:89)
Presumably, the problem has to do with symbol resolution, so maybe we try to work something out with syntax-quote:
(defmacro foo [x]
`(if (and (coll? '~x) (= (first '~x) '~'bar))
:foobar
(str ~x)))
Now, the problem is with (foo (bar)), as this expands the else clause to (clojure.core/str (bar)), which throws an exception, as bar is not defined. I then tried doing some shenanigans with eval:
(defmacro foo [x]
`(if (and (coll? '~x) (= (first '~x) '~'bar))
:foobar
(eval '(str ~x))))
But this doesn't work with let bindings again:
user=> (let [a 1 b (foo a)] b)
java.lang.Exception: Unable to resolve symbol: a in this context (NO_SOURCE_FILE:153)
So I'm really at a loss here. It seems as though fixing one problem breaks another. Is there a better, simpler way of making this macro such that it works in the following cases:
In let bindings
With (bar)
With symbols
P.S. If anybody is curious as to why I want to do this, I'm working on a DSL for Yahoo's YQL service and I want to be able to do things like (select (table :t) ...), but I need to be able to pass in symbols, as well as literals.
I believe this should work.
(defmacro foo [x]
(if (and (coll? x) (= (first x) 'bar))
:foobar
`(str ~x)))
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]))