While trying to use trampoline to optimise tail recursion in my Clojure project, I came across some strange behaviour of the trampoline function.
=> (defn f [g] (fn [k & args] #(k (apply g args))))
...
=> (trampoline (f list) println 1 2 3)
(#<core$println clojure.core$println#54e517f6> 1 2 3)
nil
=> (((f list) println 1 2 3))
(1 2 3)
nil
I thought that (trampoline (f list) ...) and ((f list) ...) gave the same result, but as you can see above, they don't. Would anyone explain what goes on here?
Good catch!
You should report this bug to Clojure Dev Group or to Clojure Issue Tracker.
Also note, that this bug can only be reproduced by calling (apply list args) inside of trampoline and only when args is bound to the tail of initial function's arguments list.
The actual problem here is that Clojure rebinds args to the whole list of initial function's arguments.
Here is a shorter example to reproduce your problem:
(defn foo [h & ts] (apply list ts))
(trampoline foo 1 2 3) ; => (1 2 3)
(foo 1 2 3) ; => (2 3)
Changing (apply list ts) to either (list ts) or (apply vector ts) will make this bug disappear.
Related
I have faux-curry in Programming Clojure book.
user=> (defn faux-curry [& args] (apply partial partial args))
#'user/faux-curry
user=> (def add-3 ((faux-curry +) 3))
#'user/add-3
user=> (add-3 10)
13
However, it's hard to see why two partials are needed in the body.
In Coluredocs.org, I see (apply f args) as an example of an apply function. How to interpret (apply partial partial args)?
I think the easiest way to understand this is to expand out each part.
(partial + 2) returns a function
(fn [& xs] (apply + 2 xs))
calling the resulting function calls + with 1 and all the subsequent args passed to partial.
(apply + 2 [3 4 5]) is the same as (+ 2 3 4 5)
(fn [& xs] ...) says "take a sequence of arguments and call them xs"
which is like (fn [x1 x2 x3...] ...)
(partial partial) returns a function
(fn [& xs] (apply partial xs))
which has exactly the same behavior as partial because the function it produces just directly calls partial with all the arguments.
(apply partial partial args)
is the same as
(partial partial arg1 arg2...)
returns
(fn [& xs] (apply partial arg1 arg2... xs))
(apply partial partial [+ 1]) produces
(fn [& xs] (apply partial + 1 xs)).
Let's call this result g.
(g 2) => (apply partial + 1 [2]) => (fn [& xs] (apply + 1 2 xs)). Let's call this result h. (h 4 5) => (apply + 1 2 [4 5]) => (+ 1 2 4 5)
But if you were to leave out one of the partials:
(apply partial [+ 1]) produces
(fn [& xs] (apply + 1 xs)))
calling this resultant function will not return a function, but the result of summing the arguments with 1.
So having observed these behaviors, let's attempt to describe
(apply partial partial args):
"Create a function that creates a function that applies some function with the supplied arguments at creation time, and the supplied arguments at call time."
Hence faux-curry is a function that creates a function that creates a function o_O
I have two variadic functions. One of them passes its arguments to the other. The problem is that the varargs are becoming a list on the second call. How do I keep them varargs?
=> (defn foo [x & ys] (println x ys))
=> (defn bar [x & ys] (foo (clojure.string/upper-case x) ys))
=> (foo "hi")
hi nil
=> (bar "hi")
HI (nil)
In the real function, foo passes its args to a variadic java function, so the varargs really need to stay varargs. How do I do this?
From http://clojuredocs.org/clojure_core/clojure.core/apply
;you can also put operands before the list of operands and they'll be
consumed in the list of operands (apply + 1 2 '(3 4)) ; equal to
(apply + '(1 2 3 4))
=> 10
So
(defn bar [x & ys] (apply foo (clojure.string/upper-case x) ys))
should work.
For your problem with Java varargs note noisesmith's comment.
i need to write code like this in clojure.
-- haskell
fns = map (,) [1..3]
head fns $ 1
-- => (1,1)
fns <*> [1..3]
-- => [(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
doesn't work
(def fns (map (partial list) (range 1 3)))
((first fns) 1)
;; => ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
works, but i think this isn't idiomatic way
(def fns (map (fn [x] `(partial list ~x)) (range 1 3)))
((eval (first fns)) 1)
;; => (1 1)
The function (partial list) is equivalent to just the function list. It's not like haskell where everything is curried - I think you intended partial to see that it's been given only one argument, list, and curry itself up to wait for a second argument. But really that should be (partial partial list): you are attempting to partially apply the function partial itself.
Note also that partially-applied functions are not as common in clojure as they are in haskell, partly because they just don't read so well. Instead of (map (partial partial list) (range 1 3)), if I wanted to build a list of functions like this, I would probably write (for [i (range 1 3)] (fn [j] (list i j))).
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)
I am having a problem running my program in Clojure. I just start learning Clojure a couple of weeks ago. So I don't know the quick and easy way to debug a Clojure program. My func2 raises an exception at (adj(a b)) as followed:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn
user/func2.
I don't know what is wrong with it. Can someone point out the problem with my coding?
And in func3, I call func2 recursively, but it throws:
ArityException Wrong number of args (0) passed to: PersistentVector
clojure.lan g.AFn.throwArity (AFn.java:437)
What is wrong with func3? Thank you.
(defn adj [value1 value2]
(def result (+ (/ value1 2) (/ value2 2)))
(if (= (mod result 2) 1)
(+ result 1)
result
)
)
(defn func2 [list]
(let [[a b c d] list]
(inc d)
([(adj c a) (adj a b) (adj b c) d]))
)
(defn func3 [list]
(loop [v list r []]
(if(= (v 0) (v 1) (v 2))
(conj list r)
(func3(func2(list)))
))
)
What's the intended result of these functions? We probably need to see some sample inputs and expected results to really be able to help you.
Here's my attempt at cleaning them up. I've noted the changes I made as comments. func3 has the most serious problem in that it's an infinite recursion - there's no end condition. What should cause it to stop working and return a result?
(defn adj [value1 value2]
;; don't use def within functions, use let
(let [result (+ (/ value1 2) (/ value2 2))]
(if (= (mod result 2) 1)
(+ result 1)
result)))
(defn func2 [list]
(let [[a b c d] list]
;; The extra parens around this vector were causing it
;; to be called as a function, which I don't think is
;; what you intended:
[(adj c a) (adj a b) (adj b c) d]))
;; This needs an end condition - it's an infinite recursion
(defn func3 [list]
(loop [v list r []]
(if (= (v 0) (v 1) (v 2))
(conj list r)
;; Removed extra parens around list
(func3 (func2 list)))))
The reason I say not to use def within functions is that it always creates a global function. For local bindings you want let.
Regarding the extra parens, the difference between [1 2 3] and ([1 2 3]) is that the former returns a vector containing the numbers 1, 2, and 3, whereas the latter tries to call that vector as a function. You had excess parens around the literal vector in func2 and around list in func3, which was causing exceptions.
As a style note, the name list isn't a good choice. For one thing, it's shadowing clojure.core/list, and for another you're probably using vectors rather than lists anyway. It would be more idiomatic to use coll (for collection) or s (for sequence) as the name.
This would suggest at least one other change. In func3 you use a vector-only feature (using the vector as a function to perform lookup by index), so to be more general (accept other data structures) you can convert to a vector with vec:
(defn func3 [coll]
(loop [v (vec coll) r []]
(if (= (v 0) (v 1) (v 2))
(conj v r)
(func3 (func2 v)))))
Oh, there is no need to debug that. I suggest you have a look at LightTable.
The first two functions are easily fixed:
(defn adj [value1 value2]
;(def result (+ (/ value1 2) (/ value2 2))) def creates a global binding in current namespace !!!
(let [result (+ (/ value1 2) (/ value2 2))]
(if
(= (mod result 2) 1)
(inc result)
result)))
(defn func2 [xx]
(let [[a b c d] xx]
[ (adj c a) (adj a b) (adj b c) (inc d)]
))
The third function is not clear to me. I don't read your intent. What I understand is: "Keep applying func2 to itself until the first three elements of its result are equal." But I'm afraid this condition is never met, so I replaced it with a true in order to see just one result without blowing the stack.
(defn func3 [xx]
(loop [ v (func2 xx) ]
(if
;(= (v 0) (v 1) (v 2))
true
v
(recur (func2 v))
)))
Useful link: http://clojure.org/cheatsheet
Cheers -