Operators in Ioke


When I first published the guide for Ioke, one of the reactions was that that was one heck of a lot of operators. The reason being that I listed all the available Ioke operators in the guide, and there are quite a lot of them. What is implicit in the reaction is that these operators all have defined meanings and are used in Ioke. That’s not true at all. So, I thought I’d describe a little bit more what operators are, how they work, and why they are necessary in a language like Ioke.

First of all, all available operators can be found in the Ioke grammar file. They are available as the tokens ComparisonOperator, RegularBinaryOperator and IncDec. Together, they are at the moment 10 + 77 + 2 = 89 operators. Together with assignment, that is 90 available operators. As mentioned above, most of these aren’t actually used anywhere. Instead they are available for use by any client program. They are there specifically for creating nice DSLs and readable APIs.

Operators only exist in the parsing stage of Ioke. After that everything is a message, and a message based on an operator is no different from one based on a regular message send. So the importance of operators happen mostly in the stage of operator shuffling. Since Ioke uses whitespace for regular message application, the implementation could treat EVERYTHING the same. That is also the base case. If you turn of operator shuffling, you could write =(foo, 1 +(2 *(20 **(42)))) to assign an expression to the name foo. This way of writing isn’t necessarily convenient, though, which is why Ioke adopts an operator shuffling scheme similar to Io.

So, what is an operator? It is really just a method with some funky characters in the name. All operators in Ioke are binary or trinary. What looks like a unary operator is simply just a message send to an implicit receiver. So 10 – 5 is the same operator as -5. It’s just that the second version will call the method – on DefaultBehavior, giving it 5 as argument. The result will be the negation of the argument. Binary operators aren’t anything strange, but when I say trinary operators, people will probably think about the ?: combination available in some languages. That isn’t exactly what I mean. There is another distinction between operators that is useful in Ioke – that between assigning operators and regular ones. The assigning operators are =, things like +=, /= and the increment and decrement operators ++ and –. All assigning operators are trinary except for the increment and decrement operators.

So what does this mean? (And I realize this is becoming a bit rambling at this point…). Ok, the rule is this. All assigning operators takes a place to assign to. That is the left hand side. Everything except for increment and decrement takes a value to send to the assign operator. But that leaves the actual receiver of the assignment message. Since assignment is just a message like everything else, there must be a receiver. So, in Ioke, if I write  foo += 1+2, that will be translated (I will explain this later), into  +=(foo, 1 +(2)). At this stage it looks like the += message is sent without receiver, but everything in Ioke has a default receiver – called the ground. In another situation, suppose we have a class like object called Foo. Then the expression  Foo bar = 42   will be translated into  Foo =(bar, 42). Here it is more apparent that the receiver of the =-message is actually Foo, and the direct left hand side and right hand side of the =-sign are both arguments. This means that there are three operands in these assignment operators and that is why they are called trinary.

Back to operator shuffling. In the examples I’ve shown above, the operator shuffling step is code that will basically take something that likes like regular arithmetic or assignment and rearrange that into the real message form. So x+1 will be translated into   x +(1). Something like   2+2*3 will be translated into 2 +(2 *(3)). And all operators translated this way has an associativity to make sure they follow expectations. You tune this associativity using the Dict inside Message OperatorTable operators. This can be used to create DSLs with new or different operators.

One thing that might surprise some people is that regular alphabetical names can be used as operators to. That is how something like “and” can be used in infix position.

I know that the operator rules are a bit complicated, and the grammar isn’t fantastic either. But when working with it, it feels really natural for me – and that is the goal. Operators and syntax are important. They make a large difference to the feel of the language. So I decided to make it as obvious as possible, without sacrificing the internal consistency of the language. And ultimately the control is in the hands of the Ioke programmer.

So, to recap, any of the available operators can be defined in the regular way. Just define it like you would anything else. And you can assign macros or syntax to operators too. They are just handled as regular names.


4 Comments, Comment or Ping

  1. One tip I use to discover the internal representation of a block of code is to wrap it inside a fn block within an iik prompt. iik will evaluate it and output the internal form:

    λ ioke
    iik> fn(foo += 1+2)
    +> fn(+=(foo, 1 +(2)))

    January 8th, 2009

  2. Sam:

    True, and that works. A longer way of doing the same is to do “Message fromText(#[text here])”. This will parse and shuffle the code in the text, and return the message chain corresponding to it without evaluating it.

    A message can format itself as text using either “code” or “formattedCode”, where formattedCode inserts newlines and whitespace and a few other things to make it easier to read.

    January 8th, 2009

  3. Cool :-)

    January 8th, 2009

Reply to “Operators in Ioke”