git.haldean.org ubik / fdc3ff8
add documentation about closure recursion Haldean Brown 5 years ago
1 changed file(s) with 78 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Recursive closures =====================================================
1 Haldean Brown First draft: Nov 2016
2 Last updated: Nov 2016
3
4 Status: Draft
5
6 ------------------------------------------------------------------------
7
8 The closure transformation turns closures into partially-applied
9 functions, by turning values that have been closed over into arguments
10 to the function itself. The specific algorithm for doing this is
11 detailed greatly in the header closure.c, but the general gist is that:
12
13 It transforms this:
14 \x -> (\y -> + x y)
15 To this:
16 \x -> ((\x0 y -> + x0 y) x)
17
18 It transforms this:
19 \x -> (\y -> (\z -> x))
20 Into this:
21 \x -> ((\x0 y -> ((\x1 z -> x1) x0)) x)
22
23 It transforms this:
24 \x -> {
25 : y = + x 10
26 ! \z -> y
27 }
28 Into this:
29 \x -> {
30 : y = + x 10
31 ! (\y0 z -> y0) y
32 }
33
34 This closes these functions over the enclosing scope by making all
35 enclosing scope information an explicit argument to the function, and
36 then partially applying the function over that information.
37
38 This document describes how the closure transformation interacts with
39 recursion for values that are not bound to a global name. For example,
40 this snippet:
41
42 ! {
43 : t = \x -> ? {
44 . eq x 0 => "ok\n"
45 . => t 0
46 }
47 ! t 1
48 }
49
50 In this example, the closure transformation should take t and turn it
51 into this:
52
53 : t = (\t x -> ? {
54 . eq x 0 => "ok\n"
55 . => t 0
56 }) t
57
58 But now we find ourselves referencing t before we've defined it, and we
59 can quickly get into a circular reference. Here, we transform t into a
60 top-level anonymous function with its own value:
61
62 : anonymous-t =
63 \t x -> ? {
64 . eq x 0 => "ok\n"
65 . => t 0
66 }
67
68 ! {
69 : t = anonymous-t anonymous-t
70 ! t 1
71 }
72
73 In so doing, we can fully define anonymous-t without any
74 self-references, and ditto with t. Note that in the actual
75 implementation of this feature, anonymous-t does not have a name in the
76 global namespace; it is fully anonymous and is only defined by its
77 value.