Fantom vs Scala: semicolon inference and something more
As I said in a previous post, even if Scala is at the moment the best candidate to become the Next Big Language, I think that many things in its syntax are Byzantine and error prone. The examples in Klaus' comment are very explanatory in this sense.
In my search of the Holy Graal of the programming languages, I met Fantom (previously known as Fan), a very interesting attempt to create a language simple yet powerful.
First of all, let's have a look at a Fantom version of the semicolon inference example of my previous post. Note that, since I'm an absolute beginner in Fantom programming, the use of the language I made is far from optimal: any suggestion will be appreciated.
class GoodFantom {
static Int subtract1(Int a, Int b) {
a -
b
}
static Int subtract2(Int a, Int b) {
a
- b
}
static Void main() {
echo(subtract1(10, 2)) //Prints 8
echo(subtract2(10, 2)) //Prints 8 too!
}
}
The Fantom way to handle statements ending seems pretty good. Anyway, I'm not sure that there are not drawbacks to this approach: again, any suggestion is welcome.
Now let's see how this example of creating a DSL fragment in Scala could be translated in Fantom.
So, let's define a Loop class:
class Loop {
//Constructor that accepts a function without parameters that returns Void
new make(|,| body)
{
this.body = body
}
Void unless(|->Bool| cond)
{
body.call()
if (!cond()) unless(cond)
}
|,| body
}
Then we use it in our code:
using fanExercise::Loop
class Main
{
static Void main()
{
Int i := 10
Loop(|,|
{
echo("${i--}")
})
.unless |->Bool| {i == 0}
}
}
We can see that the Fantom version is slightly more verbose than the Scala one (even if, as I said, maybe a good Fantom programmer could do better), but, as the dot is mandatory in method calls, I think it's less error prone.

Klaus:
Yes, the period helps in the sense that:
.unless |->Bool| {i == 0}
can occur on a line for itself. This is also the case in Scala if one uses the dot notation.
Below is the example in Scala with several uses, so one can see the different scenarios.
First the definition of the loop construct:
object Loop { def loop(stmt : => Unit) : Unless = { new Unless(stmt) } protected class Unless(stmt : => Unit) { def unless(cond : => Boolean) { stmt if(!cond)unless(cond) } } } import Loop._Then the calls:
// call 1 (using mixfix notation - works): var i : Int = 10; loop { println(i) i = i - 1 } unless (i == 0) // call 2 (also using mixfix notation, but with unless on a line for itself - gives a compile time error): i = 10; loop { println(i) i = i - 1 } unless (i == 0) // occurs on a line for itself - does not work // Also, if this last line is left out, no error message is given. // This is how other OO languages work. Not a problem as such in OO languages, // but it does reduce the value of this mixfix notation for writing DSLs. It makes a DSL unsafe to use. // call 3 (using dot notation - works as expected): i = 10; loop { println(i) i = i - 1 }.unless(i == 0) // call 4 (using dot notation, with unless on a line for itself - works): i = 10; loop { println(i) i = i - 1 }. unless(i == 0) // occurs on a line for itselfScala offers this mixfix notation for defining DSLs, and it looks very appealing. However, one can
provide only a partial instantiation of a DSL construct and the Scala compiler will be happy. We normally accept this in the case of dot-notation (that’s how it is in Java and Python) but our expectations for some reason go higher when it starts looking like a real programming language construct, which perhaps is unreasonable.
Something to think about. Could one think of imposing “static liveness” constraints? Like: ‘this intermediate object shouldnever be the result of a statement’.
Note that this problem can be avoided if instead we define the loop-unless construct as a curried function:
def loop_unless(stmt : => Unit)(cond : => Boolean) { stmt if(!cond)loop_unless(stmt)(cond) }Then one can write:
i = 20; loop_unless { println(i) i = i - 1 } (i == 0)However, if we write:
i = 20; loop_unless { println(i) i = i - 1 }leaving out the second parameter, the compiler will complain. This approach currently seems the safest way to
5 Gennaio 2010, 12:55 amdefine DSLs in Scala.
Franco Lombardo:
Klaus,
another great comment!
5 Gennaio 2010, 11:55 pmYou say “expectations for some reason go higher when it starts looking like a real programming language construct, which perhaps is unreasonable.”
You’re right, but I think also that if you give more power you need more safety too. Scala is like a Ferrari race car: as it can run so much, I expect it has good brakes too!!!
Carlos:
Hey there!
Good comparison on both langs. I’m trying to do a comparison between JVM and CLR languages. 19 languages I’m including on that comparison including Scala and Fantom. You can have a look on my blog: http://carlosqt.blogspot.com/
The comparison goes like this: you have the same program (OO Hello World) implemented in 19 languages using exactly the same features and rules) and then compare them based on some metrics. The comparisons so far are between Keywords and Lines of code
Fantom:
http://carlosqt.blogspot.com/2010/07/oo-hello-world-fantom.html
Scala:
http://carlosqt.blogspot.com/2010/07/oo-hello-world-scala.html
Then you have:
16 Luglio 2010, 11:13 amhttp://carlosqt.blogspot.com/2010/07/how-many-keywords-do-you-type-in-your.html
and
http://carlosqt.blogspot.com/2010/07/how-many-lines-to-code-same.html