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
2024-11-22 09:27:07 -06:00
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 ) ) ) )
2024-11-22 09:27:07 -06:00
( 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"
2024-11-22 09:27:07 -06:00
( 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 ) ) )