Fun with the RPN calculator in Ioke

In this article, Cédric Beust explains how to port a RPN calculator from Haskell to Fantom. It could have made me want to code more in Haskell or go discover Fantom. Not at all. Reading the article, I felt the urge to code the same algorithm with Ioke. You know, this language I discovered through a MasterMind Kata a while ago.

Here is the Fantom code:

foldingFunction := | Int[] n, Str p -> Int[] | {
  echo("n:" + n)
  switch(p) {
    case "*" : return n.push(n.pop * n.pop)
    case "+" : return n.push(n.pop + n.pop)
    case "-" : return n.push(n.pop - n.pop)
    case "/" : return n.push(n.pop / n.pop)
    default: return n.push(p.toInt)
  }
};
"8 1 2 + 5 * +".split.reduce([,], foldingFunction)

Here is my first try with Ioke:

rpn=method(sum, x,
  case(x,
    "+", [sum pop! + sum pop!],
    "*", [sum pop! * sum pop!],
    "-", [sum pop! - sum pop!],
    "/", [sum pop! / sum pop!],
    [x toRational]
  ) + sum
)
"8 1 2 + 5 * +" split fold([], sum, x, rpn(sum, x)) println

Quite neat. The code looks a lot like the Fantom code or even the Haskell code/
Now let’s use the power of Ioke and remove duplication by defining rpn method on List itself :

List rpn = method(x, 
  append!(case(x,
    "+", pop! + pop!,
    "*", pop! * pop!,
    "-", pop! - pop!,
    "/", pop! / pop!,
    x toRational
    )
  )
)
"8 1 2 + 5 * +" split prepend!([]) fold(rpn) println

I like that one better. We could remove some more duplication at the expense of readability, because, you know, there must be another way to convert “+” to , “*” to * and “-” to -:

List rpn = method(x, 
  append!(case(x,
    or("+","*","-","/"), Message fromText(x) appendArgument(pop!) sendTo(pop!),
    x toRational
  ))
)

Here we used reflection, but we could use eval method and regexp:

List rpn = method(x, 
  append!(if(x !~(#/[-+*/]/),x toRational,Origin eval("#{s pop!}#{x}#{s pop!}))
)
"8 1 2 + 5 * +" split prepend!([]) fold(rpn) println

Ok, now let’s try to recall those days I was an expert in Perl, and compress this to the max:

r=fn(e,e split fold([],s,x,s append!(if(x !~(#/[-+*/]/), x toRational,
Origin eval("#{s pop!}#{x}#{s pop!}")))))
r("8 1 2 + 5 * +") println

This one, I’m not really proud of. Should I?

3 thoughts on “Fun with the RPN calculator in Ioke”

  1. Note that you seem to be using an imperative style. The point of the exercise in Fantom and Haskell was to compare their fold/reduce capacities. I’m not sure if Ioke supports fold(?).


    Cédric

  2. Hi Cédric. Not sure I understand your question. I use Ioke’s fold method on List in every code sample. Also the code doesn’t seem imperative style to me. Can you elaborate?

    David.

Comments are closed.