2018-11-23

sph-lib examples

to use the features you have to import the relevant modules first, which are mentioned in the titles of the following sections. for example

(import (sph list))

(sph)

display trace and debug messages

(debug-log 1 2 3) -> 1
(+ 3 (debug-log (+ 1 2) a b))

the debug-log syntax form writes all arguments formatted to standard output and returns its first argument, so that it can be used to intercept the execution flow without disturbing it

nullary

alternative to (lambda () body ...)

(call-with-values (nullary (partition a? b)) list)

let

simplified let syntax that works just like the original let but additionally supports binding just one variable

(let (a 1)
  body ...)

display-line

(display-line "test")

define-syntax-case

(define-syntax-case (test a b ...) s
  (syntax a))

(define-syntax-case (test a b ...)
  (syntax a))

(define-syntax-cases test
  ((test a b ...) (syntax a))
  ((test a b ...) (syntax a)))

the simplifications compared to syntax-case are

  • removes the option to define keywords
  • removes the option to use custom lambda for define-syntax

define-syntax-rule

(define-syntax-rule (test a b) (+ a b))

(define-syntax-rules test
  ((test a b) (+ a b))
  ((test a) a))

short-forms

l q qq
lambda quote quasiquote

l for lambda

(map (l (a) (+ a 1)) a)

as alternative to

(map (lambda (a) (+ a 1)) a)

quoting without auxillary read syntax

(q a)
(qq a)

as alternatives to

(quote a)
(quasiquote a)

list-q list-qq

(list-q a b c)
(list-qq a (unquote (+ 1 2)) c)

as alternatives to

(quote (a b c))
(quasiquote (a b c))

define-as

(define-as b list
  1
  2
  3)
; as alternative to
(define b
  (list
    1
    2
    3))

binds a value to identifier after applying arguments to the procedure or syntax-form given as the second argument. the second argument can be a list of arbitrary length, which means the procedures or syntax-forms are composed. like for example (quote (div 1 2 3)). define-as can avoid additional nesting and indentation.

forms

(define-as binding-name identifier body ...)
(define-as binding-name (identifier ...) body ...)

(sph list)

mapping n times

(map-integers 10 (l (n) n))

result

(0 1 2 3 4 5 6 7 8 9)

associative data structures with (sph alist) and (sph hashtable)

creation

key and value specified alternatingly

(alist "a" 1 (q b) 2)
(ht-create "a" 1 (q b) 2)

in application similar to

(list 1 2 3)
(vector 4 5 6)

-q variants that implicitly quote keys

(alist-q a 1 b 2)
(ht-create-symbol-q a 1 b 2)

get an alist from a hashtable

(ht-alist ht #:optional (depth 0))
(ht-alist ht)
(ht-alist ht 2)
(ht-alist ht (inf))

access

(alist-ref x (q a))
(ht-ref x (q a))

-q variants that implicitly quote keys

(alist-ref-q x a)
(ht-ref-q x a)

nested references

(alists-ref x 1 2 3)
(ht-tree-ref x 1 2 3)

(sph tree)

tree-transform

map/transform list and sub-lists first top to bottom, calling descend for each sub-list, then bottom to top, calling ascend for lists and terminal for non-lists/leafs. suited to map scheme syntax trees to transform them or convert to other language strings. used for example in sescript and sc

tree-transform :: list procedure:descend procedure:ascend procedure:terminal
descend :: any:element procedure:recurse-descend -> (any:result-element boolean:continue?)
ascend :: any:element -> any:result-element
terminal :: any:element -> any:result-element
(tree-transform
  (l (a recurse)
    (list #f #t))
  (l (a)
    a)
  (l (a)
    a))

create filesystem paths from nested lists

(define input
  (q
    ("/usr"
      ("share" "guile")
      "include"
      "")))

(prefix-tree->path-list input)

result:

("/usr/share/guile" "/usr/include" "/usr/")

lambda pattern matching

actually not sph-lib specific, to be moved

(apply
  (lambda (a b c) #t)
  (list 1 2 3))

-> a:1 b:2 c:3

(apply
  (lambda (a b . c) #t)
  (list 1 2 3 4 5))

-> a:1 b:2 c:(3 4 5)

(apply
  (lambda* (a #:optional b) #t)
  (list 1 2))

-> a:1 b:2. if a shorter list (list 1) where given instead, then a:1 b:#f

(apply
  (lambda* (a #:key (b 8) c) #t)
  (list 1 #:b 2 #:c 3))

the special #: keyword syntax of lambda* is used to differentiate from normal symbols.

unfortunately, the following does not work

(apply
  (lambda (a . b) #t)
  (pair 1 2))

other

port-lines-map, streams, date stream, html multipart form data, fold-multiple, vector-accessor, call-at-interval, compact, parse indent-syntax, list-sort-with-accessor, map-slice, split-by-pattern, any->list