@@ -1055,7 +1055,7 @@ not all:
1055
1055
These represent major flaws, hence expressions in WHNF should be only used with
1056
1056
great caution. */
1057
1057
1058
- export const Lazy = ( thunk , tag = "Thunk" ) => {
1058
+ export const Lazy = ( { tag , cons = tag } ) => thunk => {
1059
1059
let state = {
1060
1060
thunk : thunk ,
1061
1061
evaluated : false ,
@@ -1071,11 +1071,9 @@ export const Lazy = (thunk, tag = "Thunk") => {
1071
1071
}
1072
1072
1073
1073
const forceEval = target => {
1074
- if ( target . evaluating ) {
1075
- throw new LazyError ( "cyclic lazy evaluation detected" ) ;
1076
- }
1074
+ if ( target . evaluating ) throw new LazyError ( "cyclic lazy evaluation" ) ;
1077
1075
1078
- if ( ! target . evaluated ) {
1076
+ else if ( ! target . evaluated ) {
1079
1077
try {
1080
1078
target . evaluating = true ;
1081
1079
target . value = target . thunk ( ) ;
@@ -1099,6 +1097,7 @@ export const Lazy = (thunk, tag = "Thunk") => {
1099
1097
1100
1098
if ( prop === $ ) return tag ;
1101
1099
else if ( prop === $$ ) return tag ;
1100
+ else if ( prop === Lazy . thunk ) return true ;
1102
1101
1103
1102
const value = target . state . evaluated
1104
1103
? target . state . value
@@ -1127,7 +1126,7 @@ export const Lazy = (thunk, tag = "Thunk") => {
1127
1126
1128
1127
if ( prop === $ ) return true ;
1129
1128
else if ( prop === $$ ) return true ;
1130
- else if ( prop === Lazy . thunk ) return true ; // reveal proxy
1129
+ else if ( prop === Lazy . thunk ) return true ;
1131
1130
1132
1131
const value = target . state . evaluated
1133
1132
? target . state . value
@@ -1214,13 +1213,16 @@ export const Lazy = (thunk, tag = "Thunk") => {
1214
1213
} ;
1215
1214
1216
1215
1216
+ export const lazy = Lazy ( "Thunk" ) ;
1217
+
1218
+
1217
1219
Lazy . thunk = Symbol ( "thunk" ) ;
1218
1220
1219
1221
1220
- Lazy . eager = x => {
1221
- if ( Object ( x ) !== x ) return x ;
1222
- while ( Lazy . thunk in x ) x = x ( ) ;
1223
- return x ;
1222
+ Lazy . eager = thunk => {
1223
+ if ( typeof thunk !== "function" ) return thunk ;
1224
+ while ( thunk [ Lazy . thunk ] ) thunk = thunk ( ) ;
1225
+ return thunk ;
1224
1226
} ;
1225
1227
1226
1228
@@ -3857,6 +3859,75 @@ Iit.tails = function* (ix) {
3857
3859
} ;
3858
3860
3859
3861
3862
+ /*█████████████████████████████████████████████████████████████████████████████
3863
+ ███████████████████████████████████████████████████████████████████████████████
3864
+ ████████████████████████████████████ LIST █████████████████████████████████████
3865
+ ███████████████████████████████████████████████████████████████████████████████
3866
+ ███████████████████████████████████████████████████████████████████████████████*/
3867
+
3868
+
3869
+ /* Lazy list type specifically for cases where lots of consings are required.
3870
+ List consing benefits from structural sharing in lists and thus doesn't rely on
3871
+ mutations. Please note that the list type is stack-safe. While lists themselves
3872
+ are lazily constructed, the eliminiation of lists happens within an imperative
3873
+ loop. */
3874
+
3875
+
3876
+ export const List = { } ;
3877
+
3878
+
3879
+ List . Nil = scope ( ( ) => {
3880
+ const empty = [ ] ;
3881
+ empty [ $ ] = "List" ;
3882
+ empty [ $$ ] = "List.Nil" ;
3883
+ return Object . freeze ( empty ) ;
3884
+ } ) ;
3885
+
3886
+
3887
+ List . Cons = x => xs => {
3888
+ const pair = [ x , xs ] ;
3889
+ pair [ $ ] = "List" ;
3890
+ pair [ $$ ] = "List.Cons" ;
3891
+ return pair ;
3892
+ } ;
3893
+
3894
+
3895
+ // unconsing is redundant due to pair structure
3896
+
3897
+
3898
+ /*█████████████████████████████████████████████████████████████████████████████
3899
+ █████████████████████████████████ COMBINATORS █████████████████████████████████
3900
+ ███████████████████████████████████████████████████████████████████████████████*/
3901
+
3902
+
3903
+ List . map = f => function go ( xs ) {
3904
+ if ( xs === List . Nil ) return xs ;
3905
+ else return List . Cons ( f ( xs [ 0 ] ) ) ( lazy ( ( ) => go ( xs [ 1 ] ) ) ) ;
3906
+ } ;
3907
+
3908
+
3909
+ // a real right associative but stack-safe fold!!!
3910
+
3911
+ List . foldr = f => acc => xs => {
3912
+ while ( true ) {
3913
+ const ys = Lazy . eager ( xs ) ;
3914
+ if ( ys === List . Nil ) return acc ;
3915
+ else acc = f ( ys [ 0 ] ) ( acc ) ;
3916
+ xs = ys [ 1 ] ;
3917
+ }
3918
+ } ;
3919
+
3920
+
3921
+ List . forEach = f => xs => {
3922
+ while ( true ) {
3923
+ const ys = Lazy . eager ( xs ) ;
3924
+ if ( ys === List . Nil ) break ;
3925
+ else f ( ys [ 0 ] ) ;
3926
+ xs = ys [ 1 ] ;
3927
+ }
3928
+ } ;
3929
+
3930
+
3860
3931
/*█████████████████████████████████████████████████████████████████████████████
3861
3932
███████████████████████████████████████████████████████████████████████████████
3862
3933
█████████████████████████████████████ MAP █████████████████████████████████████
0 commit comments