Scalite
An experimental whitespace-delimited syntax for the Scala programming language
Install / Use
/learn @lihaoyi/ScaliteREADME
Scalite
package scalite.tutorial package scalite.tutorial
class Point(xc: Int, yc: Int) class Point(xc: Int, yc: Int) {
var x: Int = xc var x: Int = xc
var y: Int = yc var y: Int = yc
def move(dx: Int, dy: Int) = def move(dx: Int, dy: Int) = {
x = x + dx x = x + dx
y = y + dy y = y + dy
}
override def toString() = override def toString() = {
"(" + x + ", " + y + ")" "(" + x + ", " + y + ")"
}
}
object Run object Run {
def apply() = def apply() = {
val pt = new Point(1, 2) val pt = new Point(1, 2)
println(pt) println(pt)
pt.move(10, 10) pt.move(10, 10)
pt.x pt.x
}
}
Scalite is an experimental whitespace-delimited syntax for the scala programming language. This lets you delimit block scope using indentation rather than curly braces, reducing the amount of unnecessary curly braces within the source code. This is an important step in view of the great curly-brace shortage of 2007.
You can use Scalite in your own projects via
// project/build.sbt
addSbtPlugin("com.lihaoyi" % "scalite-sbt-plugin" % "0.1.0")
// build.sbt
scalite.SbtPlugin.projectSettings
scalaVersion := "2.11.4"
This will cause any .scalite files in your src/main/scalite and src/test/scalite folders to be picked up by the Scalite compiler plugin automatically. Your .scalite files can interop perfectly with existing .scala code, e.g. calling back and forth. Error reporting, incremental compilation, and all that should work great. Note that Scalite only works with Scala 2.11.x.
Syntax
Scalite blocks are delimited by indentation rather than curly braces. Thus in the following code,
val x = val x = {
val y = 1 val y = 1
val z = 2 val z = 2
y + z y + z
}
var a = var a = {
1 + 2 + 3 1 + 2 + 3
}
def apply() = def apply() = {
x + a x + a
// 9 // 9
}
y and z are local variables only scoped to the definition of x, and not visible outside it. The same rule applies for for loops, if/else/while/do/try blocks. Here's some samples from the unit tests:
For loops
var x = 0 var x = 0
for(i <- 0 until 10) for(i <- 0 until 10) {
val j = i * 2 val j = i * 2
val k = j + 1 val k = j + 1
x += k x += k
}
val list = val list = {
for(i <- 0 to x) yield for(i <- 0 to x) yield {
val j = i + 1 val j = i + 1
i * j i * j
}
}
list.max list.max
// 10100 // 10100
Multi-line for- and for-yield blocks work too:
val all = for val all = for {
x <- 0 to 10 x <- 0 to 10
y <- 0 to 10 y <- 0 to 10
if x + y == 10 if x + y == 10
yield } yield {
val z = x * y val z = x * y
z z
}
all.max all.max
// 25 // 25
While/If/Else
var x = 0 var x = 0
var y = 0 var y = 0
while (x < 10) while (x < 10) {
if (x % 2 == 0) if (x % 2 == 0) {
x = x + 1 x = x + 1
y += x y += x
else } else {
x = x + 2 x = x + 2
y += x y += x
}
}
y y
// 36 // 36
Top-level definitions
case object ObjectCase case object ObjectCase {
val w = 1 val w = 1
}
object ObjectLol object ObjectLol {
val x = 100 val x = 100
}
trait MyTrait trait MyTrait {
val y = 10 val y = 10
}
class TopLevel extends MyTrait class TopLevel extends MyTrait {
def apply(): String = def apply(): String = {
val z = 1 val z = 1
import ObjectLol._ import ObjectLol._
import ObjectCase._ import ObjectCase._
"Hello World!" + (a + w + x + y + z) "Hello World!" + (a + w + x + y + z)
// Hello World!113 // Hello World!113
}
val a = 1 val a = 1
}
Match blocks
Match blocks are similarly indentation delimited, but with a twist: since there isn't any ambiguity between more case clauses and statements outside the match block, Scalite does not require you to indent the case clauses, saving you one level of indentation:
val z = (1 + 1) match val z = 1 match {
case 1 => case 1 =>
println("One!") println("One!")
"1" "1"
case 2 => "2" case 2 => "2"
}
z z
// "2" // "2"
The same applies to the catch block of a try-catch expression:
try try {
println("Trying...") println("Trying...")
x.toString x.toString
catch } catch {
case n: NullPointerException => case n: NullPointerException =>
println("Dammit") println("Dammit")
"null" "null"
}
Light syntax
In addition to indentation-scoped blocks, for/if/while blocks also support a paren-less syntax if the generators of the for or the conditional of the if or while fit on a single line:
var x = 0 var x = 0
for i <- 0 until 10 for (i <- 0 until 10) {
val j = i * 2 val j = i * 2
val k = j + 1
