Values 

Abstract value declarations 

Abstract value declarations are written by wrapping the name and the type with VAL(...):

scala> import treehugger.forest._, definitions._, treehuggerDSL._
import treehugger.forest._
import definitions._
import treehuggerDSL._

scala> val tree = (VAL("foo", IntClass): Tree)
[1m[34mtree[0m: [1m[32mtreehugger.forest.Tree[0m = ValDef(Modifiers(, , Map()),Typed(Ident(foo),TypeTree()),EmptyTree)

scala> treeToString(tree)
[1m[34mres0[0m: [1m[32mString[0m = val foo: Int

or in general:

VAL(sym|"x", typ|"C").tree

where sym is a symbol and typ is a type of the value. In the above code, sym|"x" denotes that either a symbol or String is accepted as the name of the value, and type|"C" denotes that either a type or String is accepted as the type of the value.

Calling tree method creates a Tree without a right-hand side (rhs) expression. Because there’s an implicit conversion, forcing VAL(...) as a Tree automatically calls tree method.

Value definitions 

Value definitions are written by appending right-hand side tree after := as follows:

scala> val tree2 = VAL("foo", IntClass) := LIT(0)
[1m[34mtree2[0m: [1m[32mtreehugger.forest.ValDef[0m = ValDef(Modifiers(, , Map()),Typed(Ident(foo),TypeTree()),Literal(Constant(0)))

scala> treeToString(tree2)
[1m[34mres1[0m: [1m[32mString[0m = val foo: Int = 0

Like Scala, the type annotation can be omitted when rhs is provided:

scala> val tree3 = VAL("foo") := LIT(0)
[1m[34mtree3[0m: [1m[32mtreehugger.forest.ValDef[0m = ValDef(Modifiers(, , Map()),Ident(foo),Literal(Constant(0)))

scala> treeToString(tree3)
[1m[34mres2[0m: [1m[32mString[0m = val foo = 0

In addition, a symbol could be used to define a value instead of using String names.

scala> object sym {
  val foo = RootClass.newValue("foo")
}
defined object sym

scala> val tree4 = VAL(sym.foo) := LIT(0)
[1m[34mtree4[0m: [1m[32mtreehugger.forest.ValDef[0m = ValDef(Modifiers(, , Map()),Ident(foo),Literal(Constant(0)))

scala> treeToString(tree4)
[1m[34mres3[0m: [1m[32mString[0m = val foo = 0

For a larger code base, using symbols makes the code more readable.

The general form of constant value definitions are:

VAL(sym|"x", [typ]) := rhs

Lazy values 

Lazy value declarations are written using LAZYVAL(...):

scala> val tree5 = (LAZYVAL("foo", IntClass): Tree)
[1m[34mtree5[0m: [1m[32mtreehugger.forest.Tree[0m = ValDef(Modifiers(lazy, , Map()),Typed(Ident(foo),TypeTree()),EmptyTree)

scala> treeToString(tree5)
[1m[34mres4[0m: [1m[32mString[0m = lazy val foo: Int

and lazy value definitions are written as:

scala> val tree6 = LAZYVAL("foo", IntClass) := LIT(0)
[1m[34mtree6[0m: [1m[32mtreehugger.forest.ValDef[0m = ValDef(Modifiers(lazy, , Map()),Typed(Ident(foo),TypeTree()),Literal(Constant(0)))

scala> treeToString(tree6)
[1m[34mres5[0m: [1m[32mString[0m = lazy val foo: Int = 0

Final values 

Final value definitions are written by appending withFlags(...) after VAL(...):

scala> val tree7 = VAL("foo", IntClass) withFlags(Flags.FINAL) := LIT(0)
[1m[34mtree7[0m: [1m[32mtreehugger.forest.ValDef[0m = ValDef(Modifiers(final, , Map()),Typed(Ident(foo),TypeTree()),Literal(Constant(0)))

scala> treeToString(tree7)
[1m[34mres6[0m: [1m[32mString[0m = final val foo: Int = 0

Pattern values 

There is another form of value definitions called pattern values, but it will be discussed later.