Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concise syntax for partial in Clojure

Learning Haskell some time ago, I felt in love with pointfree notation and especially convenient partial function application - just supply args you know. In Clojure, I have partial all the time. I think having a special syntax for partial in reader will be nice to have.

Look at the sample code:

; Notation with points:
(map (+ 10 (* % 2)) [1 2 3])

; With partial:
(map (comp (partial + 10) (partial * 2)) [1 2 3])

; Let #[] syntax means partial application in reader:
(map (comp #[+ 10] #[* 2]) [1 2 3])

This is so nice! Is there something like this? Is there possibility to define custom reader macro?

like image 745
demi Avatar asked Sep 06 '13 01:09

demi


3 Answers

An anonymous function syntax #(...) can be used similarly to what you are trying to do:

user=> (map (comp (partial + 10) (partial * 2)) [1 2 3])
(12 14 16) 

is equivalent to:

user=> (map (comp #(+ 10 %) #(* 2 %)) [1 2 3])
(12 14 16)

A tiny little difference is % which just means a function argument, in this case the first and only.

like image 194
tolitius Avatar answered Nov 14 '22 23:11

tolitius


I really like your idea for a partial function notation using the #[ ] literal. Unfortunately, Clojure does not let us enhance the #() notation directly, but we can define ourselves a macro like #p for a partial application.

Given you have a function

(defn partial-wrap
  [args]
  (concat '(partial) args))

defined in myapp.core. You can add the following entry into the data_readers.clj at the top of your classpath:

{p myapp.core/partial-wrap}

(usually one should use a namespace qualified symbol here like a/p, since unqualified symbols are reserved for Clojure. Nevertheless unqualified symbols do work, you need to rely on Clojure not overwriting them in a future version).

This finally allows to do almost what you asked for:

(map (comp #p[+ 10] #p[* 2]) [1 2 3])
=> (12 14 16)
like image 5
Leon Grapenthin Avatar answered Nov 14 '22 21:11

Leon Grapenthin


I found an approach to have partial in cases like in my question: (map #(+ 10 (* 2 %)) [1 2 3). Use ->> macro: (map #(->> % (* 2) (+ 10)) [1 2 3]. Similar macros are ->, .. and doto applicable in different situations.

like image 2
demi Avatar answered Nov 14 '22 22:11

demi