d-/d-.scm

145 lines
3.5 KiB
Scheme
Raw Normal View History

2024-10-23 09:02:27 -05:00
(define-module (d-)
2024-10-25 15:16:04 -05:00
#:use-module (srfi srfi-1)
2024-11-21 23:13:27 -06:00
#:use-module (language tree-il)
2024-10-23 09:02:27 -05:00
#:export
(~>
~>>
2024-11-21 23:13:27 -06:00
as~>
2024-10-25 15:48:01 -05:00
if-not
2024-11-01 18:05:27 -05:00
if-let
for
2024-10-25 15:16:04 -05:00
partial
2024-10-29 11:41:50 -05:00
argmin
2024-11-21 23:13:27 -06:00
iterate
upply
2025-01-03 09:25:49 -06:00
conjoin
2024-12-16 10:35:33 -06:00
distinct?
2024-11-21 23:13:27 -06:00
generator
2024-12-16 10:35:33 -06:00
macro-expand
amb
amb-reset
amb-require))
2024-10-23 09:02:27 -05:00
(define-syntax ~>
(syntax-rules ()
2024-11-01 18:05:27 -05:00
[(~> v) v]
[(~> v (fn args ...) more ...) (~> (fn v args ...) more ...)]
[(~> v fn more ...) (~> (fn v) more ...)]))
2024-10-23 09:02:27 -05:00
(define-syntax ~>>
(syntax-rules ()
2024-11-01 18:05:27 -05:00
[(~>> v) v]
[(~>> v (fn args ...) more ...) (~>> (fn args ... v) more ...)]
[(~>> v fn more ...) (~>> (fn v) more ...)]))
2024-10-23 09:02:27 -05:00
2024-11-21 23:13:27 -06:00
(define-syntax as~>
(syntax-rules ()
[(_ as v) v]
[(_ as v (fn args ...) more ...)
(let [(as v)]
(as~> as (fn args ...) more ...))]))
2024-10-25 15:48:01 -05:00
(define-syntax-rule (if-not pred body ...)
(if (not pred) body ...))
2024-11-01 18:05:27 -05:00
(define-syntax-rule (if-let ([ident test]) expr ...)
(let ([ident test])
(if ident
(begin expr ...)
#f)))
(define-syntax for
(syntax-rules ()
[(for () expr ...) (list (begin expr ...))]
[(for ([ident lst] bindings ...) expr ...)
(let iter ([rest lst])
(if (pair? rest)
(let ([ident (car rest)])
(append (for (bindings ...) expr ...) (iter (cdr rest))))
'()))]))
2024-10-23 09:02:27 -05:00
(define (partial fn . args)
(lambda x (apply fn (append args x))))
2024-10-25 15:16:04 -05:00
2024-11-11 15:38:13 -06:00
(define (argmin arg lt? . vals)
2024-10-25 15:16:04 -05:00
(reduce (lambda (val min)
2024-11-11 15:38:13 -06:00
(if (lt? (arg val) (arg min))
2024-10-25 15:16:04 -05:00
val
min))
#f
vals))
2024-10-29 11:41:50 -05:00
2024-11-21 23:13:27 -06:00
(define (iterate n f v)
2025-01-03 09:25:49 -06:00
"Repeatedly call f on values returned from (f v)"
2024-11-21 23:13:27 -06:00
(if (zero? n)
v
(iterate (1- n) f (f v))))
(define (upply a b cmp . fs)
2025-01-03 09:25:49 -06:00
"U-shapped apply, apply fs to a and b as in compose, then apply cmp to both results"
(let ([arm-f (apply compose fs)])
(cmp (arm-f a) (arm-f b))))
2025-01-03 09:25:49 -06:00
(define (conjoin . preds)
"Returns a procedure that applies each pred to a single value, and returns #t if all return a truthy value. With no preds returns a one arg function that always returns true"
(if (null? preds)
(lambda (x) #t)
(lambda (x)
(if ((car preds) x)
((apply conjoin (cdr preds)) x)
#f))))
2024-12-16 10:35:33 -06:00
(define (distinct? . a)
2025-01-03 09:25:49 -06:00
"Are all values distinct, as in equal?"
2024-12-16 10:35:33 -06:00
(if (or (null? a) (null? (cdr a)))
#t
2025-01-03 09:25:49 -06:00
(and (not (any (lambda (x) (equal? (car a) x)) (cdr a)))
2024-12-16 10:35:33 -06:00
(apply distinct? (cdr a)))))
2024-10-29 11:41:50 -05:00
;; Shamelessly ripped from https://wingolog.org/archives/2013/02/25/on-generators
(define (make-generator f)
(define tag (make-prompt-tag))
(define (thunk)
(f (lambda (val) (abort-to-prompt tag val))))
(lambda ()
(call-with-prompt tag
thunk
(lambda (k value)
(set! thunk k)
value))))
2024-11-11 22:15:27 -06:00
(define-syntax generator
2025-01-03 09:25:49 -06:00
;; generator with an anaphoric yield
2024-11-11 22:15:27 -06:00
(lambda (x)
(syntax-case x ()
[(generator expr ...)
(with-syntax ([yield (datum->syntax x 'yield)])
#'(make-generator
(lambda (yield)
expr ...)))])))
2024-11-21 23:13:27 -06:00
;; Why wasn't this included?
(define macro-expand (compose tree-il->scheme macroexpand))
2024-12-16 10:35:33 -06:00
;; This is the "classic" implementation of McCarthy's `amb'
;; Would rather it use delimited continuations, but I'm too dumb
(define (*fail*) (error "Could not satisfy amb"))
(define-syntax amb
(syntax-rules ()
[(amb) (*fail*)]
[(amb a) a]
[(amb a b ...)
(let ([fail0 *fail*])
(call/cc
(lambda (cc)
(set! *fail*
(lambda ()
(set! *fail* fail0)
(cc (amb b ...))))
(cc a))))]))
(define (amb-reset)
;; Shouldn't be necessary, but prompts are hard and I'm dumb dumb dummy
(set! *fail* (lambda () (error "Could not satisfy amb"))))
(define (amb-require pred)
(or pred (amb)))