ruby 中不带参数的 DSL 块

发布于 2025-01-04 11:32:37 字数 401 浏览 1 评论 0原文

我正在用 ruby​​ 编写一个简单的 dsl。几周前,我偶然发现了一些博客文章,其中展示了如何将以下代码转换

some_method argument do |book|
  book.some_method_on_book
  book.some_other_method_on_book :with => argument
end

为更简洁的代码:

some_method argument do
   some_method_on_book
   some_other_method_on_book :with => argument
end

我不记得如何执行此操作,我不确定缺点,但更简洁的语法很诱人。有人对这种转变有任何线索吗?

I'm writing a simple dsl in ruby. Few weeks ago I stumbled upon some blog post, which show how to transform code like:

some_method argument do |book|
  book.some_method_on_book
  book.some_other_method_on_book :with => argument
end

into cleaner code:

some_method argument do
   some_method_on_book
   some_other_method_on_book :with => argument
end

I can't remember how to do this and I'm not sure about downsides but cleaner syntax is tempting. Does anyone have a clue about this transformation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

So要识趣 2025-01-11 11:32:37
def some_method argument, &blk
  #...
  book.instance_eval &blk
  #...
end

更新:但是,这省略了书,但不允许您使用该参数。要透明地使用它,您必须以某种方式运输它。我建议在书本上这样做:

class Book
  attr_accessor :argument
end

def some_method argument, &blk
  #...
  book.argument = argument
  book.instance_eval &blk
  #...
end

some_method 'argument' do
   some_method_on_book
   some_other_method_on_book argument
end
def some_method argument, &blk
  #...
  book.instance_eval &blk
  #...
end

UPDATE: However, that omits book but don't let you use the argument. To use it transparently you must transport it someway. I suggest to do it on book itself:

class Book
  attr_accessor :argument
end

def some_method argument, &blk
  #...
  book.argument = argument
  book.instance_eval &blk
  #...
end

some_method 'argument' do
   some_method_on_book
   some_other_method_on_book argument
end
自此以后,行同陌路 2025-01-11 11:32:37

看看这篇文章 http://www.dan -manges.com/blog/ruby-dsls-instance-eval-with-delegation — 对该方法进行了概述(具体说明了其缺点和可能的解决方案),另外还有一些有用的链接供进一步阅读。

基本上,它是关于使用instance_eval 在所需的上下文中执行块。

谈论这种技术的缺点:

那么这有什么问题吗?嗯,问题是块是
一般都会倒闭。你期望它们实际上是完全关闭的。
从您编写块的角度来看,这一点并不明显
该块可能不是完全关闭。这就是当你
使用instance_eval:将该块的自身重置为某种东西
else - 这意味着该块仍然是所有本地块的闭包
块外的变量,但不适用于方法调用。我什至不
知道常量查找是否改变。

使用instance_eval会改变语言的规则,
读取块时并不明显。你需要考虑一个额外的步骤
找出你可以从词法上看到的方法调用的确切原因
块周围实际上不能从块内部调用。

Take a look at this article http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation — there is an overview of the method (specifically stated in the context of its downsides and possible solution to them), plus there're several useful links for further reading.

Basically, it's about using instance_eval to execute the block in the desirable context.

Speaking about downside of this technique:

So what's the problem with it? Well, the problem is that blocks are
generally closures. And you expect them to actually be full closures.
And it's not obvious from the point where you write the block that
that block might not be a full closure. That's what happens when you
use instance_eval: you reset the self of that block into something
else - this means that the block is still a closure over all local
variables outside the block, but NOT for method calls. I don't even
know if constant lookup is changed or not.

Using instance_eval changes the rules for the language in a way that
is not obvious when reading a block. You need to think an extra step
to figure out exactly why a method call that you can lexically see
around the block can actually not be called from inside of the block.

楠木可依 2025-01-11 11:32:37

查看 docile gem。它可以处理所有锋利的边缘,使这对您来说非常容易。

Check out the docile gem. It takes care of all the sharp edges, making this very easy for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文