Let Over Lambda
https://letoverlambda.com/ is a excellent book about Common Lisp with a focus on the capabilities of its macros. These are some Nelua adaptions of its examples.
- aif
- sleep-units
- unhygienic variable injection
- conditional code
- hygienize and unwanted variable capture
aif
## local function aif(test, fthen, felse)
local it = #[test]#
if it then ## inject_statement(fthen)
else ## inject_statement(felse)
end
## end
local it = 'fake'
aif!(5, print(it), print('false'))
aif!(nil, print(it), print('false'))
assert(it == 'fake')
sleep-units
--[[
(defmacro sleep-units (value unit)
`(sleep
(* ,value
,(case unit
((s) 1)
((m) 60)
((h) 3600)
((d) 86400)
((ms) 1/1000)
((us) 1/1000000)))))
]]
local Duration = @enum{ s = 1, m, h, d, ms, us }
local function sleepunits(value: number, unit: Duration <comptime>)
## local units = { 1, 60, 3600, 86400, 1/1000, 1/1000000 }
print('faking sleep for: ', value * #[units[unit.value]]#)
end
sleepunits(3, Duration.h)
sleepunits(2, Duration.h)
sleepunits(3, Duration.ms)unhygienic variable injection
## function xinjector()
in x
## end
local x = 1
local y: []integer = {#[xinjector]#()+1, #[xinjector]#()+2}
print(x, y[0], y[1])conditional code
##[[
local doit
if pragmas.doit then
function doit(thing)
inject_statement(thing)
end
else
function doit(thing) end
end
]]
doit!(print('lalala'))
doit!(print '?')usage:
$ nelua pragrun.nelua $ nelua -Pdoit pragrun.nelua lalala ?
hygienize and unwanted variable capture
local obscure_name: integer
## local function nif(pos, zero, neg)
local function f(test: auto)
obscure_name = test
if obscure_name > 0 then ## inject_statement(pos)
elseif obscure_name == 0 then ## inject_statement(zero)
else ## inject_statement(neg)
end
end
## return f
## end
local old_obscure = &obscure_name
## nif = hygienize(nif)
local obscure_name: integer = 100
local x = 2
nif!(print '+', print '0', print '-')(x)
nif!(print '+', print '0', print '-')(-x)
print(obscure_name, $old_obscure)