Skip to content

Instantly share code, notes, and snippets.

@milessabin
Created May 9, 2014 10:11
Show Gist options
  • Save milessabin/c51b6851548dae403abf to your computer and use it in GitHub Desktop.
Save milessabin/c51b6851548dae403abf to your computer and use it in GitHub Desktop.
Type safe selectDynamic without macros
miles@frege:~$ scala
Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_55).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.language.dynamics
import scala.language.dynamics
scala> case class Assoc[K, V](value: V)
defined class Assoc
scala> def mkAssoc[V](key: String)(value: V) = Assoc[key.type, V](value)
mkAssoc: [V](key: String)(value: V)Assoc[key.type,V]
scala> implicit def fooAssoc = mkAssoc("foo")(true)
fooAssoc: Assoc[String("foo"),Boolean]
scala> implicit def barAssoc = mkAssoc("bar")(23)
barAssoc: Assoc[String("bar"),Int]
scala> object SafeDynamic extends Dynamic {
| def selectDynamic[V](key: String)(implicit assoc: Assoc[key.type, V]): V = assoc.value
| }
defined object SafeDynamic
scala> SafeDynamic.foo
res0: Boolean = true
scala> SafeDynamic.bar
res1: Int = 23
scala> SafeDynamic.baz
<console>:15: error: could not find implicit value for parameter assoc: Assoc[String("baz"),V]
SafeDynamic.baz
^
@fancellu
Copy link

fancellu commented Jun 9, 2014

This is magic. In previous times you'd be burned as a witch.

@Jasper-M
Copy link

Now is there a way to make the combination of updateDynamic and selectDynamic type safe, so that the following would be possible?

scala> case class Foo[T](value: T)
defined class Foo

scala> SafeDynamic.foo = Foo("foo")
SafeDynamic.foo: Foo[String] = Foo(foo)

scala> SafeDynamic.bar = Foo(3)
SafeDynamic.bar: Foo[Int] = Foo(3)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment