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)
tree: treehugger.forest.Tree = ValDef(Modifiers(, , Map()),Typed(Ident(foo),TypeTree()),EmptyTree)

scala> treeToString(tree)
res0: String = 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)
tree2: treehugger.forest.ValDef = ValDef(Modifiers(, , Map()),Typed(Ident(foo),TypeTree()),Literal(Constant(0)))

scala> treeToString(tree2)
res1: String = val foo: Int = 0

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

scala> val tree3 = VAL("foo") := LIT(0)
tree3: treehugger.forest.ValDef = ValDef(Modifiers(, , Map()),Ident(foo),Literal(Constant(0)))

scala> treeToString(tree3)
res2: String = 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 module sym

scala> val tree4 = VAL( := LIT(0)
tree4: treehugger.forest.ValDef = ValDef(Modifiers(, , Map()),Ident(foo),Literal(Constant(0)))

scala> treeToString(tree4)
res3: String = 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)
tree5: treehugger.forest.Tree = ValDef(Modifiers(lazy, , Map()),Typed(Ident(foo),TypeTree()),EmptyTree)

scala> treeToString(tree5)
res4: String = lazy val foo: Int

and lazy value definitions are written as:

scala> val tree6 = LAZYVAL("foo", IntClass) := LIT(0)
tree6: treehugger.forest.ValDef = ValDef(Modifiers(lazy, , Map()),Typed(Ident(foo),TypeTree()),Literal(Constant(0)))

scala> treeToString(tree6)
res5: String = 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)
tree7: treehugger.forest.ValDef = ValDef(Modifiers(final, , Map()),Typed(Ident(foo),TypeTree()),Literal(Constant(0)))

scala> treeToString(tree7)
res6: String = final val foo: Int = 0

Pattern values 

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