aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/function/thunk.lux
blob: 12af1dfe2ab4282da9e05b2742db70c4aed7778a (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])
       [compiler]
       (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))]
    (lambda [_]
      (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 (compiler;gensym "")]
    (wrap (list (` (freeze' (lambda [(~ g!arg)] (~ expr))))))))

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