aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/control/thunk.lux
blob: a78f78023e1e2d3ba651236fcf6c4e1d5ffffbb3 (plain)
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
(;module:
  lux
  (lux [io]
       (control monad)
       (concurrency ["A" atom])
       [macro]
       (macro ["s" syntax #+ syntax:])))

(type: #export (Thunk a)
  (-> [] a))

(def: #hidden (freeze' generator)
  (All [a] (-> (-> [] a) (-> [] a)))
  (let [cache (: (A;Atom (Maybe ($ +0)))
                 (A;atom #;None))]
    (function [_]
      (case (io;run (A;get cache))
        (#;Some value)
        value

        _
        (let [value (generator [])]
          (exec (io;run (A;compare-and-swap _ (#;Some value) cache))
            value))))))

(syntax: #export (freeze expr)
  (do @
    [g!arg (macro;gensym "")]
    (wrap (list (` (freeze' (function [(~ g!arg)] (~ expr))))))))

(def: #export (thaw thunk)
  (All [a] (-> (Thunk a) a))
  (thunk []))