ruby - 需要帮助改进 Ruby DSL 以控制 Arduino 控制的饮料分配器(bar monkey)

标签 ruby language-design dsl arduino

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

它目前正在读取一个食谱(见下文)并将其打印出来。串行通信的代码以及我在下面提到的其他一些想法仍然需要改进。

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

我目前有 DSL 的粗略草稿,因此饮料配方如下所示 (Github link):

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

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

[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 项目是here ,请随意 fork 和提出拉取请求,或在此处发布您的代码建议和示例以供其他用户查看。如果你很好奇,使用 Ruby Arduino 开发框架的 Arduino 代码是 here .

更新

我对内容进行了一些修改和清理,以反射(reflect) Orion Edwards 对食谱的建议。现在看起来像下面这样。

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

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

最佳答案

在不查看实现细节(或您的 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

希望对您有所帮助!

关于ruby - 需要帮助改进 Ruby DSL 以控制 Arduino 控制的饮料分配器(bar monkey),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/164095/

相关文章:

ruby - 如何使用 Ruby twitter gem 获取给定 ID/句柄的关注者列表?

ruby - 为什么 Ruby 会针对私有(private)属性抛出警告

node.js - 如何执行子聚合来计算每个存储桶中没有值的字段?

scala - Scala 的 SQL DSL

arrays - 通过嵌套数组对计算公共(public)元素的最简洁方法

ruby-on-rails - 创建 Rails 新项目时出错 (../config/boot (LoadError)

java - 编写简单语言的解析器

ruby - 为什么 'super' 在 Ruby 中是关键字而不是方法?

haskell - 如何在我的 DSL 中处理许多不同类型的操作?

ruby-on-rails - 在 rails 3 上使用 i18n 延迟作业