I have a sequence of records/classes, and I map over that sequence with new and expect to get a sequence of instances of those records/classes. I know new is a special form, but I was expecting Clojure to do The Right Thing in this case.
But this does not work:
(map new [SomeClass1 SomeClass2 SomeClass3])
Neither does this.
(map #(new %) [SomeClass1 SomeClass2 SomeClass3])
Similar code works in Factor.
{ SomeClass1 SomeClass2 SomeClass3 } [ new ] map
What would be the right way to do this in Clojure? (I expect it won't involve Class.newInstance ugliness.)
Edit:
The following works, but is perhaps slower than necessary. (I don't know for sure. I would appreciate some information on this.)
(map #(eval `(new ~%)) [SomeClass1 SomeClass2 SomeClass3])
Also I am looking for something more elegant.
because special-formes are well... special they are not first class and don't compose as proper functions do, you can solve this with eval and macros:
a solution using eval:
(defn fnew [c] (eval `(new ~c)))
hello.core> (map fnew ['Exception 'java.lang.String])
(#<Exception java.lang.Exception> "")
and a version that takes arguments to the constructors:
(defn fnew [c] (eval `(new ~#c)))
hello.core> (map fnew ['(Exception) '(java.lang.String "I am a contructor argument")])
(#<Exception java.lang.Exception> "I am a contructor argument")
(map fnew [ [Exception] [(class "foo") "I am a contructor argument"]])
(#<Exception java.lang.Exception> "I am a contructor argument")
and here is a macro example
hello.core> (defmacro newify [classes] (apply vector (for [c classes] `(new ~c))))
#'hello.core/newify
hello.core> (macroexpand '(newify [java.lang.String Exception]))
[(new java.lang.String) (new Exception)]
hello.core> (newify [java.lang.String Exception])
["" #<Exception java.lang.Exception>]
The macro version is likely more efficient while the eval version is more flexible.
As new is a special form, one of the solution to make it work like first class would be use the clojure low level calls like:
(map #(clojure.lang.Reflector/invokeConstructor %1 (into-array [])) [String])
This may lead to the performance problems of Reflection hence the macro based solution are prefered over this.
Related
Given:
(defn some-fn
[]
(let [a 1
b 2
c (+ a b)]
(println c)))
and given that there are multiple such functions, where:
a and b have different values;
c is always equal to (+ a b)
is there a way to extract c without making it a function, which accepts a and b as arguments. So, I don't want:
(defn c-outside
[a b]
(+ a b))
(defn some-fn
[]
(let [a 1
b 2
c (c-outside a b)]
(println c)))
but ideally, something like:
(defn c-outside
[]
(+ a b))
(defn some-fn
[]
(let [a 1
b 2
c (c-outside)]
(println c)))
Is there a way to make c-outside look for the values of a and b in the context, in which it is called? Do I need a macro for that?
there is a way to do it using dynamic bindings:
user> (def ^:dynamic a 10)
#'user/a
user> (def ^:dynamic b 20)
#'user/b
user> (defn c-outside []
(+ a b))
user> (defn some-fn []
(binding [a 1
b 2]
(c-outside)))
#'user/some-fn
user> (some-fn)
;;=> 3
user> (c-outside)
;;=> 30
the trick is that you can temporarily rebind some dynamic vars for the 'duration' of some scope.
This is mostly used in clojure for concurrent programming: the dynamically bound vars keep their values in the threads, spawned from inside the block (as far as i remember)
Otherwise, i see more potential harm from this feature, than the profit, since it obscures the code, adding some unneeded implicit behaviour.
Also as far as i know, this is one of the most arguable features in lisps (in common lisp, to be more specific)
Almost in any case it is better to pass a and b values explicitly to the summing function, since it makes in clean and therefore testable, and helps to reason about it's correctness and performance, and increases readability
you could also think of using macro for that, like this for example:
user> (defmacro c-outside-1 []
`(+ ~'x ~'y))
#'user/c-outside-1
user> (defn some-fn-1 []
(let [x 1
y 2]
(c-outside-1)))
#'user/some-fn-1
user> (some-fn-1)
;;=> 3
but that idea is obviously even worse.
I have functions that behave different depending on which keyword arguments have values supplied. For this question, I am wondering about functions that behave slightly differently depending on the type of argument supplied.
Example function, that increments each element of a list:
(defn inc-list [& {:keys [list-str list]}]
(let [prepared-list (if-not (nil? list) list (clojure.string/split list-str #","))]
(map inc prepared-list)))
Does it make sense to make a multimethod that instead tests for the type of argument? I have not used multimethods before, not sure about right time to use them. If it is a good idea, would the below example make sense?
Example:
(defn inc-coll [col] (map inc col))
(defmulti inc-list class)
(defmethod inc-list ::collection [col] (inc-col col))
(defmethod inc-list String [list-str]
(inc-col
(map #(Integer/parseInt %)
(clojure.string/split list-str #",")))
First things first: (map 'inc x) treats each item in x as an associative collection, and looks up the value indexed by the key 'inc.
user> (map 'inc '[{inc 0} {inc 1} {inc 2}])
(0 1 2)
you probably want inc instead
user> (map inc [0 1 2])
(1 2 3)
Next, we have an attempt to inc a string, the args to string/split out of order, and some spelling errors.
If you define your multi to dispatch on class, then the methods should be parameterized by the Class, not a keyword placeholder. I changed the multi so it would work on anything Clojure knows how to treat as a seq. Also, as a bit of bikeshedding, it is better to use type, which offers some distinctions for differentiating inputs in Clojure code that class does not offer:
user> (type (with-meta {:a 0 :b 1} {:type "foo"}))
"foo"
Putting it all together:
user> (defn inc-coll [col] (map inc col))
#'user/inc-coll
user> (defmulti inc-list type)
nil
user> (defmethod inc-list String [list-str]
(inc-coll (map #(Integer/parseInt %) (clojure.string/split list-str #","))))
#<MultiFn clojure.lang.MultiFn#6507d1de>
user> (inc-list "1,10,11")
(2 11 12)
user> (defmethod inc-list clojure.lang.Seqable [col] (inc-coll (seq col)))
#<MultiFn clojure.lang.MultiFn#6507d1de>
user> (inc-list [1 2 3])
(2 3 4)
Your first example is an obfuscated application of a technique called dispatching on type. It is obfuscated because in a message-passing style the caller must convey the type to your function.
Since in every case you only use one of the keyword args, you could as well define it as:
(defn inc-list
[m l]
(->> (case m ;; message dispatch
:list l
:list-str (map #(edn/read-string %) (str/split #",")) l)
(map inc)))
The caller could be relieved from having to pass m:
(defn inc-list
[l]
(->> (cond (string? l) (map ...)
:else l)
(map inc)))
This technique has the main disadvantage that the operation procedure code must be modified when a new type is introduced to the codebase.
In Clojure it is generally superseeded by the polymorphism construct protocols, e. g.:
(defprotocol IncableList
(inc-list [this]))
Can be implemented on any type, e. g.
(extend-type clojure.lang.Seqable
IncableList
(inc-list [this] (map inc this)))
(extend-type String
IncableList
(inc-list [this] (map #(inc ...) this)))
Multimethods allow the same and provide additional flexibility over message-passing and dispatching on type by decoupling the dispatch mechanism from the operation procedures and providing the additivity of data-directed programming. They perform slower than protocols, though.
In your example the intention is to dispatch based on type, so you don't need multimethods and protocols are the appropriate technique.
In Scheme I can do something like this:
(define (adder)
(define (one) 1)
(define (two) 2)
(+ (one) (two)))
Calling adder results in 3 while calling one will yield an error since one is only visible within the scope of adder.
In Clojure if I do something similar
(defn adder []
(defn one [] 1)
(defn two [] 2)
(+ (one) (two)))
one and two will pollute my namespace since defn uses def internally which creates bindings in the current namespace.
Is there a function/macro which creates named functions in local scope?
The reason for my question is that I got used to the way Scheme works. Naming my local functions that way often makes my code more readable.
Try letfn:
Takes a vector of function specs and a body, and generates a set of
bindings of functions to their names. All of the names are available
in all of the definitions of the functions, as well as the body.
(defn adder []
(letfn [(one [] 1)
(two [] 2)]
(+ (one) (two))))
Additionally to Alex's excellent answer, any fn can be named.
(defn adder []
(let [one (fn [] 1)
two (fn [] (+ (one) (one)))]
(+ (one) (two))))
This is useful if you already have a let block.
If an fn refers to itself, it needs a name of its own
(defn silly []
(let [constant 5
thing (fn thong
([a] (+ a constant))
([] (inc (thong constant))))]
(* (thing) (thing))))
The name the fn is bound to need not be the same as the name it knows itself by.
If you want a function that is visible to the current namespace but not visible by other namespaces - you can use defn-
defn-
macro
Usage: (defn- name & decls)
same as defn, yielding non-public def
from http://clojuredocs.org/clojure_core/clojure.core/defn-
user=> (ns test)
nil
test=> (defn- foo [] "World!")
#'test/foo
test=> (defn bar [] (str "Hello " (foo)))
#'test/bar
test=> (foo)
"World!"
test=> (bar)
"Hello World!"
test=> (ns playground)
nil
playground=> (test/bar)
"Hello World!"
;; Error will be thrown
;; var: #'test/foo is not public
playground=> (test/foo)
I am doing the closure tutorial at http://clojurescriptkoans.com and I am stuck here: http://clojurescriptkoans.com/#functions/9
It looks like this
Higher-order functions take function arguments
(= 25 ( _ (fn [n] (* n n))))
I am supposed to fill in something at the underscore to make the expression true. I have no clue what to do.
The syntax simply consists of binding the function, and then calling it.
Since this is an exercise, I will show a similar situation rather than showing the exercise's solution:
user> ((fn [f] (f "abc")) (fn [s] (str s s s)))
"abcabcabc"
here I bind the argument of the first function to f, and call f with the argument "abc".
or you can use the short-hand notation:
#(%1 5)
Higher order functions takes functions as arguments.
Defining two functions
user=> (defn multiply [n] (* n n))
#'user/multiply
user=> (defn add [n] (+ n n))
#'user/add
Defining higher order function
user=> (defn highorderfn [fn number] (fn number))
#'user/highorderfn
Calling the higher order function
user=> (highorderfn multiply 5)
25
user=> (highorderfn add 5)
10
Clojure is awesome, we all know this, but that's not the point. I'm wondering what the idiomatic way of creating and managing higher-order functions in a Haskell-like way is. In Clojure I can do the following:
(defn sum [a b] (+ a b))
But (sum 1) doesn't return a function: it causes an error. Of course, you can do something like this:
(defn sum
([a] (partial + a))
([a b] (+ a b)))
In this case:
user=> (sum 1)
#<core$partial$fn__3678 clojure.core$partial$fn__3678#1acaf0ed>
user=> ((sum 1) 2)
3
But it doesn't seem like the right way to proceed. Any ideas?
I'm not talking about implementing the sum function, I'm talking at a higher level of abstraction. Are there any idiomatic patterns to follow? Some macro? Is the best way defining a macro or are there alternative solutions?
Someone has already implememented this on the Clojure group. You can specify how many args a function has, and it will curry itself for you until it gets that many.
The reason this doesn't happen by default in Clojure is that we prefer variadic functions to auto-curried functions, I suppose.
I've played a bit with the functions suggested by amalloy. I don't like the explicit specification of the number of argument to curry on. So I've created my custom macro. This is the old way to specific an high order function:
(defn-decorated old-sum
[(curry* 3)]
[a b c]
(+ a b c))
This is my new macro:
(defmacro defn-ho
[fn-name & defn-stuff]
(let [number-of-args (count (first defn-stuff))]
`(defn-decorated ~fn-name [(curry* ~number-of-args)] ~#defn-stuff)))
And this is the new implicit way:
(defn-ho new-sum [a b c] (+ a b c))
As you can see there is no trace of (curry) and other stuff, just define your currified function as before.
Guys, what do you think? Ideas? Suggestions?
Bye!
Alfedo
Edit: I've modified the macro according the amalloy issue about docstring. This is the updated version:
(defmacro defhigh
"Like the original defn-decorated, but the number of argument to curry on
is implicit."
[fn-name & defn-stuff]
(let [[fst snd] (take 2 defn-stuff)
num-of-args (if (string? fst) (count snd) (count fst))]
`(defn-decorated ~fn-name [(curry* ~num-of-args)] ~#defn-stuff)))
I don't like the if statement inside the second binding. Any ideas about making it more succint?
This will allow you to do what you want:
(defn curry
([f len] (curry f len []))
([f len applied]
(fn [& more]
(let [args (concat applied (if (= 0 (count more)) [nil] more))]
(if (< (count args) len)
(curry f len args)
(apply f args))))))
Here's how to use it:
(def add (curry + 2)) ; read: curry plus to 2 positions
((add 10) 1) ; => 11
The conditional with the [nil] is meant to ensure that every application ensures some forward progress to the curried state. There's a long explanation behind it but I have found it useful. If you don't like this bit, you could set args as:
[args (concat applied more)]
Unlike JavaScript we have no way of knowing the arity of the passed function and so you must specify the length you expect. This makes a lot of sense in Clojure[Script] where a function may have multiple arities.