Very nice examples but perhaps better to lose the reference to "LSP" or make it clearer? If the next line after setting res2 is: assert(res2.isInstanceOf[BitSet]) then I don't quite get substitutable behavior if I am expecting a BitSet. LSP within certain bounds for sure but not blanket LSP.
Also, I am not sure what you mean by "100% safe". Perhaps you mean statically type-checked according to the scala type system (which is what you kind of say later in the same sentence - which I think sums it up nicely and adequately). Not trying to nit-pick. I just find type-safety to be a small subset of the potentially desirable properties of programs. I would hate someone to think that any program I wrote was "100% safe" just because it compiled or met some type systems constraints. Cheers, Paul. On Thu, Nov 24, 2011 at 7:28 PM, Kevin Wright <[email protected]> wrote: > I guess I missed the point in my (rather terse) example. > What I was demonstrating is that the expression doesn't just change the > contents of the collection, but also the type of the collection itself. For > example: > val bitSet = BitSet(1,2,3) //a BitSet can only hold integers, it subclasses > Set[Int] > val res1 = bitSet map {2*} //BitSet(2,4,6) > val res2 = bitSet map {_.toString} //Set("1","2","3") BitSets can't hold > strings, so returns a Set[String], as per the Liskov Substitution > Principle. > val myMap = Map(1 -> "x", 2 -> "y", 3 -> "z") //a Map[K,V] is also a > collection of K->V pairs > val res3 = myMap map {x => x._1.toString -> > x._2} //Map("1"->"x","2"->"y","3"->"z"), a Map[String, String] > val res4 = myMap map {case (a,b) => a.toString -> b} //more readable via > pattern matching > val res5 = myMap map {_._1} //List(1,2,3), a List[Int] > val res6 = myMap map {_._2} //List("x","y","z"), a List[String] > This is all 100% safe and statically typed, and is made possible by the > "scary" CanBuildFrom implicit parameter that Stephen mention in his article. > I don't believe that Fantom can do this, not least because it doesn't have > highly-optimised collection types such as BitSet, it doesn't consider Maps > to subclass collections of pairs, and it doesn't support creation of your > own paramaterised collection types. So far as I'm aware, Scala is the only > language in existence that directly supports such a scheme (though I imagine > it would be totally possible to duplicate using something like Lisp macros) > It looks threatening in the documentation, but when you actually use this > stuff it's really quite effortless. The best part is that these collections > are defined entirely in library code using completely standard syntax > without a single line of compiler support required. Anybody could have > implemented them without touching the compiler, and it's completely possible > to implement your own collection types that fit transparently into this > hierarchy (although you *do* have to understand the full method signatures > at that point) > 2011/11/24 Cédric Beust ♔ <[email protected]> >> >> On Wed, Nov 23, 2011 at 3:05 PM, Kevin Wright <[email protected]> >> wrote: >>> >>> They're also core to the mechanism that allows collections to just do the >>> Right Thing(tm). For example: >>> someBitSet map {_.toString} >> >> Right, but you can achieve the same result without needing implicits. I'll >> just show how Fantom does it but I'm sure the same applies to >> Gosu/Ceylon/Kotlin: >> // a set of A instances, where A has a toUppercase method >> aSet := [ A("foo"), A("bar") ] >> l := aSet.map | v->Str | { v.toUppercase } >> echo(l) >> echo(l.typeof) >> [FOO, BAR] >> sys::Str[] >> The signature of map() is exactly what you would expect: it takes a >> function that takes an element of the collection and returns "something", >> and the type of your expression is "list of something" (here we transformed >> a list of A's into a list of strings). >> It's really not rocket science, and the fact that you need implicits to >> achieve this result is an implementation detail that's very specific to >> Scala. >> Sure, you can handwave it with "You don't need to understand the exact >> details of the API", but the truth is... you really do. Not a week goes by >> without me having to go check out a Javadoc or the signature of java.util or >> Guava method. And saying that only library authors need to know about >> implicits, CanBuildFrom and its triple generic signature is creating a rift >> between the Scala developers (people who know and people who don't), which >> is worrisome. > > -- > You received this message because you are subscribed to the Google Groups > "The Java Posse" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/javaposse?hl=en. > -- You received this message because you are subscribed to the Google Groups "The Java Posse" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
