Reputation: 2543
Say I have a function that needs two arguments and where the order of arguments affects the results.
Is it possible to pass the first argument into a partial or comp function and the other aside of it, like this:
(defn bar [arg1 arg2] (- arg1 arg2))
(def baz (partial (bar arg1)))
(def qux (comp str (bar arg1)))
(baz arg2)
(qux arg2)
If I want to pass arg2 into the function, could I do something like this?
(def baz2 (partial (bar _ arg2)))
(def qux2 (comp str (bar _ arg2)))
(baz arg1)
(qux arg1)
Upvotes: 4
Views: 3575
Reputation: 26446
Scheme SRFI 26 has a useful macro cut
for slotting parameters like this.
Usage would be like so for your subtracting bar
:
((cut bar <> 1) 2)
;=> 1
((comp str (cut - <> 1)) 2)
;=> "1"
Where the <>
symbol represents the slot to be filled.
It is a fun exercise to implement a cut
in Clojure yourself, but here is one port by @Baishampayan Ghose.
Upvotes: 4
Reputation: 17201
Here's what I got in a repl:
user=> (defn bar [arg1 arg2] (- arg1 arg2))
#'user/bar
user=> (def baz (partial bar 5))
#'user/baz
user=> (def qux (comp str baz))
#'user/qux
user=> (baz 2)
3
user=> (qux 2)
"3"
It's the closest I could get from your first example.
For the second example, maybe a simple defn is better than a partial def:
user=> (defn baz2 [x] (bar x 5))
#'user/baz2
user=> (def qux2 (comp str baz2))
#'user/qux2
user=> (baz2 2)
-3
user=> (qux2 2)
"-3"
I'd suggest you start a repl and try it yourself, it's the second best way to discover a language that I know of (TDD being the first).
Cheers!
Upvotes: 3
Reputation: 31621
partial
only "fills in" arguments on the left side, so if you need to skip arguments you must use fn
:
(def baz2 #(bar %1 arg2))
Note also that comp
requires that all its arguments be functions, so your qux
and qux2
are actually nonsense. They should be:
(def qux (comp str baz))
(def qux2 (comp str baz2))
In general, Clojure core functions will place the variable most likely to change last to make composition with comp
and partial
more natural. (E.g., the collection argument is almost always last in Clojure, except for things like into
where it makes sense to put it first.) When you design your own functions you should stick to this convention so you can compose your functions more easily.
Upvotes: 9