local function eval (prog, env) local env = env or {} local last for _, fn in ipairs (prog) do last = fn (env) end return last end local function force (env) return function (x) if type (x) == "function" then x = x (env) end return x end end local function keywords_for (apply) return function (word_list) local keywords = {} for _, word in ipairs (word_list) do keywords[word] = apply end return setmetatable (keywords, {__call = function (t, ...) return apply(...) end}) end end local function default (apply) return function (operations) return setmetatable (operations, {__call = function (t, ...) return apply (...) end}) end end local function let (var) local _let = function (val) return function (env) env[force (env) (var)] = force (env) (val) end end return keywords_for (_let) { "equal", "be" } end local function get (var) return function (env) return env[force (env) (var)] end end local function add (x) local _add = function (y) return function (env) return force (env) (x) + force (env) (y) end end return keywords_for (_add) { "to", "with" } end local function show (val) local _show = function (env) print (force (env) (val)) end return _show end local function is (a) local _equals = function (b) return function (env) return force (env) (a) == force (env) (b) end end return default (_equals) { greater_than = function (b) return function (env) return force (env) (a) > force (env) (b) end end, less_than = function (b) return function (env) return force (env) (a) < force (env) (b) end end, } end local function when (cond) local _when = function (when_true) local _when_false = function (when_false) return function (env) if force (env) (cond) then return eval (when_true, env) else return eval (when_false, env) end end end return keywords_for (_when_false) { "otherwise" } end return _when end local function rand () return math.random () end local function return_with (value) return function (env) return value end end math.randomseed (os.time ()) eval { show ( when (is (rand) .greater_than (0.5)) { show "Wow! The value was..." ; return_with "High :>" ; } .otherwise { show "Damn, the value was..." ; return_with "Low :<" ; } ) }