ruby 对象定义
In this article, we’re going to explore the following topics:
在本文中,我们将探讨以下主题:
the
defined?
keyworddefined?
关键词defined?
in the context ofresolv-replace
defined?
在解决resolv-replace
的背景下defined? yield
vsblock_given?
defined? yield
defined? yield
vsblock_given?
开始之前 (Before to start)
I’m thrilled to share with you our latest project: Fun Facts about Ruby — Volume 1
我很高兴与您分享我们的最新项目:有关Ruby的有趣事实-第1卷
Please feel free to spread the word and share this link! 🙏
请随时宣传并分享此链接! 🙏
Thank you for your time!
感谢您的时间!
定义的? 关键词 (The defined? keyword)
In Ruby, the defined?
keyword returns a string that represents the type of the entity passed as argument. Here is an exhaustive list of what you can pass to defined?
在Ruby中, defined?
关键字返回一个字符串,该字符串表示作为参数传递的实体的类型。 以下是您可以传递给defined?
的详尽列表defined?
defined? String # => "constant"
defined? puts # => "method"
defined? [1, 2] # => "expression"
@@a, @a, a = 21, 42, 84
defined? @aa # => "class variable"
defined? @a # => "instance-variable"
defined? a # => "local-variable"
defined? a = 2 # => "assignment"
defined? $$ # => "global-variable"
def hello
defined? yield
end
hello {} # => "yield"
class A
def hello; end
end
class B
def hello
defined? super
end
end
B.new.hello # => "super"
Here, we can see that defined?
handles a maximum of cases. But some cases are more relevant than others. For example, let’s see how the resolv-replace
library — available in the Ruby Standard Library — takes advantage of this keyword to handle a really “tricky” case.
在这里,我们可以看到defined?
处理最多案件。 但是有些情况比其他情况更相关。 例如,让我们看看Ruby Standard Library中提供的resolv-replace
库如何利用此关键字来处理真正的“棘手”情况。
定义的? 在解决resolv-replace
的背景下 (defined? in the context of resolv-replace
)
This library simply monkey-patches (IP|TCP|UDP|SOCKS)Socket
classes provided by the socket
library to use the Resolv
DNS resolver.
该库只是对socket
库提供的(IP|TCP|UDP|SOCKS)Socket
类(IP|TCP|UDP|SOCKS)Socket
猴子修补,以使用Resolv
DNS解析器。
In the case of SOCKSSocket
, the monkey-patching only intervenes when the Ruby interpreter is compiled with the --enable-socks
flag. So let’s see how the resolv-replace
library handles this tricky case
对于SOCKSSocket
,仅当使用--enable-socks
标志编译Ruby解释器时,才会进行猴子修补。 那么,让我们看看resolv-replace
库如何处理这个棘手的情况
# in lib/resolv-replace.rb
class SOCKSSocket < TCPSocket
# :stopdoc:
alias original_resolv_initialize initialize
# :startdoc:
def initialize(host, serv)
original_resolv_initialize(IPSocket.getaddress(host), port)
end
end if defined? SOCKSSocket
Notice the modifier-if
line 10. Indeed, to choose to monkey-patch this class or not, the resolv-replace
library simply checks if the SOCKSSocket
constant is defined using the defined?
keyword. Indeed, as seen in the previous section, SOCKSSocket
is only defined if the Ruby interpreter is compiled using the --enable-flag
.
请注意修饰符- if
第10行。的确,要选择是否对此类进行猴子修补, resolv-replace
库仅检查SOCKSSocket
常量是否使用已defined?
关键词。 确实,如上一节所述,仅当使用--enable-flag
编译Ruby解释器时,才定义SOCKSSocket
。
So, as the class
keyword is only a syntactic sugar for class definition and class opening, then you can call a modifier-if to execute this code (or not).
因此,由于class
关键字只是用于类定义和类打开的语法糖,因此您可以调用修饰符-if以执行此代码(或不执行)。
Now let’s see how using defined?
can positively impact the performances of your application.
现在让我们看看如何使用defined?
可以对应用程序的性能产生积极影响。
(收益率)vs block_given? (defined?(yield) vs block_given?)
If in your program you deal with a huge amount of blocks, then defined? yield
can definitely become a real optimization for your program performance. Indeed, to check if a block is passed to your method, you normally use the Kernel#block_given?
method
如果在您的程序中您处理了大量的块,那么defined? yield
defined? yield
绝对可以成为您程序性能的真正优化。 确实,要检查是否将块传递给您的方法,通常使用Kernel#block_given?
方法
def method_with_block_given
yield if block_given?
end
method_with_block_given { 42 } # => 42
method_with_block_given # => nil
Here method_with_block_given
checks if a block is passed as argument by using Kernel#block_given?
. If so, then yield
is called and the block is executed. Otherwise, block_given?
returns false
and yield
is never executed.
这里method_with_block_given
通过使用Kernel#block_given?
检查是否将块作为参数传递Kernel#block_given?
。 如果是这样,则调用yield
并执行该块。 否则, block_given?
返回false
并且永不执行yield
。
Ruby provides another way to achieve the same result: defined?(yield)
Ruby提供了另一种获得相同结果的方法: defined?(yield)
def method_with_defined_yield
yield if defined?(yield)
end
method_with_defined_yield {42} # => 42
method_with_defined_yield # => nil
The main difference between these 2 expressions is that defined?(yield)
is faster than Kernel#block_given?
. Indeed, it’s a keyword when the block_given?
is a method. So block_given?
is slower because of the cost of the method call added to the cost of the Method Lookup Path.
这两个表达式之间的主要区别在于,已defined?(yield)
比Kernel#block_given?
。 确实,当block_given?
时,它是一个关键字block_given?
是一种方法。 那么block_given?
由于方法调用的成本增加了方法查找路径的成本,因此速度较慢。
Let’s generate benchmark-ips
reports to see what’s the difference between defined?(yield)
and block_given?
让我们生成benchmark-ips
报告,以查看block_given?
defined?(yield)
和block_given?
之间有什么区别block_given?
require 'benchmark/ips'
def method_with_block_given
yield if block_given?
end
def method_with_defined_yield
yield if defined?(yield)
end
Benchmark.ips do |x|
x.config(:time => 5, :warmup => 2)
x.report("block_given?") { method_with_block_given {42} }
x.report("defined? yield") { method_with_defined_yield {42} }
x.compare!
end
We can see that block_given?
is 1.27x slower than defined?(yield)
.
我们可以看到那个block_given?
比defined?(yield)
速度慢1.27倍defined?(yield)
。
But as seen in the above benchmark, we’re able to call block_given
9.897M times in a second. So keep in mind that this optimization is only relevant on a huge amount of block calls.
但是从上述基准中可以看出,我们能够在一秒钟内调用block_given
9.897M次。 因此请记住,此优化仅与大量的块调用有关。
结论 (Conclusion)
defined?
isn’t the most popular keyword in Ruby. Nevertheless, in some situations this keyword becomes a powerful asset to enhance your program performance or to handle tricky cases where a constant, method, etc.. is conditionally loaded. Please feel free to share with us your experience with this keyword in the comments section.
defined?
不是Ruby中最受欢迎的关键字。 但是,在某些情况下,此关键字成为增强程序性能或处理有条件地加载常量,方法等的棘手情况的强大资产。 请随时在评论部分与我们分享您使用此关键字的经验。
Voilà!
瞧!
松尾芭蕉的“老池塘” (“The Old Pond” by Matsuo Bashō)
An old silent pond
一个古老的无声池塘
A frog jumps into the pond —
一只青蛙跳进池塘里—
Splash! Silence again.
溅! 再次沉默。
翻译自: https://medium.com/rubycademy/the-defined-keyword-in-ruby-b7a5a5a48e1e
ruby 对象定义