Day 2 covers method definition and it’s potential. Io manages to express quite a few interesting things in its minimal syntax.
The more interesting features of methods are the
Message meta information (the ability of a method invocation to introspect both the caller, callee, and the parameters), and the selective parameter evaluation, which supports the creation of new control operations (such as fancy loop or conditionals).
In line with today’s topic, exercises are about defining and executing methods.
I change the exercise a bit: I defined the fibonacci sequence for Number, and it uses the number it is called on as the argument. So I compute
40 fib rather than
fib(40). For this reason I have to use
self when I want to refer to the original argument explicitly.
The recursive (and slow) method translated directly from the definition:
For the iterative method, I’m using a intermediate function with accumulators to build the result (I have easier time thinking in functional than imperative terms):
Finally, an iterative imperative method, with explicit looping (the iteration starts at 2 because the
for method iterates up to and including the upper bound):
1 2 3 4 5 6 7 8 9 10
/ to return 0 when divided by 0
First I save the original definition of
/, then I update the operator slot with the new definition:
Add up all the numbers in a two dimensional array
Assuming the array is implemented as a
List of list, the following invocation will sum the numbers:
The initial value is supplied explicitly; otherwise
reduce would use the first value, which is not a number but a list.
Alternatively (and much shorter):
reduce method, it is easy to compute the sum of a list. The
size method can then be used to compute the average:
1 2 3
If the list is empty, the
reduce method returns
nil, so we get an exception (as
nil does not respond to the
/ method). But this is consistent with the existing
1 2 3 4 5 6 7 8 9 10 11
I am using a new operator,
+?, with the same priority as
+, and explicitly check the prototype with
Two-dimensional list prototype
First I clone a specialization of
List as the implementation to the two dimensional array.
The initialization simply creates then grows the internal lists to the appropriate size, and stores the original parameters as slots:
1 2 3 4 5 6 7
The accessor methods can use the dimension slots to check for out of bound access:
1 2 3
checkBounds guarantees an exception is raised if the position parameters are not within bounds. The method
get simply invokes
at twice to get at the data;
set first locate the right sub list with
at, then update the correct value with
atPut, and finally returns the updated array.
Two-dimensional list transpose method
Dim2 defined as above, the
transpose method is trivial:
1 2 3 4 5 6 7
Just initialize a new array, swapping the dimensions, then iterate over both dimensions, swapping the parameters for the
get and the
First the method
asString can be used to get the string representation of an object, including the two-dimensional list.
However, the default
asString returns the same representation as for regular nested lists. In order to read the object from the string,
asString has to be overridden to emit something specific.
1 2 3 4 5 6 7 8
With this defined, a two dimensional list has a unique representation:
With this in place, I can define a
twodim function that creates an instance of
Dim2 and fills it with the passed data:
1 2 3 4
twodim method is not defined on
Dim2, but globally, so that the content of a string representing a
Dim2 instance can be parsed in any context.
With this in place, the object can be serialized and unserialized, using the
doString method (which evaluates the string in the target context):
1 2 3 4 5 6
So the last step is to store the string representation in a file, and read from it:
1 2 3 4 5 6
Unsurprisingly, the content of the file is
Reading is just as simple:
1 2 3 4 5 6
Dim2 instance is equal to the unserialized one. I did not really expected that (I didn’t write any comparison code for the new object), but Io provided a sensible implementation anyway.
Note: theres is a
serialized method, but it’s output representation in the case of
Dim2 is the same as the one for
List. There should be a way to override
serialized as well, but it’s exact semantic is not clear to me.
Guess a Number Game
Given the above, the last exercise a walk in the park. Getting the number from the standard input was a bit harder to figure out. For some reason, on Mac OS X, reading from the standard input also displays
nil; I guess it is a bug, although not a very serious one.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Well, that was quite a day. The exercises did not cover the more advanced use of method (such as implicit argument evaluation), but otherwise gave the opportunity to define useful behaviours, and play with important classes from the standard library.