The defined? keyword in Ruby
An overview of the defined? keyword with a use case from the Ruby source code.. and an optimization tip!
In this article, we’re going to explore the following topics:
defined?in the context of
Before to start
I’m thrilled to share with you our latest project: Fun Facts about Ruby — Volume 1
Fun Facts about Ruby — Volume 1
Fun Facts about Ruby — Volume 1 is a collection of cards..
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
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? in the context of
This library simply monkey-patches
(IP|TCP|UDP|SOCKS)Socket classes provided by the
socket library to use the
Resolv DNS resolver.
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
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
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).
Now let’s see how using
defined? can positively impact the performances of your application.
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
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,
yield is never executed.
Ruby provides another way to achieve the same result:
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.
benchmark-ips reports to see what’s the difference between
We can see that
block_given? is 1.27x slower than
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.
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.
“The Old Pond” by Matsuo Bashō
An old silent pond
A frog jumps into the pond —
Splash! Silence again.