Skip to content

Instantly share code, notes, and snippets.

@alandipert
Created July 20, 2012 08:40
Show Gist options
  • Select an option

  • Save alandipert/3149656 to your computer and use it in GitHub Desktop.

Select an option

Save alandipert/3149656 to your computer and use it in GitHub Desktop.
From Löb's Theorem to Spreadsheet Evaluation <http://blog.sigfpe.com/2006/11/from-l-theorem-to-spreadsheet.html>
(ns loeb
"From Löb's Theorem to Spreadsheet Evaluation <http://blog.sigfpe.com/2006/11/from-l-theorem-to-spreadsheet.html>"
(:use [clojure.walk :only (postwalk)]))
(defn arg-trampoline
"Like trampoline, but always invokes functions with the supplied
arg. If f is not a function, it is returned without invocation."
[f arg]
(if (fn? f)
(let [ret (f arg)]
(if (fn? ret)
(recur ret arg)
ret))
f))
(defn tjuxt
"Trampolining juxt. Like juxt, but each fn is trampolined using
arg-trampoline."
[& fns]
(fn [argv]
((apply juxt (map #(partial arg-trampoline % argv) fns)))))
(defn loeb
([coll] (loeb coll coll))
([fns coll] ((apply tjuxt fns) coll)))
(defn !!
"Selector. Returns a function that takes an associative argument
and returns the value at k."
[k]
#(get % k))
(defn &
[f]
(fn [& fns]
(fn [coll]
(apply f (loeb fns coll)))))
(comment
(loeb [7 (!! 0) ((& +) (!! 0) (!! 1))]) ; => [7 7 14]
;; Haskell: loeb [ (!!5), 3, (!!0) + (!!1), (!!2)*2, sum . take 3, 17]
;; Clojure:
(loeb [(!! 5)
3
((& +) (!! 0) (!! 1))
((& *) (!! 2) 2)
#(reduce + (loeb (take 3 %) %))
17])
;; => [17 3 20 40 40 17]
)
;;;
;;; Experimental sheet syntax
;;;
(defn convert-form [form]
(cond
;; convert field references to selector functions
(and (symbol? form) (= (first (str form)) \_))
`(!! ~(Integer/parseInt (.substring (str form) 1)))
;; lift function calls
(list? form)
(let [[[_ op] & args] form] `((& ~op) ~@args))
;; everything else becomes a constant function of itself
:else
`(constantly ~form)))
(defn fn-idxs [v]
(let [function? #(and (list? %) (= (first %) 'fn))]
(keep-indexed #(when (function? %2) %1) v)))
(defn mergev [v m]
(reduce (fn [xs [k v]] (assoc xs k v)) v m))
(defmacro sheet [v]
(let [idxs (fn-idxs v)
fns (select-keys v idxs)
without-fns (mergev v (zipmap idxs (repeat nil)))]
`(loeb ~(mergev (second (postwalk convert-form without-fns)) fns))))
(comment
(sheet [7 _0 (+ _0 _1)]) ;=> [7 7 14]
;; Haskell: loeb [ (!!5), 3, (!!0) + (!!1), (!!2)*2, sum . take 3, 17]
;; Clojure:
(def sum #(reduce + %))
(sheet
[_5, 3, (+ _0 _1), (* _2 2), (fn [s] (sum (loeb (take 3 s) s))), 17])
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment