I now am ready to take some first steps with Ioke. If you would like to install it for yourself and try it out too, you can follow the instructions or follow the Hitchhiker’s Guide. I used the instructions for a vanilla install, but it looks like the Hitchhiker’s Guide goes into far greater detail.
I’ve now installed basic Ioke on Windows and Linux and it was painless in both cases, which was an unexpected pleasure. Once installed, you can fire up the REPL with a simple ioke at the command line. What you are presented with will look something like this:
1
2
| rubyyot@atlas:~$ ioke
iik> |
You are now ready to play with Ioke. It is quite different from what I’m used to. I would recommend that you try out the interactive mode as well to get your feet wet. That way you will get immediate feedback.
A few things stand out immediately when playing around with the language. The first is that there is no dot notation. Second are the concepts of cells and Ground. Third is the that it is a prototype based language.
It’s not a dot, it is a period
Object oriented programming is supposed to be littered with dots, it’s part of the language. Without the dots how are we supposed to tell where one word stops and the next begins. This is insane!
Or is it. English doesn’t use dots to separate it’s words. Tell.me.does.this.look.like.a.natural.sentence.to.you? No, it really doesn’t to me either. Asthetically, it’s only slightly betterThanCamelCase. Ok, so I get it, the whitespace separates the words , or in this case they are called messages. You may ask, “What is a period good for?” Let’s go to the REPL and find out.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| iik>; "hello world" println
hello world
+>; nil
iik> "hello world" println. "hello ioke" println.
hello world
hello ioke
+> nil
iik> "hello world" println "hello ioke" println
hello world
hello ioke
+> nil
iik> "hello world". println
*** - couldn't find cell 'println' on 'Ground_0x17B4DFB' (Condition Error NoSuchCell)
"hello world" [<init>:1:15]
The following restarts are available:
0: storeValue (Store value for: println)
1: useValue (Use value for: println)
2: abort (restart: abort)
3: quit (restart: quit)
dbg:1> |
Wow, so what’s all that? Well I evaluated 4 statements using the REPL. The first one simply told Ioke to print the string “hello world” on the screen followed by a new line. So far so good, I’m now past the obligatory Hello World command. The line beginning with +> displays the return value of the evaluated statement. In this case it was nil, which should be familiar to those who have used Ruby and for anyone else, it means the same thing as null.
The next expression that I evaluate is two println statements each followed by a period so that the compiler will know that I handed it two statements. Sure enough, we see that both lines are printed. So, the period can be used to separate statements. Or can it, the next experession yeilds the same results without a period in sight. This is an interesting development. Perhaps I had it wrong.
To test my theory I decided to try placing a period between the string and the println message. What happened was that I got an error saying that println is not valid for Ground. Even though I’m not entirely sure what ground is at this point, it’s fairly obvious that the placement of the period caused the println message to be called on something other than the string I passed it. As a side note, the error was nicely caught by the debugger which prompted me for an action to take.
Ground, Origin and cells
So let’s see what this Ground is that the debug message was talking about. According to the documentation:
Ground is the default ground/context for evaluation.
Meaning that Ground is a high level object that is the default context for evaluation of a message. For this to become a little clearer, a little background of the Evaluation Model helpe. Here is an excerpt from the wiki that helps sort it out. It takes the code foo bar(flux bar) quux and breaks down the evaluation into steps.
- The message
foo is sent to Ground, which is the current ground and also the default receiver.
- The message
bar is sent to the result of the foo message. The value returned will be activated.
- The cell
bar contains a method in this case, and that method expects one argument, so that forces evaluation of the arguments.
- The message
flux is sent to Ground, since it’s the ground and there is no prior message inside of an argument list.
- The message
bar is sent to the result of the flux message.
- The result of the
bar message is used as the argument value given to the outside bar method.
- The message
quux is sent to the result of the initial bar message.
- The result of the
quux message is thrown away, unless this code is part of a larger piece of code.
Here we see what it means when we say that Groud is the default context. The messages foo and flux have no receiver (there are no words preceding them in the execution model) so the receiver is defaulted to Ground.
Lets now take a closer look at objects in Ioke. Each object has an infinite (at least that is how I see it in my mind, there probably is some sort of limit on it) number of storage containers called cells. You can name these cells and fill them with stuff. You can fill them with data, and objects. These would be considered cells filled with content that is not activatable. Here are some examples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| iik> foo = Origin mimic
+> Origin_0x26FBCA:
iik> foo cheese = "Cheddar"
+> "Cheddar"
iik> foo answer = 42
+> 42
iik> foo
+> Origin_0x26FBCA:
answer = 42
cheese = "Cheddar"
iik> bar = Origin mimic
+> Origin_0x19A1925:
iik> bar size = "little fish"
+> "little fish"
iik> foo stomach = [ bar ]
+> [ Origin_0x19A1925:
size = "little fish"
]
iik> foo
+> Origin_0x26FBCA:
answer = 42
cheese = "Cheddar"
stomach = [Origin_0x19A1925]
iik> foo stomach[0]
+> Origin_0x19A1925:
size = "little fish" |
Here I’ve made two objects, each of these objects mimics Origin. Origin being an object designed to be the starting point for other objects. It seems to be a bit lower in the object hierarchy than Ground.
You can also put activatable content in the cells, these are methods (he behavior component of the object). Here is an example using the previous objects:
1
2
3
4
5
| iik> foo ask = method(question, answer)
+> ask:method(question, answer)
iik> foo ask ("What is the meaning of life, the universe and everything?")
+> 42 |
Here, I’m simply creating a method that takes a parameter called question and always returns the value of the cell answer. Because a method is activatable it is executed when the cell is referenced.
Mimics and prototypes
Ioke is a prototype based language, this is a concept that I’m having the most difficulty with. I’ve spent so much time working out the relationship between classes and objects, and here is a language that does away with the concept of classes altogether. Instead of using a class as a template for a new object instance, the new object mimics an existing object. This means that the templating comes from an instance of an existing object. I’m going to have to get used to this one.
Well I’ve cracked the seal on Ioke and it’s been a pleasant experience that still seems a bit foreign. I’m going to work with it some more and hopefully post some interesting things that I find.