|
Is there an equivalent to a typedef in Scala for primitives? I'm
working with a bunch of different hashes that use integer keys, and didn't want one key to be used for a different hashmap than intended. Obviously, it would be the programmer's responsibility not to do that, but I was wondering if there was a way to make sure it didn't happen at compile time. For example, val nameHash = new HashMap[NameKey,String]() val countryHash = new HashMap[CountryKey,String]() ... val country = 5 : CountryKey and trying to use 'country' as an index in nameHash throws a compiler error? Josh |
|
type NameKey = Int
type CountryKey = Int val nameHash = new collection.mutable.HashMap[NameKey,String]() val name:NameKey = 5 val country:CountryKey = 6 nameHash += (4,"Hi") // Compiler error nameHash += (name,"Hello") // Works nameHash += (country,"Yo") // Compiler error --Rex On Tue, Dec 1, 2009 at 1:44 PM, Josh Stratton <[hidden email]> wrote: Is there an equivalent to a typedef in Scala for primitives? I'm |
|
No, actually, that *doesn't* work. I got confused by not having a fresh shell open.
My mistake. Those all work. (And you need ((4,"Hi")) in each case.) In that case, the shortest thing I know of is making a wrapper class (may as well make it a case class): case class NameKey(val key:Int) { override def hashCode = key } case class CountryKey(key:Int) { override def hashCode = key } val nameHash = new collection.mutable.HashMap[NameKey,String]() val name = NameKey(5) val country = CountryKey(5) nameHash += ((4,"Hi")) // Error nameHash += ((name,"Hello")) // Works nameHash += ((country,"Yo")) // Error If you want easier interoperability with integers for some reason, you can add implicit conversions: implicit def namekey2int(n:NameKey):Int = n.key implicit def int2namekey(i:Int):NameKey = NameKey(i) And keep in mind that you have to box integers in hash maps anyway (at least until @specialized goes all the way through the library), so you don't lose anything by doing your own boxing of the primitive except for a bit of typing. --Rex On Tue, Dec 1, 2009 at 2:02 PM, Rex Kerr <[hidden email]> wrote: type NameKey = Int |
|
In reply to this post by Josh Stratton
I wonder what would be the consequence of allowing to subclass AnyVal types with the restriction of only extending with traits without state. We could use it to get a bit more static validation, like what you're trying to do here, and probably other interesting uses. I haven't thought of all consequences and side effects though, has anyone thought of this ? Cheers On Tue, Dec 1, 2009 at 1:44 PM, Josh Stratton <[hidden email]> wrote: Is there an equivalent to a typedef in Scala for primitives? I'm |
|
Now that I think of it, even having the restriction of adding traits without method (to avoid an undesired side effect) would still be usefull ... 2009/12/1 Maxime Lévesque <[hidden email]>
|
|
In reply to this post by Maxime Lévesque
It approaches what the unsupported units pluging does, though not as powerful.
In that, you could basically define units and have them checked at compile and run-time:
val t = 10.0s
val d = 5.0m
val v = d / t
val error = d + t
But it seems Josh is thinking of more complex types. It could be done with subclassing:
class Complex(val r: Double, val i: Double)
class ComplexTime(_r: Double, _i: Double) extends Complex(_r, _i)
class ComplexDistance(_r: Double, _i: Double) extends Complex(_r, _i)
Now, Scala's type aliases are interesting and useful, but it is truly a shame that there isn't a typedef-like facility.
2009/12/1 Maxime Lévesque <[hidden email]>
-- Daniel C. Sobral I travel to the future all the time. |
|
> Now, Scala's type aliases are interesting and useful, but it is truly a
> shame that there isn't a typedef-like facility. understatement :-) |
|
In reply to this post by Daniel Sobral
I'm not familiar with the plugin, but it seems that allowing extending AnyVals with stateless traits would give you the same level of static validation while staying lightweight, would you agree ? If I had to pick just one feature, I'd say that value types (supported by the VM and the language) would give you all this, i.e. one could make primitive type wrappers (with implicit convs) that would be as or nearly as lightweight as Primitive types, but if that is not likely to happen anytime soon, extending AnyVals sound like a good compromize. Does it ? Cheers 2009/12/1 Daniel Sobral <[hidden email]>
|
|
Units is much more powerful. For instance, you can do this with units:
val a = v / (t * t)
That is, I end up not with distance/time, but with distance/time-squared.
There's an implementation of such a thing using Church Numbers, but it is awkward.
I think both C# and F# support units nowadays.
2009/12/1 Maxime Lévesque <[hidden email]>
-- Daniel C. Sobral I travel to the future all the time. |
|
In reply to this post by Josh Stratton
On Tue, Dec 01, 2009 at 10:44:50AM -0800, Josh Stratton said
> Is there an equivalent to a typedef in Scala for primitives? I'm > working with a bunch of different hashes that use integer keys, and > didn't want one key to be used for a different hashmap than intended. > Obviously, it would be the programmer's responsibility not to do that, > but I was wondering if there was a way to make sure it didn't happen > at compile time. It's possible but a little weird. trait Typedef[T] { type Type >: T def apply(x: T): Type = x } object Types { val Name: Typedef[Int] = new Typedef[Int] { type Type = Int } val Country: Typedef[Int] = new Typedef[Int] { type Type = Int } } import scala.collection.immutable.HashMap import Types._ val nameHash = new HashMap[Name.Type,String] val countryHash = new HashMap[Country.Type,String] val name = 5: Name.Type val country = 5: Country.Type In this setup nameHash.get(5) compiles nameHash.get(name) compiles nameHash.get(country) doesn't countryHash.get(5) compiles countryHash.get(country) compiles countryHash.get(name) doesn't There's no boxing going on as name isInstanceOf[Int] and country isInstanceOf[Int] are both true It's also possible to use Name(5) and Country(5) as equivalents for (5: Name.Type) and (5: Country.Type) respectively Of course it still would be nice if scala had something builtin along the lines of newtype in haskell. -- Geoff |
| Powered by Nabble | Edit this page |
