2016-04-08 3 views
2

Я пытаюсь построить небольшую DSL в Lua с условными обозначениями.Условные обозначения для 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, но это выглядит уродливо.

Любой ключ?

Спасибо!

+1

И, о, BTW, то, что у вас есть, обычно называется ** E ** DSL (встроенный DSL), поскольку использует существующие языковые конструкции. –

ответ

2

Вы должны посмотреть, как выглядит ваш EDSL для Lua; давайте проанализируем проблемного заявление

if_x '20' { print ('x is 20') } 

Мы можем переписать его, используя «обычный» синтаксис как таковые:

if_x('20')({ 1 = print('x is 20') }) 

я добавил 1 = продемонстрировать проблемную часть; для построения массива требуется оценка заявления печати независимо от вашего состояния.

Для того, чтобы сделать его работу, вы на самом деле нужен лямбда:

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 

Не так красиво, но я не думаю, что вы может избавиться от этого, потому что любое выражение, не обернутое лямбдой, должно выполняться. Вы можете попробовать сыграть в режиме короткого замыкания оператора условного оператора, но тогда вы не сможете передать код дальше, потому что он всегда будет оцениваться на границах функций.

See Live on Ideone

4

например,

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')]] 
+2

Чтобы уточнить: '[[x]]' является альтернативным синтаксисом для '' x "' в Lua. Таким образом, строки 'print ...' на самом деле являются строками, которые условно передаются в парсер Lua во время выполнения. Вот как этот ответ решает проблему оценки: это строка, которая передается 'if_x' не как функция, а результат выражения. Неплохо! :) –