rplevy / swiss-arrows Goto Github PK
View Code? Open in Web Editor NEWa collection of arrow macros
a collection of arrow macros
It might be as simple as using this macro from incubator:
https://github.com/clojure/core.incubator/blob/master/src/main/clojure/clojure/core/incubator.clj#L21
(defnilsafe
"doc"
-<> -?<>)
See http://dev.clojure.org/jira/browse/CLJ-1121
It gives this example:
After
(macroexpand-1 (macroexpand-1 '(-> a b c)))
=> (c (-> a b))
c is now in control if it is a macro, and is now seeing the argument (-> a b) rather than (b a) as would be the case if we had written (c (b a)) originally.
CLJ-1121 says it's fixed now, but it looks like maybe -<> and -<>> (and maybe the other ones) could suffer from the same problem.
I haven't actually tried it because I'm not actually a clojure user (I use racket).
What would it take to make these two equivalent?:
(-<> s
(map keyword <>)
(vec <>))
(-<> s
(map keyword <>)
vec)
This includes:
-?<>> Nil-shortcutting Diamond Spear
-!<>> Non-updating Diamond Spear
-<>>< , -<>><:p Diamond Harpoon, Parallel Diamond Harpoon
/cc @pauldorman
Hi,
The logic of the diamond wand example would be made clearer by passing a non-zero value. multiplication by zero returns zero, which is the original value, making the chaining unclear at a first glance.
I'm not sure if my pull request #27 would be considered actively useful, but if not I'd rather see why. At the moment I can't tell if it's been noticed.
Since "furclae" are branching arrows, why not "tegumina" for nesting / wrapping arrows and "cateno" for what arrows do, in general; that is convert nesting into chaining.
The furcula macros seem to be unnecessary because anything that could be done with them could be done with more idiomatic expressions.
the macros in question include:
-< , -<:p The Furcula, Parallel Furcula
-<< , -<<:p The Trystero Furcula, Parallel Trystero Furcula
-<>< , -<><:p The Diamond Fishing Rod, Parallel Diamond Fishing Rod
Confirm the equivalence of the behavior of these macros with more idiomatic expressions.
For example, a call to
(-< (+ 1 2)
(list 2)
(list 3)
(list 4)))
Should produce the same value as
(map (fn [x] (list (+ 1 2) (first x))) [(list 1) (list 2) (list 3)])
Write test that demonstrate more idiomatic expressions can accomplish results.
Compare the output with the result of the expression that is supposed to produce the same value
If the tests pass, then mark the macros as deprecated
I'm quite new to clojure and not sure if there isn't a better way already, but I found myself writing things like
(fn [x] (->> x (f a) (g b)))
quite often. Which I instinctively want to write in a point-free style, but this means I'll loose the comfort and readability of arrows:
(comp (partial g b) (partial f a))
I'm using these trivial helper macros now:
(defmacro fn->
"(fn-> f g...) expands to (fn [x] (-> x f g...)"
[& args]
`(fn [x#] (-> x# ~@args)))
(defmacro fn->>
"(fn->> f g...) expands to (fn [x] (->> x f g...))"
[& args]
`(fn [x#] (->> x# ~@args)))
which allow writing
(fn->> (f a) (g b))
Would that be a candidate for inclusion in swiss-arrows?
Issue found by Roman Perepelitsa.
I often find, especially for logging, that I want to stick some function that does not change the result, midway in the pipeline of an arrow. For this purpose I propose !-*-style arrows that always produce the same thing that they consume, while making use of that value.
(-> foo
(-!> prn)
bar)
(-> foo
(-!>> (prn "prefix"))
bar)
(-> foo
(-!<> (prn "prefix" <> "suffix"))
bar)
To make this somewhat more explicit
(-!>> :foo (prn "got here"))
Will (maybe I need to think this through more though) expand to
(let [v# foo] (prn "got here" v#) v#)
Or say you want to to print some key of an item partway down the pipleline
(-> foo
(-!> (->> :some-key first first (prn "got here")))
bar)
That would expand to
(bar (-!> foo (->> :some-key first first (prn "got here"))))
And then
(bar (let [v# foo] (->> v# :some-key first first (prn "got here")) v#))
And finally
(bar (let [v# foo] (prn "got here" (first (first (:some-key v#)))) v#))
This is especially handy for using within other arrows but is generally useful for other situations in which you don't want to interrupt the flow of passing a value but want to do something "on the side" with the value. It is more concise than the the let form that would be necessary to write to get the same effect in these cases.
PS:
If it's not really an arrow and only threads one step out it could be named !>, !>>, !<> to make this clear. Otherwise, if the semantics of -!> makes sense for example
(-!>> 1 inc double (prn "inc'd double'd & ready to rock")) => 1
, then use the arrowish -!>, -!>>, -!<> nomenclature.
How about an arrow that chains "apply", as in
(-@>> ([1 2] [3 4]) concat + ) => (apply + (apply concat '([1 2] [3 4]))) => 10
Issue identified by Roman Perepelitsa.
Presently it just exhibits undefined behavior when misused in this way.
I believe it should be fairly easy to port this library to a CLJC file (I did a quick proof of concept locally) and make it compatible with Clojure(Script). Any interest in a pull request for this? If yes, I can make one.
Hello, the ability to use the diamond in nested expressions would make it a lot more useful for me. Here's a suggestion how to do it. This way, it would not be compatible with -> or -<>. The assert would make sure that the user is aware of that. Or am I missing something, and nested diamonds are already possible?
(defmacro n-<>
"A diamond macro that allows the diamond to appear in nested position.
Example: (n-<> 1 (+ 4 (inc <>)))
Each form must contain at least one diamond, or an Exception will be thrown."
([x] x)
([x form]
(do
(assert (some (fn [x] (= '<> x)) (tree-seq seq? identity form)))
(cons (first form)
(clojure.walk/postwalk-replace {'<> x} (next form)))))
([x form & forms] `(n-<> (n-<> ~x ~form) ~@forms)))
Disclaimer: I've used -<>
without quote handling for a long time, so this may just be resistance to change. However:
The quote special case seems weird. It's like, "we'll put the form in the list/map/whatever, unless the CAR is the symbol "quote", in which case we'll do it to the CADR instead.
But more importantly, whereas the base <>
behavior is (empirically!) quite intuitive, what happens for quote is not. Notwithstanding Bruce's First Law of Lisp:
#_1 (-<> (blah) '(a <> b))
#_2 (-<> (blah) '<>)
In form 1, according to the README
, (blah)
is not evalled. I wouldn't care to guess that. Of course, that is also the case for form 2 without quote handling; however, the simpler rule for list scanning yields that conclusion as well.
When using some of the arrow macros, like -<>
, it seems type hinting does not work. Consider the following two examples:
(as-> "Hello" <> (.toUpperCase ^String <>))
(-<> "Hello" <> (.toUpperCase ^String <>))
While both have the exact same result, running (set! *warn-on-reflection* true)
reveals the one using -<>
is not preserving the type hint on the generated code, while the one using as->
does.
Is this intended, or you think it could be fixed?
Btw, many thanks for the great library!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.