point-free
(require point-free) | package: point-free |
Tools for defining point-free functions with very little syntactic overhead.
source code: https://github.com/jackfirth/point-free
1 Thrush Combinator
The thrush combinator is a higher order function that reverses the order of application. It can be seen as the reverse of function composition.
procedure
(thrush f ...) → procedure?
f : procedure?
procedure
(λ~> f ...) → procedure?
f : procedure?
procedure
(thrush+ v f ...) → any?
v : any? f : procedure?
procedure
(~> v f ...) → any?
v : any? f : procedure?
> (thrush+ 0 add1 positive?) #t
> (thrush+ "foo" string->list length even?) #f
> (thrush+ 'foo symbol->string string-length) 3
procedure
(thrush* v ...) → (-> [f procedure?] ... any?)
v : any?
procedure
(~>* v ...) → (-> [f procedure?] ... any?)
v : any?
> ((thrush* 1 2 3) + even?) #t
> ((thrush* "foo" "bar") string-append string-length) 6
procedure
(thrush-and f ...) → procedure?
f : procedure?
procedure
(λand~> f ...) → procedure?
f : procedure?
> (define find-odd (curry findf odd?))
> ((thrush-and find-odd add1) '(2 3 4)) 4
> ((thrush-and find-odd add1) '(2 4 6)) #f
procedure
(thrush+-and v f ...) → any
v : any/c f : procedure?
procedure
v : any/c f : procedure?
procedure
((thrush*-and v ...) f ...) → any
v : any/c f : procedure?
procedure
v : any/c f : procedure?
2 Define forms of function composition
syntax
(define/compose name func-expr ...)
> (define/compose symbol-length string-length symbol->string)
> (symbol-length 'foo) 3
> (symbol-length 'bazzz) 5
syntax
(define/thrush name func-expr ...)
> (define/thrush symbol-length symbol->string string-length)
> (symbol-length 'foo) 3
> (symbol-length 'bazzz) 5
syntax
(define/thrush-and name func-expr ...)
> (define/thrush-and inc-odd (curry findf odd?) add1)
> (inc-odd '(2 3 4)) 4
> (inc-odd '(2 4 6)) #f
3 Point-free argument counts
These forms define ways to define anonymous functions in a point-free style while binding a single variable that contains the number of arguments passed to the function. This can be useful for removing boilerplate.
syntax
(arg-count n func-expr)
syntax
(define/arg-count name n func-expr)
> (define/arg-count average n (compose (curryr / n) +))
> (average 8 10 12) 10
4 Point-free parallel function composition
Racket functions can accept and return any number of arguments, so there are two ways to combine them - chaining them together in serial with compose, or joining them in parallel with the join function defined in this module. These two primitives can be combined in powerful and expressive ways, making point-free function definitions much simpler in many cases. Note that this has absolutely nothing to do with parallel execution or concurrency, this is purely a handy terminology for talking about function operations.
procedure
(join f ...) → procedure?
f : (-> any/c any/c)
procedure
(wind-pre f g ...) → procedure?
f : procedure? g : (-> any/c any/c)
> ((wind-pre < string-length symbol-length) "foo" 'bazz) #t
> ((wind-pre + string-length symbol-length) "foo" 'bazz) 7
procedure
(wind-post f g ...) → procedure?
f : procedure? g : (-> any/c any/c)
procedure
((wind f g ...) h ...) → procedure?
f : procedure? g : (-> any/c any/c) h : (-> any/c any/c)
procedure
(join* f) → procedure?
f : (-> any/c any/c)
> ((join* add1) 1 2 3)
2
3
4
> ((join* symbol->string) 'foo 'bar)
"foo"
"bar"
procedure
(wind-pre* f g) → procedure?
f : procedure? g : (-> any/c any/c)
> (define string< (wind-pre* < string-length))
> (string< "foo" "barrr" "bazzzzz") #t
> (string< "foooooo" "barrr" "baz") #f
procedure
(wind-post* f g) → procedure?
f : procedure? g : (-> any/c any/c)
procedure
(wind* f g h) → procedure?
f : procedure? g : (-> any/c any/c) h : (-> any/c any/c)
> (define str-append (wind* append string->list list->string))
> (str-append "foo" "bar" "baz") "foobarbaz"
5 Definition forms of winding functions
These forms allow for short definitions of point-free functions using wind and friends.
syntax
(define/wind id f (pre ...) (post ...))
> (define/wind pythagoras + (sqr sqr) (sqrt))
> (pythagoras 3 4) 5
> (pythagoras 5 12) 13
syntax
(define/wind-pre id f pre ...)
> (define/wind-pre sym-and-num->str string-append symbol->string number->string)
> (sym-and-num->str 'foo 123) "foo123"
syntax
(define/wind-post id f post ...)
> (define/wind-post first-true-last-false partition first last)
> (first-true-last-false symbol? '(1 2 a b 3 c 4 5 6 d))
'a
6
syntax
(define/wind* id f pre post)
> (define/wind* pythagoras + sqr sqrt)
> (pythagoras 3 4) 5
> (pythagoras 5 12) 13
syntax
(define/wind-pre* f pre)
> (define/wind-pre* symbol-shorter < (λ~> symbol->string string-length))
> (symbol-shorter 'foo 'bazz 'barrr) #t
> (symbol-shorter 'blah 'bloo) #f
syntax
(define/wind-post* f post)
> (define/wind-post* firstf partition first)
> (firstf symbol? '(1 2 3 a b 4 5 c 6 d e))
'a
1
6 Fixpoint functions
These functions manipulate other functions based on their fixpoints - the values that can be given to the function such that the function does nothing and returns just those values. The fixpoints of the function abs for example, are all nonnegative numbers. The absolute value of a nonnegative number x is just "x".