<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-30540442</id><updated>2024-10-24T04:49:44.134-04:00</updated><category term="alegebra"/><category term="array"/><category term="configuration"/><category term="encapsulation"/><category term="namespaces"/><category term="negation"/><title type='text'>7ransCode</title><subtitle type='html'>l33t c0d3 $p1n!</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default?alt=atom'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-30540442.post-5369357770840243481</id><published>2007-05-02T09:37:00.000-04:00</published><updated>2007-05-03T13:48:36.510-04:00</updated><title type='text'>The Library Poll</title><content type='html'>I&#39;ve been thinking far too long about how best to organize and distribute programming libraries. Having a hard time coming to any firm conclusions, I&#39;ve decided to try an inductive approach -- via a poll. If you have a moment, I&#39;d really appreciate your thoughtful answers to the following questions. Thanks!&lt;br /&gt;&lt;br /&gt;(Note: Put your mouse over the question to see any truncated portion. It will scroll left.)&lt;br /&gt;&lt;br /&gt;&lt;iframe allowTransparency=&quot;true&quot; frameborder=&quot;0&quot; src=&quot;http://www.dPolls.com/DisplayPoll.aspx?PollID=23521&quot; width=&quot;350&quot; height=&quot;150&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;a href=&quot;http://www.dPolls.com&quot; target=&quot;_blank&quot; title=&quot;Create polls and vote for free. dPolls.com&quot;&gt;&lt;img src=&quot;http://www.dPolls.com/dPollsLink.aspx&quot; border=&quot;0&quot; alt=&quot;Create polls and vote for free. dPolls.com&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; src=&quot;http://www.dPolls.com/DisplayPoll.aspx?PollID=23524&quot; width=&quot;350&quot; height=&quot;150&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;a href=&quot;http://www.dPolls.com&quot; target=&quot;_blank&quot; title=&quot;Create polls and vote for free. dPolls.com&quot;&gt;&lt;img src=&quot;http://www.dPolls.com/dPollsLink.aspx&quot; border=&quot;0&quot; alt=&quot;Create polls and vote for free. dPolls.com&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On these last two, please consider the general spirit of the naming, not so the specific names used --which are completely fictitious.&lt;br /&gt;&lt;br /&gt;&lt;iframe allowTransparency=&quot;true&quot; frameborder=&quot;0&quot; src=&quot;http://www.dPolls.com/DisplayPoll.aspx?PollID=23522&quot; width=&quot;350&quot; height=&quot;150&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;a href=&quot;http://www.dPolls.com&quot; target=&quot;_blank&quot; title=&quot;Create polls and vote for free. dPolls.com&quot;&gt;&lt;img src=&quot;http://www.dPolls.com/dPollsLink.aspx&quot; border=&quot;0&quot; alt=&quot;Create polls and vote for free. dPolls.com&quot;&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;iframe allowTransparency=&quot;true&quot; frameborder=&quot;0&quot; src=&quot;http://www.dPolls.com/DisplayPoll.aspx?PollID=23613&quot; width=&quot;250&quot; height=&quot;150&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;&lt;br/&gt;&lt;a href=&quot;http://www.dPolls.com&quot; target=&quot;_blank&quot; title=&quot;Create polls and vote for free. dPolls.com&quot;&gt;&lt;img src=&quot;http://www.dPolls.com/dPollsLink.aspx&quot; border=&quot;0&quot; alt=&quot;Create polls and vote for free. dPolls.com&quot;&gt;&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/5369357770840243481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/5369357770840243481' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/5369357770840243481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/5369357770840243481'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2007/05/library-poll.html' title='The Library Poll'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-3149829289545186658</id><published>2006-12-03T20:17:00.000-05:00</published><updated>2006-12-04T09:19:55.521-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="alegebra"/><category scheme="http://www.blogger.com/atom/ns#" term="array"/><category scheme="http://www.blogger.com/atom/ns#" term="configuration"/><category scheme="http://www.blogger.com/atom/ns#" term="negation"/><title type='text'>Negative Arrays</title><content type='html'>My current work involves the creation of an extensive configuration file format representing project information. In a number of cases I have had need of an &lt;i&gt;inclusion list&lt;/i&gt;, representing files and file patterns to include for some operation --say, what files to include in a package. In such a case I generally end up with a least two parameters which I basically label &lt;code&gt;include&lt;/code&gt; and &lt;code&gt;exclude&lt;/code&gt;. While &lt;code&gt;include&lt;/code&gt; is the list of files to use, &lt;code&gt;exclude&lt;/code&gt; is list of files to exclude from the included list. Using &lt;code&gt;exclude&lt;/code&gt; makes it easier to specify a large selection and then subsequently omit a file or two. The &lt;code&gt;include&lt;/code&gt; list typically has a suitable default value, so a third parameter is sometimes also of use, &lt;code&gt;append&lt;/code&gt;, which concats to the defaults as opposed to replacing the &lt;code&gt;include&lt;code&gt; parameter outright.&lt;br /&gt;&lt;br /&gt;Since these three parameters help define what is essentially one list of data, it would be nice if they could be specified as a single parameter too. So I gave the problem some thought.&lt;br /&gt;&lt;br /&gt;Taking inspiration from the notion of a negated symbol (see facets/symbol/not). It occurred to me that any object that can be added or subtracted is taking part in the same &quot;algebraic group&quot; as whole numbers. And just as a whole number can be negative, why not also an array?&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    a =  [:a,:b,:c,:d,:e]&lt;br /&gt;    n = -[:d,:e]&lt;br /&gt;    a + n #=&gt; [:a,:b,:c]&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So this could be very helpful. And it shouldn&#39;t be too much hard to implement.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    class Array&lt;br /&gt;      def @-&lt;br /&gt;        @negative = !@negative&lt;br /&gt;        self&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      def negative?&lt;br /&gt;        @negative&lt;br /&gt;      end&lt;br /&gt;&lt;br /&gt;      alias :add :+&lt;br /&gt;      alias :sub :-&lt;br /&gt;&lt;br /&gt;      def +(other)&lt;br /&gt;        if negative?&lt;br /&gt;          if other.negative?&lt;br /&gt;            -add(other)&lt;br /&gt;          else&lt;br /&gt;            -sub(other)&lt;br /&gt;          end&lt;br /&gt;        else&lt;br /&gt;          if other.negative?&lt;br /&gt;            sub(other)&lt;br /&gt;          else&lt;br /&gt;            add(other)&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;  &lt;br /&gt;      ...&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I&#39;m sure tighter implementation is possible, but you get the idea. So then include and exclude parameters could be specified in a single parameter.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  files = [ &#39;**/*&#39;, -[ &#39;Installedfiles&#39; ] ]&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Neat! But unfortunately it doesn&#39;t really solve the whole problem since YAML doesn&#39;t understand this negative listing concept either. It could still be of use in general Ruby scripts though. Notations such as this often prove very powerful. And in fact the idea does move us in a possible workable direction. There&#39;s no reason a string can&#39;t be marked as negative as well. After all it&#39;s just a flag. In fact, if we move the core method @- to Object itself, then any object can be so indicated. The above line could then be written:&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  files = [ &#39;**/*&#39;, -&#39;Installedfiles&#39; ]&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Methods such as &lt;code&gt;Dir.multiglob(*files)&lt;/code&gt; (another Facet) could use this extra bit of information to provide the desired results, equivalent to:&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  files = Dir.glob(&#39;**/*&#39;) - Dir.glob(&#39;InstalledFiles&#39;)&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, this still doesn&#39;t quite help us with the YAML configuration file, but with a little fudging we can get a useful format.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  files: [ &#39;**/*&#39;, &#39;-InstalledFiles&#39; ]&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As for the &lt;code&gt;append&lt;/code&gt; parameter that was mentioned as the beginning, we could just add a special notation for this as well, say, &#39;$&#39; to mean defaults.&lt;br /&gt;&lt;br /&gt;Okay. So will I use this bit of trickery to reduce three parameters to one? Perhaps. While the result is wonderfully practical in usage, it&#39;s not necessarily so simple to implement. Either a filter would have to split the one entry into three parts when loading, or an untold number of methods would have to augmented to take the trick into consideration. The later I imagine would simply prove too extensive w/o pre-established support for the negation concept. The former might be reasonable however. I&#39;ll give it a try.&lt;br /&gt;&lt;br /&gt;In any case it was in interesting thought experiment. Although perhaps you have a better way to represent this kind of information?</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/3149829289545186658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/3149829289545186658' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/3149829289545186658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/3149829289545186658'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/12/negative-arrays.html' title='Negative Arrays'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-6778970090939722345</id><published>2006-11-11T19:15:00.000-05:00</published><updated>2006-12-03T20:16:52.308-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="encapsulation"/><category scheme="http://www.blogger.com/atom/ns#" term="namespaces"/><title type='text'>We all live in a Yellow Submarine</title><content type='html'>Anyone having read my previous posts, here and on ruby-talk, knows I love to explore ideas. It doesn&#39;t matter if they are considered &quot;good&quot; or &quot;bad&quot;. Most cannot be judged without first exponding on them anyway. In fact, half the time I have no idea where an idea might lead until I sit down and blog it.&lt;br /&gt;&lt;br /&gt;Tonight&#39;s idea comes by way of frustration with project organization, specifically module namespaces. A minor issue for small projects; large projects on the other hand... Well, consider my current problem. I have a class called Project. Now related to Project are a number of modularized tool sets. Each tool set can be used independently of the Project class, but typically will be used via it. So where do I locate the tool sets? My first instinct is to go ahead and put them in the class itself.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; module MyApp&lt;br /&gt;   class Project&lt;br /&gt;     module ToolSetA&lt;br /&gt;     module ToolSetB&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But I find this less the optimal. While it may be a small and unlikely matter, class is not a bonofide namespace --it is a class. And while it depends on these tool sets, the tool sets do not necessarily depend on it. As such we would never be able to include these tool sets in another namespace --such as the toplevel if it struck my or some users fancy. So we are left then to use some alternate organization.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   class Project&lt;br /&gt;   module ProjectToolsets&lt;br /&gt;     module ToolSetA&lt;br /&gt;     module ToolSetB&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or as a compromise&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   class Project&lt;br /&gt;     module Toolsets&lt;br /&gt;       module ToolSetA&lt;br /&gt;       module ToolSetB&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The downside here, of course, are the long-winded names. But a better solution eludes me, other than one possibility: the use of all capitals for pure namespace modules.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;   class Project&lt;br /&gt;   module PROJECT&lt;br /&gt;     module ToolSetA&lt;br /&gt;     module ToolSetB&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It&#39;s a bit strange in appearance but it works well. One quark however is that this new rule begs for my project&#39;s toplevel namepsace to be all caps too. Do I want to go there?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  module MYAPP&lt;br /&gt;   class Project&lt;br /&gt;   module PROJECT&lt;br /&gt;     module ToolSetA&lt;br /&gt;     module ToolSetB&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I&#39;m not sure it&#39;s the solution I&#39;m after, but to its merit, it does draw a nice distinction between namespace modules and other modules and classes.&lt;br /&gt;&lt;br /&gt;In the course of this consideration I began to wonder about the distinction between Class and Module. The difference is almost not-existent in reality. If you peer into the Ruby source code you will find that interoperability between them is purposefully prevented. After all Class is a subclass of Module. Yet they are made distinct for a good reason. They provide conceptually different ideas. A class represents an data archetype; a module represents a reusable component. In fact, one could easily argue that Module itself could use an additional distiction between Namespace and Mixin. Even so, I could not help but wonder if it might yet be possible to have a single Encapsulation, relegating the differences to the elements within them instead of the encapsulation types themselves. I imagined this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; class Something&lt;br /&gt;   def x&lt;br /&gt;   def y&lt;br /&gt;   mod_def a&lt;br /&gt;   mod_def x&lt;br /&gt;   class SomethingElse&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Instantiating via &lt;code&gt;Something.new&lt;/code&gt; or subclassing would provide the instance methods &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. Including however would provide the mod_def methods  &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; instead along with adding SomethingElse to the including namespace. More refined means of controlling namespace become possible. For instance &lt;code&gt;include_constants&lt;/code&gt; could limit inclusion to constants only; vice-verse with &lt;code&gt;include_methods&lt;/code&gt;. Methods could be defined as both instance and module methods. And while we&#39;re at it, throw in a &lt;code&gt;class_def&lt;/code&gt; as an alternative to &lt;code&gt;def self.x&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;It&#39;s interesting. I&#39;ve often thought about the idea of eliminating the distinction between Class and Module. This is the first time it&#39;s occurred to me that it could be done while retaining the utility of that distinction by passing responsibility down to the methods themselves.&lt;br /&gt;&lt;br /&gt;I suppose now the question is, what are the downsides to this? That&#39;ll require further consideration, but one clear point is that methods are less cleanly divided. You could have module methods scattered about your class definitions, weaving in and out of your instance methods. I suspect we would make an effort to nicely organize them however. Besides it means having fewer modules to name --and I&#39;m all for anything that reduces the number of names I have to make-up.&lt;br /&gt;&lt;br /&gt;It would be interesting to see how far one could go in implementing this in pure Ruby. Some details of Ruby will hold back a perfect implementation, but the essence of it is certainly possible. For starters, here&#39;s a neat trick for doing without the distinction between class and module.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; class Module&lt;br /&gt;   def new&lt;br /&gt;     mod = self&lt;br /&gt;     Class.new{ include mod }.new&lt;br /&gt;   end&lt;br /&gt; end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Have fun! Unfortunately I&#39;m not. I&#39;m still stuck on the forementioned namespace issue! Oh well. Back to the coding board...</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/6778970090939722345/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/6778970090939722345' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/6778970090939722345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/6778970090939722345'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/11/we-all-live-in-yellow-submarine.html' title='We all live in a Yellow Submarine'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-116317992348517910</id><published>2006-11-10T10:42:00.000-05:00</published><updated>2006-11-11T17:20:00.618-05:00</updated><title type='text'>Separation of Church and State</title><content type='html'>Have you ever had a class so choke full of interrelated data and function members that had trouble avoiding name clashes between the two. Of course it&#39;s a rare problem when you&#39;re in full control of the members, but when you&#39;re designing extensible classes, it become a major issue and you have to resort to some less-than-lovely work around.&lt;br /&gt;&lt;br /&gt;Let me give you a simple scenario.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  class Package&lt;br /&gt;    # Release date&lt;br /&gt;    #&lt;br /&gt;    attr :release&lt;br /&gt;&lt;br /&gt;    # Release the package.&lt;br /&gt;    #&lt;br /&gt;    def release&lt;br /&gt;       puts &quot;Telling the world on #{@release}...&quot;&lt;br /&gt;       # ...&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The issue here is clear. On one hand, we want to use &lt;code&gt;release&lt;/code&gt; as a noun to represent the date of release. On the other, we want to use it as a verb for &lt;i&gt;releasing&lt;/i&gt; the package to the world. Of course, under completely isolated circumstances we could just change one of the names and deal. But when we are working on the basis of extensibility, where these and additional data or functional members may be added readily, say via a plug-in system, then a solution is not as simple.&lt;br /&gt;&lt;br /&gt;So what can we do? The bottom line is that in some way or another the two member types must be distinguished from one another.&lt;br /&gt;&lt;br /&gt;One could transform one set of the members with a slightly different name via some uniform convention. For instance, all data memebers could start with &quot;my_&quot;, so release as a date would be &lt;code&gt;my_release&lt;/code&gt;. Ruby actually makes this it a bit nicer in that we can use &#39;?&#39; or &#39;!&#39; prepended to method names. A fair solution might then be:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def release?&lt;br /&gt;      @release&lt;br /&gt;    end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    def release!&lt;br /&gt;      puts &quot;Telling the world on #{release?}...&quot;&lt;br /&gt;      #...&lt;br /&gt;    end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It&#39;s not a perfect solution however, especially as a matter of convention. It goes against the grian. &#39;?&#39; typically indicates a true/false query. And &#39;!&#39; indicates in place or caution. Consider how others will &quot;smell&quot; your code when they see a question mark for every reference to a data member.&lt;br /&gt;&lt;br /&gt;The other more traditional solution is to use &lt;bold&gt;delegation&lt;/bold&gt;. In this case we make a subclass for either or both of the member types. For instance:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  class Package&lt;br /&gt;&lt;br /&gt;    class Data&lt;br /&gt;      attr :release&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    attr :data&lt;br /&gt;&lt;br /&gt;    def initialize&lt;br /&gt;      @data = Data.new&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def release&lt;br /&gt;      puts &quot;Telling to the world on #{data.release}...&quot;&lt;br /&gt;      #...&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Albeit a bit longer. It works very well. Delegation is a powerful tool. One could even emulate the former solution via &lt;code&gt;method_missing&lt;/code&gt;, trapping method calls that end in &#39;?&#39; and rerouting them to &lt;code&gt;@data&lt;/code&gt;. Another advantage is that we can readily pass around the data independent of the function members. On the flip side however, we are regulated to this special &lt;code&gt;data.&lt;i&gt;member&lt;/i&gt;&lt;/code&gt; interface. and likewise any reverse access by the data members to the functional members, if ever needed, would require us to also pass a reference to the Package instance into the Data instance.&lt;br /&gt;&lt;br /&gt;In considering all this of course, it becomes apparent that Ruby already has a means of distinguishing data members from functional members via instance variables. Clearly &lt;code&gt;@release&lt;/code&gt; references the date. But Ruby does not give us the power to treat  &quot;instance members&quot; publicly or programaticlly. We can&#39;t, for instance, use &lt;code&gt;project.@release&lt;/code&gt; to access the release date. Nor can we wrap data members in order to massage their data, say:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def @release&lt;br /&gt;    super || Time.now&lt;br /&gt;  end&lt;br /&gt;  public :@release&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I&#39;m sure many readers will take such notion for simply god aweful. But I think careful consideration at least warrants the fair question. &quot;Is a distinct separation between data and functional members useful?&quot; The mere existence of instance variables indicates that the distinction is in fact useful. In contrast, data members could have been made indistinguishable from functional members, or local variable persistence could be used in their stay. So if the distinction is useful, why hide public access to data members behind functional members acting as mini-delegates?&lt;br /&gt;&lt;br /&gt;To be a bit more pragmatic, how would a solution to our example pane out if data members were in fact accessible? Interestingly it could look &lt;i&gt;exactly&lt;/i&gt; like the original example. Public access to the release date however would simply come via &lt;code&gt;project.@release&lt;/code&gt; or preferably even &lt;code&gt;project@release&lt;/code&gt;. And there would be no need for any name (mis)conventions or special-interface delegation.&lt;br /&gt;&lt;br /&gt;Of course let&#39;s be honest here. &#39;&lt;code&gt;@&lt;/code&gt;&#39; itself is the Special Delegate of State to the Ruby &quot;Church&quot;. Too bad he&#39;s only allowed to preach to the chior.</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/116317992348517910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/116317992348517910' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/116317992348517910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/116317992348517910'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/11/separation-of-church-and-state.html' title='Separation of Church and State'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115980327969618794</id><published>2006-10-02T10:36:00.000-04:00</published><updated>2006-11-11T17:20:00.242-05:00</updated><title type='text'>I See You</title><content type='html'>&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;http://i96.photobucket.com/albums/l191/transfire/iseeyou.jpg&quot;&gt;&lt;img style=&quot;float:right; margin:0 0 0 10px;cursor:pointer; cursor:hand;width: 320px;&quot; src=&quot;http://i96.photobucket.com/albums/l191/transfire/iseeyou.jpg&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;br /&gt;You have to &lt;a href=&quot;http://tenderlovemaking.com/2006/09/28/new-ruby-betabrite-002/&quot;&gt;check this out&lt;/a&gt;. Okay. I know. I know. It&#39;s been blogged by others many times now. In fact, you can check out these other blog posts too: Why_the_lucky_stiff has it on &lt;a href=&quot;http://redhanded.hobix.com/inspect/hackASignOnSomeoneElseSWoodFloors.html#comments&quot;&gt;Redhanded&lt;/a&gt;, and &lt;a href=&quot;http://www.eachmapinject.com/2006/9/29/betabrite&quot;&gt;J&#39;ey&lt;/a&gt; put out the word as well. But it&#39;s just so damn cool, I just had to blog it too!&lt;br /&gt;&lt;br /&gt;Go ahead. Try it at home:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  require &#39;drb&#39;&lt;br /&gt;&lt;br /&gt;  def brite_shot(text)&lt;br /&gt;    url = &quot;druby://eviladmins.org:9000&quot;&lt;br /&gt;    obj = DRbObject.new_with_uri(url)&lt;br /&gt;    File.open(&quot;out.jpg&quot;,&#39;wb&#39;) do |a|&lt;br /&gt;      a &amp;lt;&amp;lt; obj.write_simple(text)&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  brite_shot(&quot;I SEE YOU!&quot;)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(And if a still picture isn&#39;t enough for you. How about an &lt;a href=&quot;http://pastie.caboo.se/15646&quot;&gt;animation&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;And so, a REAL picture is made for me by remote many thousands of miles away. How far I wonder? Well, with a GeoIP lookup and Google Maps, I found out &lt;a href=&quot;http://maps.google.com/maps?f=q&amp;hl=en&amp;q=47.610%C2%B0N,+122.304%C2%B0W&amp;ie=UTF8&amp;z=17&amp;ll=47.61,-122.304&amp;spn=0.004231,0.012757&amp;t=h&amp;om=1&quot;&gt; where this picture was made&lt;/a&gt;. The world really is getting smaller!&lt;br /&gt;&lt;br /&gt;I See You!</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115980327969618794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115980327969618794' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115980327969618794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115980327969618794'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/10/i-see-you.html' title='I See You'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115888980435072505</id><published>2006-09-21T21:36:00.000-04:00</published><updated>2006-11-11T17:20:00.110-05:00</updated><title type='text'>I No Longer Believe In Methods</title><content type='html'>Yes, that&#39;s right. I no longer believe in methods. Why? Becuase this is OOP and if the methods aren&#39;t honest to goodness objects from the start, without exception, then they are not really methods. They&#39;re just glorified functions.&lt;br /&gt;&lt;br /&gt;Let me show you what I mean. I have a Project class in which is defined a set of tools that can manipulate it. Clearly the proper implementation abstraction for these tools is the method.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  Class Project&lt;br /&gt;    def announce&lt;br /&gt;      puts &quot;This is my new project!&quot;&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But these tools must be distinguishable from other supporting methods. Moreover additional information may be associated with these tools, like help information or valid states of the Project for the tool to be useful. How do we encode this information with Ruby? Since methods aren&#39;t first class objects, we are forced to return to functional programming. In which case, it is best to define some sort of DSL.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  module ProjectDSL&lt;br /&gt;    def help( name, text )&lt;br /&gt;      @help ||= {}&lt;br /&gt;      @help[name] = text&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def valid( name, &amp;test )&lt;br /&gt;      @valid ||= {}&lt;br /&gt;      @valid[name] = test&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  Class Project&lt;br /&gt;    extend ProjectDSL&lt;br /&gt;&lt;br /&gt;    def announce&lt;br /&gt;      puts &quot;This is my new project!&quot;&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    help :announce, &quot;Announces your project to the world!&quot;&lt;br /&gt;    valid :announce { @version &gt; &quot;0.0.0&quot; }&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now this kind of thing has come up enough in large projects, such as &lt;a href=&quot;http://nitroproject.org&quot;&gt;Nitro&lt;/a&gt;, that a general means of &lt;i&gt;annotation&lt;/i&gt; proved to be most effective.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  require &#39;facet/annotation&#39;&lt;br /&gt;&lt;br /&gt;  Class Project&lt;br /&gt;    def announce&lt;br /&gt;      puts &quot;This is my new project!&quot;&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    ann :announce, :help =&gt; &quot;Announces your project to the world!&quot;,&lt;br /&gt;                   :valid =&gt; lambda { @version &gt; &quot;0.0.0&quot; }&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Annotations works very well, and if you find yourself in need of this kind of &quot;method metadata&quot; it is an excellent approach.&lt;br /&gt;&lt;br /&gt;But I&#39;ve worked with all this long enough now to be able to have a wide perspective on it and it&#39;s become very clear to me that the whole &quot;special needs&quot; arises out of the fact that Ruby is still just a functional lanaguage in this respect, and not a full OOPL. (And please no objections that &lt;code&gt;method()&lt;/code&gt; and &lt;code&gt;instance_method()&lt;/code&gt; make it otherwise, these do not provide a persitant object, but return a new object every time they are invoked.) So what might the above look like if it were not so? There would of course be more than one way to go about it, but imagine this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  class Tool &lt; Method&lt;br /&gt;    attr_accessor :help&lt;br /&gt;&lt;br /&gt;    def valid( &amp;test )&lt;br /&gt;      @valid = test&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  Class Project&lt;br /&gt;    def announce =&gt; Tool&lt;br /&gt;      puts &quot;This is my new project!&quot;&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    announce.help = &quot;Announces your project to the world!&quot;&lt;br /&gt;&lt;br /&gt;    announce.valid { @version &gt; &quot;0.0.0&quot; }&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I&#39;m taking some liberties with the syntax here for clarity. But in anycase it certainly paints a provocative idea. And I would argue that it paints the approprite OOP idea too.</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115888980435072505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115888980435072505' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115888980435072505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115888980435072505'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/09/i-no-longer-believe-in-methods.html' title='I No Longer Believe In Methods'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115662839670360626</id><published>2006-08-26T17:14:00.000-04:00</published><updated>2006-11-11T17:19:59.949-05:00</updated><title type='text'>The Persnickety Order of Self Serving Modules</title><content type='html'>This one caught me off guard.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  irb(main):001:0&gt; module M&lt;br /&gt;  orb(main):002:1&gt;   def x; &quot;x&quot;; end&lt;br /&gt;  orb(main):003:1&gt; end&lt;br /&gt;  =&gt; nil&lt;br /&gt;  orb(main):005:0&gt; module Q&lt;br /&gt;  orb(main):006:1&gt;   extend self&lt;br /&gt;  orb(main):007:1&gt;   include M&lt;br /&gt;  orb(main):008:1&gt; end&lt;br /&gt;  =&gt; Q&lt;br /&gt;  orb(main):009:0&gt; Q.x&lt;br /&gt;  NoMethodError: undefined method `x&#39; for Q:Module&lt;br /&gt;          from (orb):9&lt;br /&gt;          from :0&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Why isn&#39;t the included #x coming along for the ride in the self extension of Q? This kind of dyanmicism is vital when dynamically loading behaviors. And so I suspect it must do with the dread &lt;a href=&quot;http://groups.google.com/group/comp.lang.ruby/msg/70509b289f0ea999&quot;&gt;Dynamic Module Inclusion Problem&lt;/a&gt;? And it would appear that I am right:&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;  orb(main):012:0&gt; module M&lt;br /&gt;  orb(main):013:1&gt;   def x; &quot;x&quot;; end&lt;br /&gt;  orb(main):014:1&gt; end&lt;br /&gt;  =&gt; nil&lt;br /&gt;  orb(main):015:0&gt; module Q&lt;br /&gt;  orb(main):016:1&gt;   include M&lt;br /&gt;  orb(main):017:1&gt;   extend self&lt;br /&gt;  orb(main):018:1&gt; end&lt;br /&gt;  =&gt; Q&lt;br /&gt;  orb(main):019:0&gt; Q.x&lt;br /&gt;  =&gt; &quot;x&quot;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Yes, another of the edge cases. But the preponderance weighs heavy on the Coding Spirit. The &lt;i&gt;Dynamic Module Inclusion Problem&lt;/i&gt; is getting old.</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115662839670360626/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115662839670360626' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115662839670360626'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115662839670360626'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/08/persnickety-order-of-self-serving.html' title='The Persnickety Order of Self Serving Modules'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115621668256730376</id><published>2006-08-21T22:47:00.000-04:00</published><updated>2006-11-11T17:19:59.797-05:00</updated><title type='text'>Main Campaign &quot;Out of Object Now!&quot;</title><content type='html'>The word from Matz on Kernel as toplevel object:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;quote&quot;&gt;&lt;br /&gt;  I don&#39;t feel that making Kernel as toplevel self is not a good idea,&lt;br /&gt;  because:&lt;br /&gt;&lt;br /&gt;    * toplevel def does not define methods on Kernel, but Object.&lt;br /&gt;    * toplevel include does not include modules into Kernel, but Object.&lt;br /&gt;    * toplevel private etc. do not work on Kernel, but Object.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I wouldn&#39;t call that an explanation exactly, more an explicative of the current behavior. I&#39;m sure Matz has his reasons, and we can just assume that he wants to keep the namespace distinct. Fair enough, and of course he can do that. (It&#39;s not REALLY a democracy after all!) So Kernel drops out of the race. But the Kernel&#39;s running mate, Main, is still here campaigning.&lt;br /&gt;&lt;br /&gt;You might be surprised to learn (as I was when I first discovered it):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  Object.public_instance_methods(false) +&lt;br /&gt;  Object.private_instance_methods(false) +&lt;br /&gt;  Object.protected_instance_methods(false)&lt;br /&gt;  =&gt; []&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That&#39;s right. There&#39;s not a single method defined in Object. All the methods &lt;code&gt;ri&lt;/code&gt; tells you belong to Object actually are inherited from Kernel. But from there, any toplevel method we define does end-up in Object. Hence the clear separation of namespace I mentioned above.&lt;br /&gt;&lt;br /&gt;Now a separate module, eg. Main, would do just as well. Kernel need not be used. And as I&#39;ve expressed before, Main could be induced into Object for all the same effects. The base hierarchy then being &lt;code&gt;Object &amp;lt; Main &amp;lt; Kernel&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;But wait a second! Why are all these toplevel methods sneaking into all my Object&#39;s anyway? I can just as easily add them to Object myself if that&#39;s what I want. I don&#39;t need some cheap toplevel proxy to do it for me. In fact, that can be a problem too.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  module Foo&lt;br /&gt;    def self.method_missing( name, *args )&lt;br /&gt;      super unless require &quot;foo/#{name}&quot; rescue nil&lt;br /&gt;      send( name,*args )&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then some unsuspecting nuby comes along (okay I admit, it was I and it happened to me today!) and innocently adds to the top level:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def check( name )&lt;br /&gt;    name == &quot;foo&quot;&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well, so much for my lazily required Foo.check routine. It&#39;s been whacked from the &lt;u&gt;top&lt;/u&gt; down!&lt;br /&gt;&lt;br /&gt;You see where I&#39;m going now? Primaries are over Main has taken Kernel out of the running with a new divisive platform. &quot;Out of Object Now!&quot;</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115621668256730376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115621668256730376' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115621668256730376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115621668256730376'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/08/main-campaign-out-of-object-now.html' title='Main Campaign &quot;Out of Object Now!&quot;'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115595077248317299</id><published>2006-08-18T19:52:00.000-04:00</published><updated>2006-11-11T17:19:59.597-05:00</updated><title type='text'>Vote Kernel for Toplevel Object</title><content type='html'>&lt;img src=&quot;http://www.mattdrake2006.com/images/vote.gif&quot; align=&quot;left&quot;/&gt;&lt;br /&gt;As a follow up to my last post on the &quot;pain that is main&quot;, I want to offer a potential improvement for Ruby 2.0. I approached the topic on &lt;a href=&quot;http://groups.google.com/group/comp.lang.ruby/browse_thread/thread/907714abe21f98bd/?hl=en#&quot;&gt;ruby-talk&lt;/a&gt; this week and while Matz initially took some interest, he hasn&#39;t followed up since his last comment:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;quote&quot;&gt;&lt;br /&gt;  &lt;b&gt;matz&lt;/b&gt;: Why?  If it is really required it&#39;s fairly&lt;br /&gt;  easy to add toplevel methods like we did for #include.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But it isn&#39;t always easy. In order get my Taskable module to work, for instance, I had to make exceptions for the toplevel case, which is far from ideal and is fragile [Ed- in fact I&#39;m still getting bugs that I haven&#39;t yet pinned down]. These subtile difficulties arise becuase &lt;code&gt;main&lt;/code&gt; acts as a partial proxy for the Object class. Anyone who has created a proxy object before knows the subtile issues that can come into play. In this case, only the bare minimal interface is supported --essentially the method #include. Yet, even if we take matz&#39; advice and add in all the missing proxy methods, we still won&#39;t be 100% out of the woods. The Object class and main are fundamentally two distinct objects --&lt;code&gt;self&lt;/code&gt; is not the same, nor are their singleton classes, &amp;c. In the vast majority of cases this will never present an issue, but the distinction can creep in. Here&#39;s an highlight of one way it can:&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    module Q&lt;br /&gt;      define_method :q do&lt;br /&gt;        base = self&lt;br /&gt;        define_method :r do&lt;br /&gt;          base == self.class&lt;br /&gt;        end&lt;br /&gt;      end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    class C&lt;br /&gt;      extend Q&lt;br /&gt;      q&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    c = C.new&lt;br /&gt;    p c.r&lt;br /&gt;&lt;br /&gt;    # per matz&#39; direction&lt;br /&gt;&lt;br /&gt;    def define_method( name, &amp;act )&lt;br /&gt;      Object.class_eval {&lt;br /&gt;        define_method( name, &amp;act )&lt;br /&gt;        private name&lt;br /&gt;      }&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    extend Q&lt;br /&gt;    q&lt;br /&gt;    p r&lt;br /&gt;&lt;br /&gt; &lt;i&gt;produces&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    true&lt;br /&gt;    false&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So in effect Ruby is mildly schizophrenic. The &lt;code&gt;false&lt;/code&gt; reading is because &lt;code&gt;main != Object&lt;/code&gt;. So, you can&#39;t neccessarily create a DSL for &lt;code&gt;Object&lt;/code&gt; to be used in &lt;code&gt;main&lt;/code&gt;, and you can&#39;t neccessairly create a DSL for &lt;code&gt;main&lt;/code&gt; to be used in any Object. Hence the devolution to DRYless code.&lt;br /&gt;&lt;br /&gt;There is a potentially elegant solution however, and I&#39;d really like to understand others insights into this (esspecially Matz&#39; of course): Instead of &lt;code&gt;main&lt;/code&gt; being a special proxy object, just let it be a self extended module.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    module Main&lt;br /&gt;      extend self&lt;br /&gt;      # programs are written as if in here&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This would provide all the facilities required of the toplevel without all the proxy troubles. Also, while I&#39;m not so convinced of the merits of every toplevel method becoming a private method of all objects (and with Main that can be easily prevented), it has proven workable in practice so it&#39;s not a significant factor of consideration here. Main can simply be include in Object to achieve that effect.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    class Object&lt;br /&gt;      include Main&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;But when we do that it becomes very clear what Main appears to be: Kernel. That strikes me as esspecially interesting. Then again, there may be good reasons to keep the Kernel as a separate module, in which case we&#39;d just have a class hierachy:&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    Object.ancestors&lt;br /&gt;    =&gt; [Object, Main, Kernel]&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Nevertheless, it is clear the Kernel could just as well serve as the toplevel object, which, IMHO, makes this an elegant proposition to consider. Perhaps I&#39;ll start a campaign as November elections roll around: &quot;Vote Kernel for Toplevel Object!&quot; ;-)</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115595077248317299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115595077248317299' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115595077248317299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115595077248317299'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/08/vote-kernel-for-toplevel-object.html' title='Vote Kernel for Toplevel Object'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115583071994872736</id><published>2006-08-17T11:44:00.000-04:00</published><updated>2006-11-11T17:19:59.451-05:00</updated><title type='text'>Main is a DRY Pain</title><content type='html'>I have a module that depends on &lt;code&gt;define_method&lt;/code&gt; and &lt;code&gt;ancestors&lt;/code&gt;. It works great when I include it in other modules or classes. But if I try including it into the toplevel it fails miserably.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    NameError: undefined local variable or method `define_method&#39; for main:Object&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That seems fairly peculiar when you consider that defining methods at toplevel is perfectly acceptable. One must then wonder, what is this toplevel thing anyway?&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    self  #=&gt; main&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Okay, it calls itself &quot;main&quot;. Great. But that doesn&#39;t really tell us anything. Let&#39;s check it&#39;s class:&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    self.class  #=&gt; Object&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ah. So it&#39;s an instance of Object. An instance of Object!? How is that possible? A normal instance of Object and main can&#39;t be exactly the same. Indeed, they are not.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    (public_methods - Object.public_instance_methods).sort&lt;br /&gt;    =&gt; [&quot;include&quot;, &quot;private&quot;, &quot;public&quot;]&lt;br /&gt;    singleton_methods&lt;br /&gt;    =&gt; [&quot;include&quot;, &quot;private&quot;, &quot;public&quot;, &quot;to_s&quot;]&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Notice &lt;code&gt;include&lt;/code&gt; has been defined here specifically for main. So something special&#39;s going on when you include a module into the toplevel. Hmm... What about methods defined at the toplevel? If main is an instance of Object then are they singleton methods? Well, no. Turns out they get &quot;magically&quot; defined as private methods of the Object class itself, and main&#39;s singleton class space is actually something else entirely.&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    class &lt;&lt; self&lt;br /&gt;      def x; &quot;x&quot;; end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    class Q&lt;br /&gt;      def q; x; end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    Q.new.q&lt;br /&gt;    =&gt; NameError: undefined local variable or method `s&#39; for #&amp;lt;Q:0xb7ce9a3c&amp;gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Which means the sure solution for my problem...&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    module Kernel&lt;br /&gt;      include MyModule&lt;br /&gt;    end&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Can you guess?&lt;br /&gt;&lt;br /&gt;  &lt;pre&gt;&lt;br /&gt;    module M&lt;br /&gt;      def m; &quot;m&quot;; end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    module Kernel&lt;br /&gt;      include M&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    m&lt;br /&gt;    =&gt; NameError: undefined local variable or method `m&#39; for main:Object&lt;br /&gt;&lt;br /&gt;    class Q&lt;br /&gt;      def q; m; end&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    Q.new.q&lt;br /&gt;    =&gt; NameError: undefined local variable or method `m&#39; for #&amp;lt;Q:0xb7cbb324&amp;gt;&lt;br /&gt;  &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Lands me squre in the face of the Module Inclusion Problem.&lt;br /&gt;&lt;br /&gt;All this leads me to two points. First, I&#39;m stuck! There seems to be no solution to my problem other than rewritting a second version of my module specifically for the toplevel. Talk about lack of DRY! And 2) Why in the world isn&#39;t &lt;code&gt;main&lt;/code&gt; a self extended module?</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115583071994872736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115583071994872736' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115583071994872736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115583071994872736'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/08/main-is-dry-pain.html' title='Main is a DRY Pain'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115369127382172350</id><published>2006-07-23T17:34:00.000-04:00</published><updated>2006-11-11T17:19:59.059-05:00</updated><title type='text'>Taming the File System Zoo</title><content type='html'>I&#39;m not quite sure I undestand why we have all these classes and modules: Dir, File, FileUtils, FileTest and Pathname. I understand what each of these does, of course, but I don&#39;t understand why the clearly related functionality has been spread about.&lt;br /&gt;&lt;br /&gt;I think a FileSystem class or module would be in order -- a system we could use in much the same manner as we use the command shell to access our filesystem.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  fs = FileSystem.new&lt;br /&gt;  fs.cd(&#39;/&#39;)&lt;br /&gt;  entries = fs.ls&lt;br /&gt;  entries.each do |e|&lt;br /&gt;    if fs.directory?(e)&lt;br /&gt;      ...&lt;br /&gt;    else&lt;br /&gt;      fs.open(e) { |f| ... }&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;  &lt;br /&gt;It&#39;s not so common that we open files and harbor them, even less so for directories. So the FileSystem can have those defined within it as well, and there&#39;s no reason to even draw them up yourself. FileSystem can do it for you:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  fs[&#39;afile.txt&#39;]  #=&gt; &lt;#FileSystem::File...&gt;&lt;br /&gt;  fs[&#39;adir/&#39;]      #=&gt; &lt;#FileSystem::Dir...&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Clear, straightforward and convenient. But best of all, this single point of entry into all things &quot;file system&quot; may lead to more interesting possibilities, in some respect similar to what FUSE offers us in general, only confined to Ruby&#39;s realm.&lt;br /&gt;&lt;br /&gt;I also wonder how remote file systems might fit into this... interesting considerations all.</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115369127382172350/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115369127382172350' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115369127382172350'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115369127382172350'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/07/taming-file-system-zoo.html' title='Taming the File System Zoo'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30540442.post-115358722006608324</id><published>2006-07-22T11:47:00.000-04:00</published><updated>2006-11-11T17:19:58.888-05:00</updated><title type='text'>Singleton 2 Legion</title><content type='html'>For as long as I&#39;ve coded Ruby there has been some question as to the appropriateness of the term &lt;i&gt;singleton class&lt;/i&gt;. This is the term generally used in Ruby parlance to refer to the language construct: &lt;code&gt;class &amp;lt;&amp;lt; obj; self; end&lt;/code&gt;, and is the context of &lt;i&gt;class methods&lt;/i&gt; and &lt;i&gt;module methods&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;While the term is fitting in the sense that each object only has &lt;i&gt;one&lt;/i&gt; of these classes (hence &quot;single&quot;), issue arises from a terminology clash with an already well accepted object-oriented programming term: http://en.wikipedia.org/wiki/Singleton_pattern. In OOP-speak a singleton class is a class that can only be instantiated once. Many have argued that the Singleton pattern itself is a flawed concept, since one can just instantiate an object and assign it to a constant to achieve the same end. So why restrict anyone from a second instance of a class if they so choose? That&#39;s a reasonable argument, although not always as practical as it might seem. Nonetheless, the terminology clash still remains.&lt;br /&gt;&lt;br /&gt;In light of nomenclature issue, many have offered alternative terms for Ruby&#39;s singleton class. Indeed, Ruby itself has used two alternatives in the past: &lt;i&gt;virtual class&lt;/i&gt; and &lt;i&gt;metaclass&lt;/i&gt;, and many people still prefer that later of these choices. Other suggestions include the well known _whyism &#39;eigenclass&#39;, the abbreviated &#39;sclass&#39;, the pronoun contingents &#39;myclass&#39; and &#39;ownclass&#39;, as well as my own concoctions &#39;adhoc&#39;, &#39;quaclass&#39; and &#39;nonce&#39;. Yet despite all these names, none of which ever stick, what is this singly thing really?&lt;br /&gt;&lt;br /&gt;Recently, our beloved Pit Capitan put it concisely when he said &quot;there are only two types of methods in Ruby, instance methods and singleton methods&quot;. Well said. Unfortunately it&#39;s not really true. Instance methods aren&#39;t really methods at all, they are just &lt;i&gt;definitions for methods to be&lt;/i&gt;. That&#39;s why when you use #instance_method you get something called an UnboundMethod, not a Method. It only becomes a method when it&#39;s bound to an object. To clarify further how that distinction is a bit misleading, consider that when a singleton method is defined it falls into an inheritance hierarchy along side so-called instance methods. In other words, the singleton methods and instance methods exist on the same playing field, and the former can call on the other via #super. In fact, we can access these singleton methods in instance fashion via &lt;code&gt;(class&amp;lt;&amp;lt;obj;self;end).instance_method(sym)&lt;/code&gt;. So these methods are not really distinct in this manner after all. In fact there is no distinction between methods other than bound and unbound. And this distinction arises from the capability of &lt;code&gt;class Module&lt;/code&gt; and &lt;code&gt;class Class&lt;/code&gt; to harbor a set of method definitions that are not their own. Which is of course exactly why these constructs exist in the first place. So when we say singleton method, we are not referring to something different from instance method. We only mean that these methods are kept in a special &quot;singleton class&quot;, made just for a specific object, and consequently, are automatically bound to that object. &lt;br /&gt;&lt;br /&gt;Now, I&#39;m going to claim that the term &#39;singleton&#39; is a poor choice for a completely different reason than any given before. It may come as a bit of surprise, but singletons are not inherently single. They are only made so by an explicit restriction in the Ruby&#39;s source code. It is quite simple, actually, to remark the if-clause out of the source, recompile Ruby and then do:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  o = Object.new&lt;br /&gt;  def o.x&lt;br /&gt;    &quot;x&quot;&lt;br /&gt;  end&lt;br /&gt;  def o.x&lt;br /&gt;    super + &quot;x&quot;&lt;br /&gt;  end&lt;br /&gt;  o.x   =&gt; &quot;xx&quot;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The reason Ruby makes the per-object classes single is because it would be terribly inefficient to define a whole new class for every new singleton method defined. That&#39;s understandable, but it also comes at a cost. We can not reliably receive an object from the outside world and define our own singleton on it because we may be clobbering someone else&#39;s singleton method without even knowing it. (NOTE: It doesn&#39;t matter so much if you&#39;re just redefining a method altogether, but if you&#39;re calling super it very much matters.) Generally we don&#39;t even think about such things, but truth be told, object singleton methods often fail to survive code refactoring. Object singleton&#39;s really only exist as a side effect of Ruby&#39;s class model (and Smalltalk&#39;s) which utilize the singleton class as a means of separating a module/class method definitions from it&#39;s own actual methods. This could have been done another way of course, but then a class/module would be something wholly different from any other object. The use of the singleton allowed classes and modules to be just like any other object. So singletons are really a bit of cleverness that lie at the very heart of how Ruby works.&lt;br /&gt;&lt;br /&gt;But does it mean that they &lt;i&gt;have&lt;/i&gt; to be singly? Could we remove the restriction and open up a additional robustness to these per-object classes? We could. In fact, this was the very first hack I ever made to the Ruby source code. My change simply checked to see if the method was already defined in the first &quot;singleton&quot; layer and continue upward until it either found a usable layer or ran out of layers, in which case it created a new one. Combined with the capability to selectively undefine particular methods of particular layers and we gain a flexible pre-object class hierarchy system that can be used without the caveats that currently make singletons so limited outside of class and module definitions.&lt;br /&gt;&lt;br /&gt;And then we no long can call them &quot;singleton&quot; but rather &quot;legion&quot; ;)</content><link rel='replies' type='application/atom+xml' href='http://7ranscode.blogspot.com/feeds/115358722006608324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/30540442/115358722006608324' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115358722006608324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30540442/posts/default/115358722006608324'/><link rel='alternate' type='text/html' href='http://7ranscode.blogspot.com/2006/07/singleton-2-legion.html' title='Singleton 2 Legion'/><author><name>tea42</name><uri>http://www.blogger.com/profile/02848516783203845093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://www.umich.edu/~umfandsf/film/img/colossus-hall-sm.jpg'/></author><thr:total>1</thr:total></entry></feed>