Skip to content

Clojure macros that complement the clojure.core threading (arrow) macros

License

Notifications You must be signed in to change notification settings

jdevuyst/fletching-macros

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fletching macros

A collection of Clojure macros that complement the clojure.core threading macros -> and ->>.

Setup

To start, create a Leiningen project and add the following dependency to project.clj:

Clojars Project

Next, load the macros as follows:

(require '[fletching.macros :refer :all])

>>

The macro >> removes itself from the head of the enclosing S-expression, and then moves the second form in the remaining expression to the end of the expression.

Intended to be used within -> to switch to ->> conventions.

(-> [[1 2 3] [3 4 5]]
    (nth 1)
    (->> (map -))
    (nth 1))
;=> -4

This can be rewritten as

(-> [[1 2 3] [3 4 5]]
    (nth 1)
    (>> map -)
    (nth 1))
;=> -4

<<

The macro << removes itself from the head of the enclosing S-expression, and then moves the last form in the expression to the second position.

This macro addresses the problem of nesting -> within ->>.

Working around this composition problem using clojure.core macros was already possible, but not always very elegant. You might have been writing code like this:

(-> (->> [-1 -2 -3 -4 -5]
         (map -)
         (filter even?))
    last
    range
    rest
    (->> (reduce *)))
;=> 6

Or like this:

(as-> [-1 -2 -3 -4 -5] x
      (map - x)
      (filter even? x)
      (-> x last range rest)
      (reduce * x))
;=> 6

Now you can write this:

(->> [-1 -2 -3 -4 -5]
     (map -)
     (filter even?)
     (<< -> last range rest)
     (reduce *))
;=> 6

Of course, << is also useful in one-off situations:

(->> [1 2 3 4 5]
     (map -)
     (<< nth 2)
     (/ 6))
;=> -2

?>, <?

The macros ?> and <? remove themselves from the head of the enclosing S-expression, and then remove the second (?>) or last (<?) form in the remaining expression and bind it to ?.

These macros are useful when you're composing functions using -> or ->> and you find yourself needing a little bit more flexibility for some of the threaded expressions.

(->> [1 2 3 4 5]
     (take 3)
     (reduce *)
     (<? str ? " is " (if (even? ?) "even" "odd"))
     (<? do [? ?]))
;=> ["6 is even" "6 is even"]

><

The macro >< removes itself from the head of the enclosing S-expression.

This macro is useful when you want to thread functions (as opposed to function arguments):

(-> [+ - * /]
    (nth 2)
    (>< 3 4)
    inc)
;=> 13

Equivalently,

(->> [+ - * /]
     (drop 2)
     first
     (<< >< 3 4)
     inc)
;=> 13

<fn, <&fn

The macros <fn and <&fn remove themselves from the head of the enclosing S-expression, and then insert a variable in the second position of the remaining expression. Finally, the expression is transformed into a 1-ary (<fn) or variadic (<&fn) lambda, which binds the variable.

<fn and <&fn can be used for defining functions in a point-free style:

(def f (<fn ->> (map -)
                (filter even?)
                (reduce *)))
(f [2 4 5 6])
;=> -48

<&fn is like <fn but takes a variable number of arguments, which it threads into the expression as a sequence.

(def g (<&fn ->> (map -)
                 (filter even?)
                 (reduce *)))
(g 2 4 5 6)
;=> -48

License

Copyright © 2015 Jonas De Vuyst

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

About

Clojure macros that complement the clojure.core threading (arrow) macros

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published