On Mon, 28 May 2001, Stefan Matthias Aust wrote:

> To allow a better documentation of classes, I added a "var" method to
> the kernel module which helps me to write down instance variable
> definition is a readable manner.  I'd like to some opinions whether
> this is a stupid idea or a useful one.

In dynamically-typed language circles there is the consensus that
type-checking is what the language already does and that you should
not seek to put any explicit type-checking.

Now, there's of course a difference between this wish, and my opinion
(which I also call "Reality"). My opinion is that: in several cases you
*need* type declarations; in many other cases, you wish they were there; 
and a dynamic language gifts you with the possibility to invent your own
kinds of types, type-declarations, and type-checking.

For example, the X11 client protocol codec I'm writing right now (RubyX11) 
uses its own type declarations as a protocol specification. It also uses
it for ordinary type-checking because that traps a large amount of bugs. 

But for many other domains, types aren't so useful beyond what the
language offer, that is true.

> class Game
>   var :name,      'String'
>   var :turn,      'Integer'
>   var :players,   'Array<Player>', :readonly
>   var :worlds,    'Array<World>', :readonly
> end

why not:

var :name,    String
var :turn,    Integer
var :players, Array.of(Player), :read
var :worlds,  Array.of(World),  :read

If you wish to do checking of generic types, then you have several
options: you can make the accessor check all the contents of the array,
or you can have the array checking contents that are introduced in it.
(Blatant plug: this is yet another 10-line program using MetaRuby). In
both cases, you'll have to implement Array.of().

> This currently only works for non-generic types, but with more effort
> (and meta-magic) it should be possible to also support Array<E> and
> Hash<K,V> style type checks.  My idea is to wrapp arrays and hashes
> when they are assigned to the instance variable using some proxy
> object which then intercepts the []= method and delegates all other
> methods to the original.

you could also simply do:

module TypedArray
	def []=(*args)
		raise TypeError if ...
		super
	end
end
a = []
a.extend TypedArray

But then, you have also to wrap a few other methods that bypass your
implementation of #[]= because they call each other directly at the C
level (or they access the array directly). Those are #map!, #collect!,
#concat, #fill, #flatten!, #push, #<<, #unshift, and I think it's all.

You can't pass arguments when you call Object#extend, but you could have a
write-once field called :element_type, which you would use to set the
type.

matju