gpt4 book ai didi

ruby - ruby如何解析lambda或block中的 `self`关键字?

转载 作者:行者123 更新时间:2023-12-02 08:00:10 26 4
gpt4 key购买 nike

就像 JavaScript 一样,在 ruby​​ 中,lambda 可以传递给函数。

在 JavaScript 中 this 将被解析为调用者对象。

但是 ruby 呢?相同的机制是否也适用于 ruby​​ 的 lambda 或 block ?如何?能给我一些示例代码吗?

顺便说一下,我读过 The Ruby Programming Language ,但我找不到任何有用的信息..

最佳答案

在 Ruby 中,self 是词法范围的,即 self 在 block 或 lambda 中是在同一位置而不在 block 或 lambda 中的任何内容。

class << foo = Object.new
def bar
puts "`self` inside `foo#bar` is #{self.inspect}"
yield self
end
end

this = self

foo.bar do |that|
puts "`self` inside the block is #{self.inspect}"
case
when this.equal?(self)
puts "… which is the same as outside the block."
when that.equal?(self)
puts "… which is the same as inside the method."
else
puts "Ruby is really weird, `self` is something completely different!"
end
end

# `self` inside `foo#bar` is #<Object:0xdeadbeef48151623>
# `self` inside the block is main
# … which is the same as outside the block.

这也适用于 lambda:

class << foo = Object.new
def bar(lambda)
# ↑↑↑↑↑↑↑↑
puts "`self` inside `foo#bar` is #{self.inspect}"
lambda.(self)
#↑↑↑↑↑↑↑↑↑↑↑↑
end
end

this = self

foo.bar(-> that do
# ↑↑↑↑↑↑↑↑
puts "`self` inside the lambda is #{self.inspect}"
case
when this.equal?(self)
puts "… which is the same as outside the lambda."
when that.equal?(self)
puts "… which is the same as inside the method."
else
puts "Ruby is really weird, `self` is something completely different!"
end
end)

# `self` inside `foo#bar` is #<Object:0xdeadbeef48151623>
# `self` inside the lambda is main
# … which is the same as outside the lambda.

,但是,改变self的非常具体的反射方法是固定数量的,这些是中的方法>*_{exec|eval}<​​ 系列:

示例(仅更改上面的相关行):

class << foo = Object.new
def bar(&blk)
# ↑↑↑↑↑↑
puts "`self` inside `foo#bar` is #{self.inspect}"
instance_exec(self, &blk)
#↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
end
end

this = self

foo.bar do |that|
puts "`self` inside the block is #{self.inspect}"
case
when this.equal?(self)
puts "… which is the same as outside the block."
when that.equal?(self)
puts "… which is the same as inside the method."
else
puts "Ruby is really weird, `self` is something completely different!"
end
end

# `self` inside `foo#bar` is #<Object:0xdeadbeef48151623>
# `self` inside the block is #<Object:0xdeadbeef48151623>
# … which is the same as inside the method.
# ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

这也适用于 lambda(转换为 block ):

foo.bar(&-> that do
# ↑↑↑↑↑↑↑↑
puts "`self` inside the lambda is #{self.inspect}"
case
when this.equal?(self)
puts "… which is the same as outside the lambda."
when that.equal?(self)
puts "… which is the same as inside the method."
else
puts "Ruby is really weird, `self` is something completely different!"
end
end)

# `self` inside `foo#bar` is #<Object:0xdeadbeef48151623>
# `self` inside the lambda is #<Object:0xdeadbeef48151623>
# … which is the same as inside the method.
# ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

最后,Ruby 允许您以反射方式将特定调用站点的词法环境具体化为 Binding。目的。然后,您可以依次使用绑定(bind)的 Binding#eval 在此特定绑定(bind)的上下文中评估代码。方法或将绑定(bind)对象传递给 Kernel#eval :

class << foo = Object.new
def bar(str)
puts "`self` inside `foo#bar` is #{self.inspect}"
binding.eval(str)
#↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
end
end

$this = self

foo.bar <<~'HERE'
puts "`self` inside the eval'd string is #{self.inspect}"
if $this.equal?(self)
puts "… which is the same as outside the eval'd string."
end
HERE

# `self` inside `foo#bar` is #<Object:0x0070070070070070>
# `self` inside the eval'd string is #<Object:0x0070070070070070>

self 是 Ruby 中三个隐式上下文之一:

  • self
  • 默认定义者
  • 常量查找上下文

yugui 有一篇不错的博客文章,主要讨论了默认定义,但也简要介绍了self:Three implicit contexts in Ruby .还有一篇更详细的日文文章:Rubyの呼び出し可能オブジェクトの比較 (3) - なんかklassの話 .

关于ruby - ruby如何解析lambda或block中的 `self`关键字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58296007/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com