拥有Lua DSL的条件?

时间:2016-04-08 13:22:54

标签: lua conditional dsl

我正在尝试使用条件在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内进行检查,我就无法做到这一点,但这看起来很难看。

有任何线索吗?

谢谢!

2 个答案:

答案 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包裹的表达都需要执行。您可以尝试使用条件运算符的短路行为,但是您无法进一步传递代码,因为它总是会在函数边界进行评估。

See Live on Ideone