Tyler Brandt
Tyler Brandt

Reputation: 51

Io: How to instantiate a subclassed primitive (e.g. Number)?

In the book 7 Languages in 7 Weeks there is a question:

How would you change / to return 0 if the denominator is zero?

Thanks to the thread What's the significance of self inside of a method? I have a working solution, but I wanted to try to do it without clobbering the Number "/" method, and instead subclass Number. Here is what I tried:

Zeroable := Number clone
Zeroable / = method(denom, if(denom == 0, 0, self proto / denom))

However, this doesn't work. If I try to instantiate an instance of Zeroable, it behaves just like a number:

Io> ten := Zeroable 10
==> 10
Io> ten type
==> Number
Io> ten / 5
==> 2
Io> ten / 0
==> inf
Io> ten slotNames
==> list()

If I instantiate the Zeroable the "normal" way it works, but the value is always 0 and there doesn't appear to be a way to change it:

Io> zero := Zeroable clone
==> 0
Io> zero type
==> Zeroable
Io> zero / 0
==> 0
Io> zero / 2
==> 0

I think the issue is the way that ten is instantiated, but I cannot figure out how to pass "arguments" to a clone method, or otherwise how to create a Zeroable that is not 0. What is going on here?

Upvotes: 3

Views: 128

Answers (1)

jer
jer

Reputation: 20236

Arguments cannot be passed to clone, clone is effectively set up like this:

clone := method(
  obj := primitiveAllocateMemory(sizeof(self))
  obj parent := self
  obj do(?init)
)

Secondly, you can't subclass Number like that. Number objects are created by the lexer when it encounters a literal number, and given the type Number. This object is set as the cached result of a message, meaning, even if you intercept the message and evaluate it as some other object, you'll still get back a Number. Effectively this is a short circuit of message evaluation for performance reasons.

If you want a different Number type, you'll have to actually implement it yourself with what operations you want. This means subclassing Object (or some other object) and implementing all the behaviours your want. Note if you subclass Number, the implementation of methods on Number won't be able to make sense of your subclass (how it stores its numbers). Number methods assume a numerical value encoded in the object, not its slot table.

Upvotes: 3

Related Questions