Useful Tacit function
(require tacit) | package: Tacit |
source code: https://github.com/lurry-m/tacit
1 The different variant of the fork-macros
These macros are inspired by APL (J).
syntax
(fork (first ...) second ...)
> (define average (fork (/) sum length)) > (average (range 10)) 9/2
> (define euler-form (fork (make-rectangular) cos sin)) > (euler-form 3.141592653589793) -1.0+1.2246467991473532e-16i
> (define positive-even-number? (fork (and) number? positive? even?))
> (map (fork (cons) identity positive-even-number?) (range 5)) '((0 . #f) (1 . #f) (2 . #t) (3 . #f) (4 . #t))
> (define displayln-and-negate (fork (begin) displayln -)) > (map displayln-and-negate (range 3))
0
1
2
'(0 -1 -2)
syntax
(fork2 (first ...) second ...)
syntax
(fork3 (first ...) second ...)
syntax
(fork* (first ...) second ...)
2 Syntactic sugar for mutable objects
Vectors and hashes are useful but they can be a bit verbose. These two definitions provide a few helpful procedures out of the box wich are similar to struct.
syntax
(define-vector identifier my-vector)
> (define-vector v (make-vector 5 5)) > (v-set! 1 17) > (v-ref 1) 17
> (v-update! 2 sqr) > (v++ 3) > (v-- 4) > (v-length) 5
> v '#(5 17 25 6 4)
syntax
(define-mutable-hash identifier my-hash)
> (define-mutable-hash ht (make-hash (list (cons 1 1) (cons 2 2)))) > (ht-set! 3 30) > (procedure-arity ht-ref) '(1 2)
> (ht-ref 3) 30
> (ht-ref 4 16) 16
> (ht-ref! 4 12) 12
> (ht-ref 4 16) 12
> (ht-update! 3 sqr) > (ht++ 1) > (ht-- 2) > (ht-count) 4
> (ht-map cons) '((1 . 2) (2 . 1) (3 . 900) (4 . 12))
> (ht-for-each (compose displayln list))
(1 2)
(2 1)
(3 900)
(4 12)
> (ht-has-key? 5) #f
> ht '#hash((1 . 2) (2 . 1) (3 . 900) (4 . 12))
3 Showcase: Y-Combinator
The fork-macro is actually similar to the S function in the SKI-calculus.
> (define K const) > (define I (fork () K K))
> (define P (fork (fork (fork ()) K) K))
> (define C (fork (fork (fork ())) (fork (K) K) (K I)))
> (define E (fork (fork (I)) (fork () I I))) > (I 5) 5
> (((P add1) sqr) 10) 121
> (((C add1) sqr) 10) 101
> (define Y ((C E) (P E)))
Then we can define a factorial function like that:
Alternatively, the fibonacci function:
4 Showcase: Easy Racket
This section is inspired by an article of The alleged unreadability of J. The last section showcased some of the power of the fork, but it is barely readable. Here is a showcase of how it can also be used to make the code more readable, especially in combination with contracts.
> (struct triangle (a b c)) > (define the identity) > (define on identity) > (define of identity) > (define squares (curry map sqr)) > (define hypotenuse triangle-c) > (define other-two-sides (fork (list) triangle-a triangle-b)) > (define are-equal? =) > (define calculate compose)
> (define/contract triangle-is-pythagorean? (-> triangle? boolean?) (fork (are-equal?) (calculate the sqr on the hypotenuse) (calculate the sum of the squares on the other-two-sides))) > (triangle-is-pythagorean? (triangle 3 4 5)) #t
> (triangle-is-pythagorean? (triangle 3 4 6)) #f