package sbt /** Define our settings system */ // A basic scope indexed by an integer. final case class Scope(index: Int) // Extend the Init trait. // (It is done this way because the Scope type parameter is used everywhere in Init. // Lots of type constructors would become binary, which as you may know requires lots of type lambdas // when you want a type function with only one parameter. // That would be a general pain.) object SettingsExample extends Init[Scope] { // Provides a way of showing a Scope+AttributeKey[_] val showFullKey: Show[ScopedKey[_]] = new Show[ScopedKey[_]] { def apply(key: ScopedKey[_]) = key.scope.index + "/" + key.key.label } // A sample delegation function that delegates to a Scope with a lower index. val delegates: Scope => Seq[Scope] = { case s @ Scope(index) => s +: (if(index <= 0) Nil else delegates(Scope(index-1)) ) } // Not using this feature in this example. val scopeLocal: ScopeLocal = _ => Nil // These three functions + a scope (here, Scope) are sufficient for defining our settings system. } /** Usage Example **/ object SettingsUsage { import SettingsExample._ import Types._ // Define some keys val a = AttributeKey[Int]("a") val b = AttributeKey[Int]("b") // Scope these keys val a3 = ScopedKey(Scope(3), a) val a4 = ScopedKey(Scope(4), a) val a5 = ScopedKey(Scope(5), a) val b4 = ScopedKey(Scope(4), b) // Define some settings val mySettings: Seq[Setting[_]] = Seq( setting( a3, value( 3 ) ), setting( b4, map(a4)(_ * 3)), update(a5)(_ + 1) ) // "compiles" and applies the settings. // This can be split into multiple steps to access intermediate results if desired. // The 'inspect' command operates on the output of 'compile', for example. val applied: Settings[Scope] = make(mySettings)(delegates, scopeLocal, showFullKey) // Show results. /* for(i <- 0 to 5; k <- Seq(a, b)) { println( k.label + i + " = " + applied.get( Scope(i), k) ) }*/ /** Output: * For the None results, we never defined the value and there was no value to delegate to. * For a3, we explicitly defined it to be 3. * a4 wasn't defined, so it delegates to a3 according to our delegates function. * b4 gets the value for a4 (which delegates to a3, so it is 3) and multiplies by 3 * a5 is defined as the previous value of a5 + 1 and * since no previous value of a5 was defined, it delegates to a4, resulting in 3+1=4. * b5 isn't defined explicitly, so it delegates to b4 and is therefore equal to 9 as well a0 = None b0 = None a1 = None b1 = None a2 = None b2 = None a3 = Some(3) b3 = None a4 = Some(3) b4 = Some(9) a5 = Some(4) b5 = Some(9) **/ }