1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
; ʞ / interlace.scm
; a scheme library by lexi hale
;
; (interlace) solves an age-old problem. what kind of data structure
; do you use when you need both an aggregate (a list, a vector) of
; items but also to be able to individually refer to those items by
; name? this problem is effectively unsolvable in C and C++ without
; inordinate runtime overhead, and there's no native syntax for it
; in Scheme. however, by rewriting the AST, we can implement a clean,
; performant, low-cost solution ourselves, thanks to the fact that
; (let*) bindings are expressions.
;
; interlace takes a constructor function, e.g. (vector) or (list),
; a list of items, and returns an expression calling that constructor
; on a list of all items defined in it. if an item is proceded by
; an atom that ends in a period (e.g. “name.”), it is defined within
; a (let*) expression, and its name is then included among the
; arguments passed to the constructor function.
;
; the upshot of this is that items can reference other items by name
; *as they are being defined*. for instance:
;
; (define verbs (interlace vector
; talk. (verb "talk" "talking" "talked")
; (phrasal-verb talk "to")
; (phrasal-verb talk "about")
; (verb "say" "saying" "said)))
;
; here, the function to generate a phrasal verb exhibits backreference
; to an existing verb contained alongside it in the vector. note that
; the name bindings are ephemeral; they do not survive the immediate
; context of the constructor.
(define-macro (interlace . body)
; given a list with both named and nameless members, identify
; which is which and instate the vector.
(define (name? term)
; given a symbol, determine wheter it is a name, and if so return
; that name as a string and without the name-marking suffix ‹.›
|
|
|
>
>
>
|
<
<
<
>
>
>
>
|
<
>
|
|
>
|
<
>
>
|
|
<
<
>
>
<
>
>
|
|
|
|
|
|
|
<
>
>
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
; [ʞ] interlace.scm
; ~ lexi hale <lexi@hale.su>
; © affero general public license
; > (load "lib/lisp-macro.scm")
; (load "lib/interlace.scm")
; (interlace) solves an old problem. what kind of data
; structure do you use when you need both an aggregate
; (a list, a vector) of items but also to be able
; to individually refer to those items by name? this
; problem is effectively unsolvable in C and C++ without
; inordinate runtime overhead, and there's no native
; syntax for it in Scheme. however, by rewriting the AST,
; we can implement a clean, performant, low-cost solution
; ourselves, thanks to the fact that (let*) bindings are
; expressions.
;
; interlace takes a constructor function, e.g. (vector)
; or (list), a list of items, and returns an expression
; calling that constructor on a list of all items defined
; in it. if an item is proceded by an atom that ends in a
; period (e.g. “name.”), it is defined within a (let*)
; expression, and its name is then included among the
; arguments passed to the constructor function.
;
; the upshot of this is that items can reference other
; items by name *as they are being defined*. for
; instance:
;
; ex: (define verbs (interlace vector
; talk. (verb "talk" "talking" "talked")
; (phrasal-verb talk "to")
; (phrasal-verb talk "about")
; (verb "say" "saying" "said)))
;
; here, the function to generate a phrasal verb exhibits
; backreference to an existing verb contained alongside
; it in the vector. note that the name bindings are
; ephemeral; they do not survive the immediate context of
; the constructor.
(define-macro (interlace . body)
; given a list with both named and nameless members, identify
; which is which and instate the vector.
(define (name? term)
; given a symbol, determine wheter it is a name, and if so return
; that name as a string and without the name-marking suffix ‹.›
|