6

我正在用 Ruby 编写 DSL 来控制我正在从事的 Arduino 项目;巴迪诺。这是一个酒吧猴子,将由软件控制以提供饮料。Arduino 通过串行端口接收命令,告诉 Arduino 要打开哪些泵以及打开多长时间。

它当前读取一个配方(见下文)并将其打印出来。串行通信的代码以及我在下面提到的其他一些想法仍然需要处理。

这是我的第一个 DSL,我正在处理前面的示例,所以它的边缘非常粗糙。任何批评、代码改进(对于 Ruby DSL 最佳实践或习语有什么好的参考吗?)或任何一般性评论。

我目前有一份 DSL 的草稿,所以饮料配方如下所示(Github 链接):

desc "Simple glass of water"
recipe "water" do
  ingredients(
  "Water" => 2.ounces
  )
end

这反过来被解释,目前结果如下(Github 链接):

[mwilliams@Danzig barduino-tender]$ ruby barduino-tender.rb examples/water.rb
Preparing: Simple glass of water

Ingredients:
 Water: 2 ounces

这对于 DSL 来说是一个好的开始,但是,我确实认为它可以实现得更好一些。我有以下一些想法:

  1. 使用成分的名称和它所连接的数字泵来定义可用的“成分”。也许使用哈希?成分 = {“水” => 1,“伏特加” => 2}。这样,当一种成分被解释时,它可以 a)通过串行端口发送泵号,然后是 Arduino 分配的盎司数 b)告诉用户成分不存在并中止,因此没有分配 c)如果它们被改变,很容易有能力改变或添加新的成分。
  2. 让菜谱看起来不像代码,这是 DSL 的主要目的,也许构建一个菜谱构建器?使用可用的成分提示用户输入饮料名称、涉及的成分和多少?

Github 项目在这里,请随时 fork 并提出拉取请求,或在此处发布您的代码建议和示例以供其他用户查看。如果您完全好奇,这里是使用 Ruby Arduino 开发框架的 Arduino 代码。

更新

我修改和清理了一些东西,以反映 Orion Edwards 对食谱的建议。现在看起来如下所示。

description 'Screwdriver' do 
  serve_in 'Highball Glass'
  ingredients do
    2.ounces :vodka
    5.ounces :orange_juice
  end
end

我还添加了一个哈希(键是成分和它所连接的泵号的值)。我认为这提供了很大的进步。我暂时将这个问题留待任何进一步的建议,但最终会选择 Orion 的答案。更新的 DSL 代码在这里

4

3 回答 3

5

在不查看实现细节(或您的 github 链接)的情况下,我会尝试编写这样的 DSL:

(从这里偷:http ://supercocktails.com/1310/Long-Island-Iced-Tea- )

describe "Long Island Iced Tea" do
  serve_in 'Highball Glass'

  ingredients do
    half.ounce.of :vodka
    half.ounce.of :tequila
    half.ounce.of :light_rum
    half.ounce.of :gin
    1.dash.of :coca_cola
    #ignoring lemon peel as how can a robot peel a lemon?
  end

  steps do
    add :vodka, :tequila, :light_rum, :gin
    stir :gently
    add :coca_cola
  end
end

希望有帮助!

于 2008-10-02T20:16:28.553 回答
3

如果你想让食谱看起来更自然,为什么不(来自 Orion Ewards 使用的相同食谱,谢谢!):

Recipe for Long Island Iced Tea #1
Ingredients:
  1/2 oz Vodka
  1/2 oz Tequila
  1/2 oz Light Rum
  1/2 oz Gin
  1 Dash Coca-Cola
  # ignored Twist of Lemon Peel (or Lime)

然后将Treetop添加到混合物中。你可以有如下规则:

grammar Cocktail
  rule cocktail
    title ingredients
  end

  rule title
    'Recipe for' S text:(.*) EOF
  end

  rule ingredients
    ingredient+
  end

  rule ingredient
    qty S liquid
  end
# ...
end

树顶编译器将转换为一个不错的 ruby​​ 模块。然后:

parser = CocktailParser.new
r = parser.parse(recipe)
于 2008-12-13T21:16:24.823 回答
1

Orion 的 DSL 看起来很不错。我可能建议您“更新”代码的唯一更改是

  1. 替换descriptionrecipe。这是一个更具描述性的术语
  2. 由于成分和动作的集合是固定的,因此将成分绑定到变量而不是符号,即您已在vodka = :vodka某个地方定义。它更容易说

    混合伏特加、杜松子酒和triple_sec # 而不是使用:vodka、:gin 和:triple_sec。

无论如何,这是一个小问题。

于 2008-10-03T05:50:06.507 回答