我正在尝试使用条件在Lua中构建一个小型DSL。
x = '0'
function start ()
return function () end
end
function set_x (v)
x = v
return function () end
end
function if_x (v)
if x == v then
print ("x = ", v)
else
print ("x != ", v)
end
return function () end
end
-- DSL here
start {
set_x '10',
if_x '10' { print ('x is 10') },
if_x '20' { print ('x is 20') }
}
输出是:
x = 10
x is 10
x != 20
x is 20
如何以优雅的方式实现条件,以便不打印x is 20
?如果不在set_x
中设置全局变量并在if_x
内进行检查,我就无法做到这一点,但这看起来很难看。
有任何线索吗?
谢谢!
答案 0 :(得分:4)
e.g。
x = '10'
function if_x (v)
if x == v then
return function (s)
assert(loadstring(s))()
end
end
return function() end
end
if_x '10' [[print('x is 10')]]
if_x '20' [[print('x is 20')]]
答案 1 :(得分:2)
你必须看看你的EDSL对Lua的样子;让我们剖析有问题的陈述
if_x '20' { print ('x is 20') }
我们可以使用#34; regular"重写它。这样的语法:
if_x('20')({ 1 = print('x is 20') })
我已添加1 =
来展示有问题的部分;数组的构造需要评估打印语句,无论你的条件是。
为了使它工作,你实际上需要一个lambda:
start {
set_x '10',
if_x '10' { function() print ('x is 10') end },
if_x '20' { function() print ('x is 20') end }
}
然后可以有条件地调用:
function if_x (v)
if x == v then
print ("x = ", v)
return function (block) block[1]() end
else
print ("x != ", v)
return function () end
end
end
不是很漂亮,但我认为你不能摆脱它,因为任何没有用lambda包裹的表达都需要执行。您可以尝试使用条件运算符的短路行为,但是您无法进一步传递代码,因为它总是会在函数边界进行评估。