citizen428.blog()

Try to learn something about everything

Tom and Michael vs Prototypical Inheritance

Tom and I read another paper, this time on prototypical inheritance: Organizing Programs Without Classes. You can find his post here and I have to admit that he also did almost the entire summary this time whereas I only added some minor things and code examples.

Summary

OOP is a paradigm which uses “objects” to encapsulate behavior and state in a programming language. This can be accomplished in a few ways, two of the more popular being class based and prototype based object orientation. In class based object models (e.g. Java) a class will be written to define the behavior and state that the object will embody. A class can be inherited from and extended to provide new functionality. In prototype based object models (e.g. ECMAScript, Io), there are no classes, only objects which can be cloned and altered to provide new features. Here’s a quick comparison of the two approaches in Ruby and ECMAScript:

Ruby:

1
2
3
4
5
6
7
8
9
10
11
# define a class
class Hello
   def hello
     puts "Hello"
   end
end #=> nil
# create an object instance
h = Hello.new #=> #<Hello:0x00000100a2f520>
# call a method
h.hello #=> nil
Hello

ECMAScript:

1
2
3
4
5
6
7
8
// create object using a function
function Hello() { this.hello = function() { alert("Hello!") } };
// create instance
h = new Hello();
h.hello(); // pops up an alert
// alternatively we can use an object literal
h = {hello: function() { alert("Hello!") } };
h.hello();

Class based inheritance purports many organizational benefits. Do prototype based languages share them? The paper looks at each benefit in turn and shows approaches to add these features into classless languages or even improve upon them.

Behaviour Sharing:
In class based programming languages code re-use is easy, you can inherit from a class and you’ll get access to that class’s methods and member variables.

In prototype based languages a clone/copy method is written on a prototypical object which can define which data members and methods are copied to the new object. This idea can be refined to an object whose sole purpose is to supply behavior, a trait. This can be a parent object of the new object to provide its functionality. As this trait object is shared amongst all clones, any changes to it affect the clones, just as with the class and subclass of class based programming. Here’s an example on behavior sharing in a prototype based language (Io):

1
2
3
4
5

1
2
3
4
5
<span class='line'><span class="nx">A</span> <span class="o">:=</span> <span class="nb">Object</span> <span class="nx">clone</span>
</span><span class='line'><span class="nx">A</span> <span class="nx">m</span> <span class="o">:=</span> <span class="nx">method</span><span class="p">(</span><span class="nx">write</span><span class="p">(</span><span class="s2">&quot;in A\n&quot;</span><span class="p">))</span>
</span><span class='line'><span class="nx">A</span> <span class="nx">m</span>
</span><span class='line'><span class="nx">B</span> <span class="o">:=</span> <span class="nx">A</span> <span class="nx">clone</span>
</span><span class='line'><span class="nx">B</span> <span class="nx">m</span>
</span>

This will print:

1
2
in A
in B

Representation Sharing:
In class based languages, subclassing gives the child class access to the member variables of the parent, its representation. In prototype based languages, a trait object provides only behavior, not data. This job is performed by a prototype instance of the object, one every other object will be cloned from. Its clone method will copy across its data slots (member variables) with any default values the programmer has provided. This is called a “Data Parent”.

In Ruby:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class A
  def initialize
    @member = "fred"
  end
 def method_a
   puts "in A with #{@member}"
 end
end

class B < A
  def method_b
    puts "in B with #{@member}"
  end
end

A.new.method_a
B.new.method_b

#in A with fred
#in B with fred

In IO:

1
2
3
4
5
6
7
8
9
Food := Object clone

pizza := Food clone
pizza name := "Meat Feast"
pizza price := 10

pasta := pizza clone
pasta name = "Macaroni Cheese"
pasta price = 5

Dynamic Behaviour Changes – Changing an instance’s class and dynamic inheritance:
Tom: This was a section of particular interest, mainly because I think it’s not quite as skewed as they portray it. The idea is that because in a prototype based model the reference to the parent object (traits, data) is simply a reference it can be changed very easily depending on the state the object is in. This provides new functionality as the object goes through its life. In a class based model, changing an instance’s class is difficult at best and not a good idea, however the idea of changing behavior based on state is still a useful concept. The authors however seem to miss the concept of composition and delegation, it’s next to trivial to change the behavior of an object simply by changing the object that is providing a function, just take a look at the Strategy Pattern for an example.
Michael: This paper is from 1991, the Gang of Four book on Design Patterns from 1994, so I guess you’re blaming the authors for not knowing about something that hasn’t been published when they wrote their paper.
Tom: Fair point! I wonder when the concept of delegation was first coined?
Michael: According to Wikipedia in a paper from 1986, “Using Prototypical Objects to Implement Shared Behavior in Object-Oriented Systems”.

In ECMAScript:

1
2
3
4
5
6
function circle(){}
circle.prototype
#circle
circle.prototype = function ellipse(){}
circle.prototype
#ellipse

Changing the prototype can entirely change the behavior of an object.

Naming and Categorising:
This feature is vital in any nontrivial system, without being able to find code to serve its purpose the programmer would be constantly rewriting the same code over and over. Class based languages tend to provide a globally accessible name for a set of functions. They also tend to provide namespaces to prevent naming collisions or categorisation. Prototype based languages need to be able to access the prototype anywhere in the system to be cloned, but as they are just regular objects, they have no internal names. The authors of the paper propose that namespace objects can be used to fill this need. Essentially a globally accessible hash map, which can contain nested namespace objects to provide categorisation. This later emerged as a fairly common pattern in ECMAScript.

In Ruby:

1
2
3
class A; end
A
#A

A is a globally defined constant which points to an Object.

In ECMAScript:

1
2
3
4
5
6
TopLevel = window.TopLevel || {}
TopLevel.SecondLevel = function(){
  var member = null;
  function memberMethod(){
  }
}

Note that TopLevel is simply an object literal.

The naming of these type of systems is highly dependent on the structure of the system, this type of naming is called Extensional naming. Intensional naming is the term given to systems where the name of classes is defined by the programmer and not necessarily related to the structure of the system. The authors claim that Extensional naming has a few key advantages:

1) It’s free with a classless language; no other constructs are required for this behaviour to work.
2) The names are also expressions, and as this is code it can have additional interpretations.
3) Intensional naming can become inconsistent quite easily.

Tom’s not convinced any of these reasons are actually advantages: 1) just because a system comes with a feature doesn’t mean you should use it if there is a better alternative available – prototype based models don’t seem to have much of an alternative. 2) because it is code and not a simple lookup this is more complicated and has more potential for error. 3) this is probably valid. Changing a class name does require it to be updated everywhere in the system, but with refactoring tools this is mitigated.

Conclusion:
This was a pretty interesting paper. Personally I’ve always been drawn to Io, but never got past the “playing around” stage with it. Checking out Self also is on my todo list. I think there’s a certain elegance to prototype based object orientation and I’d like to research it a bit more.

Further reading:

Information Overload 2011-07-10

Review: Learn You a Haskell for Great Good

Disclaimer: No Starch Press were nice enough to provide me with a free copy of the book reviewed here but what I’m about to write has not been influenced by this.

Properly learning Haskell has been on my todo list for years. One of my first more serious attempts was in 2009, when I found a weird little book with lots of cartoons online. As you may have guessed that was Miran Lipovaca’s “Learn You a Haskell for Great Good” and I was immediately intrigued by the writing style and cute cartoons. However back then the book was still a work in progress and I eventually stopped reading it before Miran got around to adding the last chapters. I always promised myself to eventually revisit this later, so I was delighted when I found out that No Starch Press is actually releasing an offline version of the book! Here you can see the cover in its full cartoony glory:
Learn You A Haskell cover

Before you think this book is all about funny drawings, lets talk about the real star, the content. LYAH definitely is among the top programming books I read so far. Due to the author’s easy-going and funny style — though I’m sure there will be some readers who won’t appreciate his humor — you might not even notice at first how choke-full of good content this book is, but once you are done with it you realize that you actually learned a lot. This would be an amazing feat for any technical book, but is even more impressive considering Haskell’s reputation as being a very academical and arcane language. Sure, not everything is covered here — Arrows or CPS come to mind — but every book is finite and the selection of topics is absolutely appropriate for beginning Haskell enthusiasts. The only chapter I wasn’t so happy with was the last one on Zippers, not because it wasn’t well written or interesting, but more because it felt a bit tucked on.

What can you expect from this book? Will you be a Haskell guru after reading it? Most likely not, because that takes a long time of practice and actually writing code. Maybe that’s one of the few weak points of LYAH, the code examples are usually rather short and focussed on getting the point across, not “real-world” tasks you are likely to encounter in day to day programming. They still are great for introducing the reader to Haskell’s way of abstracting problems, which I find immensely beautiful and well thought out. Still, a chapter or two on “programming in the large” and how to structure a big Haskell project would have been nice additions, but there are other places for learning more about the language, e.g. the Haskell wiki or the Haskell Wikibook. What the book will do for you is that once you are done with it, you should have a good basic understanding of the language’s key concepts and type system and will be comfortable around terms like “monoid”, “applicative functor” and “monad”. There still we be a long way to go before you can consider yourself a Haskell expert, but you’ll have a very solid grounding to build on.

All in all this is a remarkable book and maybe just what this beautiful language was missing, an easy to read, entertaining yet still thorough introduction to the language, that gives you an idea that Haskell is not only a research subject for computer scientists but a useful tool that can be used to build software.

Information Overload 2011-07-03

Information Overload 2011-06-26

  • Fish don’t know they’re in water
    This is something I also learned while traveling, the further you go away from home, the more you realize that many things you take as granted are just part of your own culture.
  • Don’t Know Much About History
    While I hope that history lessons in Europe aren’t as bad as they apparently are in the US, I remember from my own high-school days that the subject is often taught in awful ways.
  • The story of the Gömböc
    This is why math is cool: what starts as a weird theory, is later discovered to actually exist in nature.
  • How do magnets work?
    A very nice explanation of magnetism.
  • Why numbering should start at zero
    A letter by Edsger W. Dykstra gives a reason for why array indexing should start with 0 (“an element’s ordinal (subscript) equals the number of elements preceding it in the sequence”).
  • New Japanese Pop Idol Shocks Fans With News — She’s Not Real
    With the amount of crazy news coming out of Japan, it’s surprising the country doesn’t feature here more regularly.
  • An Indian summary
    Great visualization of Indian states compared to countries. Maharashtra for example has the GDP of Singapore, but a per head roughly like Sri Lanka.
  • How European Elites Lost a Generation
    A good article to understand some of the motivations behind the protests of young people everywhere in Europe.
  • Lucky Yingluck
    With the Thai elections around the corner, this article provides some insights into the current election campaign.
  • Criminalizing free speech
    On free speech and extra-legal killings.

Ruby: Going to the C Side

Yesterday afternoon I decided it’s about time I finally learn how to write Ruby C extensions, so I went ahead and rewrote one of our RubyLearning.org exercises in C. Here’s the exercise description:

Write a class called Person, that has balance as an instance variable and
the following public method: show_balance.

I shall create the Person object as follows:

p = Person.new(40000)
puts p.show_balance # calling the method

Here’s the program in C, with relevant function signatures included as comments:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<span class='line'><span class="cp">#include &lt;ruby.h&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="k">static</span> <span class="n">VALUE</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">VALUE</span> <span class="n">self</span><span class="p">,</span> <span class="n">VALUE</span> <span class="n">amount</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// VALUE rb_iv_set(VALUE obj, char *name, VALUE value)</span>
</span><span class='line'>  <span class="n">rb_iv_set</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="s">&quot;@balance&quot;</span><span class="p">,</span> <span class="n">amount</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">self</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">static</span> <span class="n">VALUE</span> <span class="nf">show_balance</span><span class="p">(</span><span class="n">VALUE</span> <span class="n">self</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// VALUE rb_iv_get(VALUE obj, char *name)</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">rb_iv_get</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="s">&quot;@balance&quot;</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kt">void</span> <span class="nf">Init_person</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// VALUE rb_define_class(char *name, VALUE superclass)</span>
</span><span class='line'>  <span class="n">VALUE</span> <span class="n">cPerson</span> <span class="o">=</span> <span class="n">rb_define_class</span><span class="p">(</span><span class="s">&quot;Person&quot;</span><span class="p">,</span> <span class="n">rb_cObject</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="c1">// void rb_define_method(VALUE classmod, char *name, VALUE(*func)(), int argc)</span>
</span><span class='line'>  <span class="n">rb_define_method</span><span class="p">(</span><span class="n">cPerson</span><span class="p">,</span> <span class="s">&quot;initialize&quot;</span><span class="p">,</span> <span class="n">initialize</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span><span class='line'>  <span class="n">rb_define_method</span><span class="p">(</span><span class="n">cPerson</span><span class="p">,</span> <span class="s">&quot;show_balance&quot;</span><span class="p">,</span> <span class="n">show_balance</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span>

I think the code is very self-explanatory, almost like writing Ruby in C. As you can see we define a class called “Person” in the “Init_person” function (which is called by Ruby when it loads our module), where we add the functions as instance methods with “rb_define_method”. To compile this, we need an extconf.rb, which contains the following:

1
2
3
4

1
2
3
4
<span class='line'><span class="n">require</span> <span class="err">&#39;</span><span class="n">mkmf</span><span class="err">&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="n">extension_name</span> <span class="o">=</span> <span class="err">&#39;</span><span class="n">person</span><span class="err">&#39;</span>
</span><span class='line'><span class="n">create_makefile</span><span class="p">(</span><span class="n">extension_name</span><span class="p">)</span>
</span>

Now we can build and run it:

1
2
3
4
5
6
7
8
9

1
2
3
4
5
6
7
8
9
<span class='line'>→ ruby extconf.rb
</span><span class='line'>creating Makefile
</span><span class='line'>→ make
</span><span class='line'>gcc -I. <span class="o">[</span>output snipped<span class="o">]</span>
</span><span class='line'>→ irb
</span><span class='line'>&gt;&gt; <span class="nv">$:</span>&lt;&lt;<span class="s1">&#39;.&#39;</span> <span class="c">#=&gt; [..., &#39;.&#39;]</span>
</span><span class='line'>&gt;&gt; require <span class="s1">&#39;person&#39;</span> <span class="c">#=&gt; true</span>
</span><span class='line'>&gt;&gt; <span class="nv">p</span> <span class="o">=</span> Person.new<span class="o">(</span>3000<span class="o">)</span> <span class="c">#=&gt; #&lt;Person:0x00000100a01940 @balance=3000&gt;</span>
</span><span class='line'>&gt;&gt; p.show_balance <span class="c">#=&gt; 3000</span>
</span>

As you can see everything works as if we had defined the class in Ruby. Let’s add another method to deposit some money, which gives us a chance to demonstrate “rb_funcall”:

1
2
3
4
5
6

1
2
3
4
5
6
<span class='line'><span class="k">static</span> <span class="n">VALUE</span> <span class="nf">deposit</span><span class="p">(</span><span class="n">VALUE</span> <span class="n">self</span><span class="p">,</span> <span class="n">VALUE</span> <span class="n">amount</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// VALUE rb_funcall(VALUE recv, ID id, int argc, ... )</span>
</span><span class='line'>  <span class="n">VALUE</span> <span class="n">result</span> <span class="o">=</span> <span class="n">rb_funcall</span><span class="p">(</span><span class="n">rb_iv_get</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="s">&quot;@balance&quot;</span><span class="p">),</span> <span class="n">rb_intern</span><span class="p">(</span><span class="s">&quot;+&quot;</span><span class="p">),</span> <span class="mi">1</span><span class="p">,</span> <span class="n">amount</span><span class="p">);</span>
</span><span class='line'>  <span class="n">rb_iv_set</span><span class="p">(</span><span class="n">self</span><span class="p">,</span> <span class="s">&quot;@balance&quot;</span><span class="p">,</span> <span class="n">result</span><span class="p">);</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span>

We also need to add this function as a method in “Init_person”:

1

1
<span class='line'> <span class="n">rb_define_method</span><span class="p">(</span><span class="n">cPerson</span><span class="p">,</span> <span class="s">&quot;deposit&quot;</span><span class="p">,</span> <span class="n">deposit</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span>

Does it work?

1

1
<span class='line'><span class="o">&gt;&gt;</span> <span class="nb">p</span><span class="o">.</span><span class="n">deposit</span><span class="p">(</span><span class="mi">400</span><span class="p">)</span> <span class="c1">#=&gt; 3400</span>
</span>

It does and we’ve successfully created a Ruby class from C. Probably not the type of class you’d really implement this way, but good enough as an example.

Recommended reading:

Information Overload 2011-06-19

Information Overload 2011-06-03

Information Overload is a bit early this week and may be skipped altogether next Sunday. After that it should be back to the regular schedule.

Information Overload 2011-05-29

Information Overload 2011-05-22

Copyright © 2016 - Michael Kohl - Powered by Octopress