{"id":429,"date":"2015-01-11T10:38:27","date_gmt":"2015-01-11T15:38:27","guid":{"rendered":"http:\/\/codefork.com\/blog\/?p=429"},"modified":"2015-06-06T11:25:00","modified_gmt":"2015-06-06T15:25:00","slug":"demystifying-ruby-functions","status":"publish","type":"post","link":"https:\/\/codefork.com\/blog\/index.php\/2015\/01\/11\/demystifying-ruby-functions\/","title":{"rendered":"Demystifying Ruby functions"},"content":{"rendered":"<p>(NOTE: Edited slightly on 6\/6\/2015 for better clarity about the behavior of Object in different versions of Ruby. This post mostly applies to version 1.9.)<\/p>\n<p>Something that confused me about Ruby at first was why tutorials, articles, and books kept referring to Ruby &#8220;methods&#8221; when talking about functions. For example:<\/p>\n<pre>def hello\r\n puts \"hi there\"\r\nend\r\n<\/pre>\n<p>Since hello is not being defined as part of a class or module, it stands on its own. Any reasonable programmer would call this a function, not a method. Initially, I took this as some odd quirk of the Ruby community. They include some <a href=\"http:\/\/keeprubyweird.com\/\">pretty strange folks<\/a>, after all.<\/p>\n<p>Turns out there&#8217;s a good reason for this terminology. It IS a method.<\/p>\n<p>As Pat Shaughnessy explains in <a href=\"http:\/\/www.sitepoint.com\/rubys-top-self-object\/\">this article<\/a>, when you execute <code>def hello<\/code> at the top level, it gets added as an instance method to the <code>Object<\/code> class. You can verify this yourself:<\/p>\n<pre>def hello\r\n puts \"hi there\"\r\nend\r\n# this will print 'true'\r\nputs Object.respond_to? :hello\r\n<\/pre>\n<p>When you call <code>hello<\/code>, the method is invoked on a receiver (ie. <code>self<\/code>) that is an object instance called &#8220;main&#8221;, whose class is <code>Object<\/code>.<\/p>\n<pre>def hello\r\n  puts \"hi there\"\r\n  puts \"self is #{self}, its class is #{self.class}\"\r\nend\r\n# this prints 'self is main, its class is Object'\r\nhello\r\n<\/pre>\n<p>This explains why defining methods at the top level appears to make them globally accessible. What actually happens is that, when you call <code>hello<\/code> from any class or module, Ruby will look for it up the class hierarchy until it finds the method in <code>Object<\/code>.<\/p>\n<p>This also explains something else not immediately obvious to the newbie rubyist: things such as <code>puts<\/code> are not builtins or special cases, but just regular methods in the <code>Kernel<\/code> class, which is the parent of <code>Object<\/code>. Whether you call <code>puts<\/code> at the top level or from inside a class or module, Ruby will look up the class hierarchy and find it in <code>Kernel<\/code>.<\/p>\n<p><code>Kernel<\/code>&#8216;s members include things that might surprise you, like <code>require<\/code>!<\/p>\n<p>These simple mechanisms&mdash;the implicit &#8220;main&#8221;, the <code>Object<\/code> class, and the <code>Kernel<\/code> module&mdash;are stunningly elegant design ideas (and, apparently, according to Shaughnessy, ideas adapted from Smalltalk). It allows Ruby to provide the convenient calling syntax of functions, while remaining object-oriented down to its very core.<\/p>\n<p>(Compare this to Python, which does support &#8220;real&#8221; functions and differentiates them from methods. The distinction is less important in practice, as Python treats them both as &#8220;callables&#8221;&#8211;ie. arbitrary executable things.)<\/p>\n<p>One small note: Shaughnessy writes that &#8220;All Ruby functions are actually private methods of Object.&#8221; In his example, he prints <code>Object.private_instance_methods<\/code> and finds his newly defined function there. This is true in Ruby 2.1, but not in 1.9.3, where functions are public:<\/p>\n<pre>def hello\r\n puts \"hi there\"\r\nend\r\n# In Ruby 1.9.3, this will print 'false' and then 'true'\r\nputs Object.private_instance_methods.member? :hello\r\nputs Object.methods.member? :hello\r\n<\/pre>\n<p>I am just now beginning to realize how much Ruby is truly an object oriented language through and through. Parts of the language design might seem ad hoc and magical, which is indeed part of Ruby&#8217;s beauty and allure, but some very consistent and elegant mechanisms under the hood are what make them work.<\/p>\n<p>(I&#8217;ve eagerly ordered Shaughnessy&#8217;s book, <a href=\"http:\/\/patshaughnessy.net\/ruby-under-a-microscope\">Ruby Under a Microscope<\/a>, which looks terrific.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(NOTE: Edited slightly on 6\/6\/2015 for better clarity about the behavior of Object in different versions of Ruby. This post mostly applies to version 1.9.) Something that confused me about Ruby at first was why tutorials, articles, and books kept referring to Ruby &#8220;methods&#8221; when talking about functions. For example: def hello puts &#8220;hi there&#8221; &hellip; <a href=\"https:\/\/codefork.com\/blog\/index.php\/2015\/01\/11\/demystifying-ruby-functions\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Demystifying Ruby functions&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[],"class_list":["post-429","post","type-post","status-publish","format-standard","hentry","category-ruby"],"_links":{"self":[{"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/429","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=429"}],"version-history":[{"count":40,"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/429\/revisions"}],"predecessor-version":[{"id":534,"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/429\/revisions\/534"}],"wp:attachment":[{"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=429"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=429"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codefork.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=429"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}