2006-09-21

I No Longer Believe In Methods

Yes, that's right. I no longer believe in methods. Why? Becuase this is OOP and if the methods aren't honest to goodness objects from the start, without exception, then they are not really methods. They're just glorified functions.

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.


Class Project
def announce
puts "This is my new project!"
end
end


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't first class objects, we are forced to return to functional programming. In which case, it is best to define some sort of DSL.


module ProjectDSL
def help( name, text )
@help ||= {}
@help[name] = text
end

def valid( name, &test )
@valid ||= {}
@valid[name] = test
end
end

Class Project
extend ProjectDSL

def announce
puts "This is my new project!"
end

help :announce, "Announces your project to the world!"
valid :announce { @version > "0.0.0" }
end


Now this kind of thing has come up enough in large projects, such as Nitro, that a general means of annotation proved to be most effective.


require 'facet/annotation'

Class Project
def announce
puts "This is my new project!"
end

ann :announce, :help => "Announces your project to the world!",
:valid => lambda { @version > "0.0.0" }
end


Annotations works very well, and if you find yourself in need of this kind of "method metadata" it is an excellent approach.

But I've worked with all this long enough now to be able to have a wide perspective on it and it's become very clear to me that the whole "special needs" 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 method() and instance_method() 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:


class Tool < Method
attr_accessor :help

def valid( &test )
@valid = test
end
end

Class Project
def announce => Tool
puts "This is my new project!"
end

announce.help = "Announces your project to the world!"

announce.valid { @version > "0.0.0" }
end


I'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.

9 comments:

Anonymous said...

it's polymorphism over self that defines OO languages. ruby certainly qualifies.

methods are and should be a concept orthogonal to objects. this is because objects are a labeled set of methods. if we state that methods are also objects, we arrive at an empty recursive definition. we also completely fail to capture the actual behavior of methods, which is term rewriting under substitution of self and the formal parameters of an invocation.

read abadi and cardelli's Theory of Objects for in depth discussion.

it's obvious that even in your example, methods are something different than objects, though you're having them syntactically masquerade as objects to store some properties.

can you take your strawman example and define a semantics that makes sense for an entire language? what does that look like? i think you'll find it instructive.

tea42 said...

Yes, Ruby is an OOPL, but I am arguing that it lacks an OOPL characteristic. Just like Lisp is a functional language but is not considerd pure. Things admit of degrees.

Every object is different from every other object, yet they are still objects. Thus a method can be different but also be an object. The "semantic" is already defined. They are called "methods as 1st class objects." It's been done... it's being done. Consider, the heart of all computer code is simply number as symbolic representation. The computer cannot, on its own, distinguish between operator and operand.

As for my "strawman" example, it is in fact the simplification of very real code.

Jacob Fugal said...

You need to be careful of your usage of the term "functional". E.g.:


... the whole "special needs" arises out of the fact that Ruby is, in this respect at least, still a functional lanaguage and not a true OOPL.


I have a feeling you mean "procedural" here. The term "functional language" is a very well accepted term for languages whose entire semantic is based on composition of "functions" (aka lambdas), such as Lisp, Scheme, OCaml, etc. "Procedural languages", on the other hand, are languages where the semantic is based on the imperative execution of subroutines ("procedures").

And I don't think many in the "true" functional languages camp would be too happy with the characterization that functional languages fall short of OOP languages, if that's what you really meant. :)

Anonymous said...

we will simply have to disagree. your definition of object is broad enough to lose it's utility.

lisp was based on a misunderstanding of lambda calculus. these issues were later (mostly) corrected, tho impure features remain as they're considered useful.

i believe you are similar misunderstanding OO. there are several formalisms for OO available. each are largely equivalent, though i believe abadi and cardelli's is most convenient. read http://lucacardelli.name/Papers/PrimObj1stOrder.pdf for an introduction.

i'm calling your example a strawman because you've merely provided syntax with the assumption that a reasonable semantics for it exists. if you work the semantics out explicitly, i think you'll find you need to separate the concepts of object and method.

autocrat said...

You should look at Io. _Everything_ is an object, for real. It doesn't even have keywords.

http://www.iolanguage.com/about/faq/

From the manual:

"Io’s guiding design principle is simplicity and power through conceptual unification.

In Io, everything is an object (including the locals storage of a block and the namespace itself) and all actions are messages (including assignment). Objects are composed of a list of key/value pairs called slots, and an internal list of objects from which it inherits called protos. A slot’s key is a symbol (a unique immutable sequence) and it’s value can be any type of object."

tea42 said...

Hi jacob. Well "procedural" would be okay. I really just mean non-OOP. People tend to associate Ruby to Smalltalk when it comes to it's OOP charateristics and Lisp otherwise. So I choose the term "functional" for that reason. And don't get me wrong I'm not implying anything against functional langauges. I love Lisp!

tea42 said...

i'm calling your example a strawman because you've merely provided syntax with the assumption that a reasonable semantics for it exists. if you work the semantics out explicitly, i think you'll find you need to separate the concepts of object and method.

Are you saying that it is not truly possible to have methods as 1st class objects? Despite my hyperbole, in short, that's all I'm really suggesting.

Anonymous said...

what does "methods as first class objects" mean?

that you can treat a method as an object?

yes, this is obviously possible.

that you can unify the notion of object and method into a single uniform entity?

no, i do not believe there is any reasonable semantics for this.

in io anonymous methods and blogs are first class, but they are not objects. stack frames however are, which is a rather interesting possibility.

"Are you saying that it is not truly possible to have methods as 1st class objects? Despite my hyperbole, in short, that's all I'm really suggesting."

i think you're confounding two uses of 'object'. one to mean object as in the thing that has slots/methods/etc, and the other to mean "entity of the language semantics". if you rewrite your statement to say that methods can be first class values of the language, I would agree. this is a far different thing than saying that the concept of method is superfluous, and that you need not believe in it, believing only in objects.

tea42 said...

this is a far different thing than saying that the concept of method is superfluous, and that you need not believe in it, believing only in objects.

Okay. It just terminological then. What I mean is simply this: if a procedure isn't 1st class then it isn't a method. Now obviously one can argue with my definition of method, but understand that I am making it from a pure OOPL point of view. The upshot of course is that when I say by "I no longer beleive in methods" I mean that I no longer beleive in Ruby's "methods" b/c they aren't methods, rather they are just procedures.

Thanks for the feedback!