Variant types

My languages lecturer is a fan of a feature called ‘variant’ in a model
language he defined. The variant declaration is used to specify that a
variable may be of one or another type.

When he stated that no languages we are taught have this functionality,
I asked him whether using an abstract class which is subclassed for
each variant type would be enough. He said that this would work, but is
a form of encoding the declaration and as such is not as good as such a
declaration provided as part of the language.

I had a go at implementing ‘variant’ in Ruby. I’m going to show it to
him tomorrow and see what he thinks. Comments welcome.

Variant takes the name of the property, and one or more types. I
haven’t seen him use this for more than two types however.

Can anyone see a way to do away with the instance variables? I could
have made them methods, but this does not seem to offer additional
encapsulation.

Code:

class Class

def variant(name, *classes)
instance_variable_set("@#{name}_value", nil)
instance_variable_set("@#{name}_classes", classes)

classes = instance_variable_get("@#{name}_classes")

define_method("#{name}=") do |value|
  if classes.include? value.class
    instance_variable_set("@#{name}_value", value)
  else
    raise "TypeException for '#{value}'. May be one of

[#{classes.join(’, ')}]"
end
end

define_method(name) do
  instance_variable_get("@#{name}_value")
end

end
end

class ListItem

def initialize(value)
self.value = value
end

attr_accessor :value

variant :next, ListItem, NilClass
end

item = ListItem.new(‘1’)

item.next = ListItem.new(‘2’)

item.next.next = ListItem.new(‘3’)

Try assigning a value which would not make sense

in the context of a list.

begin
item.next.next = 2.2
rescue => ex
puts ex
end

while item != nil
puts item.value
item = item.next
end

Output:

TypeException for ‘2.2’. May be one of [ListItem, NilClass]

1

2

3

Stefan.

Stefan Haflidason wrote:

My languages lecturer is a fan of a feature called ‘variant’ in a model
language he defined. The variant declaration is used to specify that a
variable may be of one or another type

If I understand correctly, it sounds very much like a static lanugage
concept, with little applicability to Ruby. The problem with
implementing it is Ruby is not to open up variables to more than one
type (that happens automatically), but to artificially restrict the
variable to the explicitly listed types.

When he stated that no languages we are taught have this functionality,

Perhaps the key phrase is “we are taught”, because as described,
variants sound much like a union in C. If I recall correctly, even
Pascal has variant records that did much the same thing. Of course, I
may be misunderstanding yor description.


– Jim W.

Hi –

On Thu, 16 Mar 2006, Stefan Haflidason wrote:

I had a go at implementing ‘variant’ in Ruby. I’m going to show it to

class Class

def variant(name, *classes)

You’re right to call your variable classes, rather than types. In
Ruby, an object’s type is not the same as its class. The type of an
object is basically the sum of its various capabilities at a given
moment in runtime. Some of those capabilities come from the object’s
class, but not necessarily all; and the object’s type can change.

There are already some packages out there that do class/ancestry
checking (and sometimes refer to it as “type” checking). Actual
type-checking is much harder in Ruby, perhaps even impossible, though
there have also been some interesting experiments along those lines.

It’s an interesting exercise to do class-checking, but keep in mind
that it doesn’t really address object type, and also that you’re
unlikely to need it beyond the exercise stage :slight_smile:

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! Ruby for Rails

Jim W. wrote:

If I understand correctly, it sounds very much like a static lanugage
concept, with little applicability to Ruby. The problem with
implementing it is Ruby is not to open up variables to more than one
type (that happens automatically), but to artificially restrict the
variable to the explicitly listed types.

Can’t a little restriction be healthy? In the lecture last week I could
have, instead of using abstract classes in Java, used Ruby’s dynamic
typing to show that the property could already be set to be of any type.
But is that freedom a weakness?

If this restriction was used in a large software system, and another
developer mis-used a list type I had defined, or some other library,
then the TypeException would be raised. Without the restriction, the
other developer would be able to set ‘next’ to be a Fixnum, for example.
Then, when I call next on the Fixnum I’d get its successor, and not a
ListItem. I would need to call kind_of? to check that next is returning
a ListItem and not something else.

If you wanted to be confident that the software was implemented as it is
specified, would this (variant typing) not be preferable to calling
kind_of? many times?

When he stated that no languages we are taught have this functionality,

Perhaps the key phrase is “we are taught”, because as described,
variants sound much like a union in C. If I recall correctly, even
Pascal has variant records that did much the same thing. Of course, I
may be misunderstanding yor description.

We are, unfortunately or necessarily, only taught a few languages. I
don’t agree with the choices, but it’s not a problem as I teach myself
what I can.

I currently do ~90% of my programming in Ruby. I’m currently studying
(outwith my course) Ruby, Common Lisp and Haskell.

What I don’t have is an answer to the question, “How does the freedom of
Ruby’s typing system affect large-scale software development?”. I enjoy
programming in Ruby and have involved it in my final year project and
every-day tasks. The freedom does make me a little nervous though, as
unless I have misunderstood the ethos behind it, it seems to imply that
those who use it must be proficient.

Given the ease with which Ruby can be picked up, there are sure to be
many people in the near future who put Ruby on their CV who have at best
a simplistic understanding of its workings/use.

I do not consider this to be a fault of Ruby; far from it. I do however
forsee in my own future a discussion with a future manager where I
suggest Ruby and will be required to exemplify Ruby’s suitability for a
large project.

Without restrictions, and without the notion of contracts, what
foundations could my answer be based on?

Stefan.

Hi –

On Thu, 16 Mar 2006, Stefan Haflidason wrote:

have, instead of using abstract classes in Java, used Ruby’s dynamic
typing to show that the property could already be set to be of any type.
But is that freedom a weakness?

That’s a bit like asking whether having strings is a weakness because
clarinets don’t have them. It’s just a different design principle.

I do not consider this to be a fault of Ruby; far from it. I do however
forsee in my own future a discussion with a future manager where I
suggest Ruby and will be required to exemplify Ruby’s suitability for a
large project.

Without restrictions, and without the notion of contracts, what
foundations could my answer be based on?

The evidence of people who’ve done it is one possibility. Also, it’s
important to remember (though you may not want to tell the future
manager :slight_smile: that the dynamism of Ruby is not something that can be
switched on and off. Checking class/module ancestry is, I think,
comforting to some people. But in the end, you send messages to
objects at a given point in runtime, and that’s what it’s all about.
Ruby doesn’t really care whether you’ve checked the class name or not.
It’s all about the objects.

David


David A. Black ([email protected])
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! Ruby for Rails