--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+unsubscribe@googlegroups.com.
Simon,This is interesting (not that I disagree); can you elaborate? I've been always debating whether to use them.
Thanks,
-Vlad
On Sat, Sep 7, 2013 at 5:35 PM, Simon Schäfer <ma...@antoras.de> wrote:
Maybe because views are crap. Use Stream or Iterator instead.
On 09/08/2013 01:06 AM, Eric Tanter wrote:
2) But more simply: why isn't `force' defined on all sequences, assuming it does nothing (evaluates to `this') in all strict sequences?
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
I decided to stop wasting my effort on scala, that's what happened. Views are yet another fine example of why I'm moving on.
FWIW, I think Java 8's Streams, which are essentially the same as our views [...] it looks like they will actually deliver working stream fusion in a few months.
intended for the same kinds of use cases.
Thats a bug, IMO, and shows that you can't fuse operations for sets in general.
In any case, the java.util.stream package summary is pretty good, and shows (to me at least) that they're intended for the same kinds of use cases.
I'm sure that's been proposed multiple times over the years. It would be good if now is the time it finally happens, given recent pushes towards cleaning up Tech debt.
Speaking as someone who was playing with Scala+android+proguard before it was even considered possible, I can also testify that this would clean out a *lot* of classloading baggage as well. What's not to like?
> -jason
As a side note, "map" shouldn't even exist on sets. It is a never-ending parade of invisible bugs. It should be an invariant of "map" that you get the same number of things out that you put in. If someone wanted some funky maplike thing which may or may not make pieces of the resulting collection vanish into the ether, they should call it funkyMap or setMap or something. Leave poor map alone.
On Mon, Sep 9, 2013 at 2:59 PM, Jason Zaugg <jza...@gmail.com> wrote:
Thats a bug, IMO, and shows that you can't fuse operations for sets in general.
On 9 Sep 2013 23:18, "Paul Phillips" <pa...@improving.org> wrote:
>
>
> On Mon, Sep 9, 2013 at 2:59 PM, Jason Zaugg <jza...@gmail.com> wrote:
>>
>> Thats a bug, IMO, and shows that you can't fuse operations for sets in general.
>
>
> As a side note, "map" shouldn't even exist on sets. It is a never-ending parade of invisible bugs. It should be an invariant of "map" that you get the same number of things out that you put in. If someone wanted some funky maplike thing which may or may not make pieces of the resulting collection vanish into the ether, they should call it funkyMap or setMap or something. Leave poor map alone.
>
The same can also be said of the Map type (& derivatives). So this particular rabbit hole goes a whole lot deeper...
> I will always fondly remember the bug where Set's hashCode was calculated something like
>
> xs.map(_.##).sum
>
> Hey, where are my sets disappearing to, sometimes?
>
I've logged many an hour tracking down nasty bugs that stemmed from the highly related:scala> List(1 -> 2, 1 -> 3).toMapres16: scala.collection.immutable.Map[Int,Int] = Map(1 -> 3)
No, but it might be a reuse case
On Mon, Sep 9, 2013 at 11:33 PM, Alex Cruise <al...@cluonflux.com> wrote:
On Mon, Sep 9, 2013 at 12:02 PM, Paul Phillips <pa...@improving.org> wrote:
On Mon, Sep 9, 2013 at 11:43 AM, Alex Cruise <al...@cluonflux.com> wrote:
FWIW, I think Java 8's Streams, which are essentially the same as our views [...] it looks like they will actually deliver working stream fusion in a few months.What is your vantage such that they appear essentially the same? Are you Felix Baumgartner?Just to make sure we're on the same sportsmetaphor, I'm talking about JDK8's java.util.stream.Stream, not java.io.{Input,Output}Stream. :)For me at least, the main purpose of views is that they let you apply a chain of map/filter/flatMap/etc. without having to build intermediate collections that will be instant garbage. If there's some other reason to use Scala views, I'd love to hear it. In any case, the java.util.stream package summary is pretty good, and shows (to me at least) that they're intended for the same kinds of use cases.What we've done a really bad job at documenting is that fusing those sort of operations together can be done with much less fragile machinery via `xs.iterator.map(f).map(g).toList`.Views try to capture a richer set of operations, so `xs.view.drop(1).reverse` captures those operations until `force` or `toList` is called. The intermediate data structures are pretty hairy.Furthermore, it's hard to reason about what properties of the original collection should be preserved through the view.Compare:scala> var x = 0x: Int = 0scala> Set(1, 2).map(x => 1).map(_ => {x += 1; x})res14: scala.collection.immutable.Set[Int] = Set(1)With:scala> var x = 0x: Int = 0scala> Set(1, 2).view.map(x => 1).map(_ => {x += 1; x}).forceres15: Iterable[Int] = Set(1, 2)Thats a bug, IMO, and shows that you can't fuse operations for sets in general. (You can if you know the functions satisfy `f(x) == f(y) if x == y`). So making people convert to an iterator (or stream, or java.Stream) is actually a good means to be explicit about what sort of collection properties you have during the intermediate steps.
The best way forward for views would be:1) people using them try converting to `.iterator` where possible2) where not possible, let us know what your use case is3) accomodate those use cases in a new, simpler view library4) we deprecate the views in the collections, pointing people to said new library, and possibly distributing it as a module of Scala.
-jason
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
On Tue, Sep 10, 2013 at 12:18 AM, Paul Phillips <pa...@improving.org> wrote:
As a side note, "map" shouldn't even exist on sets. It is a never-ending parade of invisible bugs. It should be an invariant of "map" that you get the same number of things out that you put in. If someone wanted some funky maplike thing which may or may not make pieces of the resulting collection vanish into the ether, they should call it funkyMap or setMap or something. Leave poor map alone.On Mon, Sep 9, 2013 at 2:59 PM, Jason Zaugg <jza...@gmail.com> wrote:
Thats a bug, IMO, and shows that you can't fuse operations for sets in general.I will always fondly remember the bug where Set's hashCode was calculated something likexs.map(_.##).sumHey, where are my sets disappearing to, sometimes?I disagree completely. There's nothing more natural than mapping a function over a set. If you want to maintain same length you need a multi-set, not a set. One could argue that it would be nice to have better support for multi-sets in the Scala library. But arguing that map should not exist on sets is ... weird.
On Tue, Sep 10, 2013 at 10:18 AM, martin odersky <martin....@epfl.ch> wrote:
On Tue, Sep 10, 2013 at 12:18 AM, Paul Phillips <pa...@improving.org> wrote:
As a side note, "map" shouldn't even exist on sets. It is a never-ending parade of invisible bugs. It should be an invariant of "map" that you get the same number of things out that you put in. If someone wanted some funky maplike thing which may or may not make pieces of the resulting collection vanish into the ether, they should call it funkyMap or setMap or something. Leave poor map alone.On Mon, Sep 9, 2013 at 2:59 PM, Jason Zaugg <jza...@gmail.com> wrote:
Thats a bug, IMO, and shows that you can't fuse operations for sets in general.I will always fondly remember the bug where Set's hashCode was calculated something likexs.map(_.##).sumHey, where are my sets disappearing to, sometimes?I disagree completely. There's nothing more natural than mapping a function over a set. If you want to maintain same length you need a multi-set, not a set. One could argue that it would be nice to have better support for multi-sets in the Scala library. But arguing that map should not exist on sets is ... weird.In practice it isn't weird at all and fits into this thread perfectly. There are those little things in the Scala collections library where you even after years cannot say with confidence why a certain operation has a certain effect. Of course, the above semantic of mapping over Maps or Sets is one possible solution. That's not the problem. The problem is that there's at least one other perfectly reasonable outcome which would be an intuitively correct choice in some cases. However, when using map you cannot confidently predict which one is chosen because there's no high-level rule to apply that would work in all cases. To be sure you then resort be being explicit about what you expect which is often made harder than necessary because you suddenly have to understand all of the CanBuildFrom typing rules and logic at once to make the choice.
Here, the difference with Java is clear: in Java, if you want to take
advantage of functionnal programmation on collection (and of course, you
do - hell, it's one of the best selling point for Scala), you will have
to use lazy structure, no alternative. So bugs will be find and ironned,
eventually.
To sum up: view are buggy because lazy structure are hard, they are not
well tested because alternative (standard collection) are better and
less risky.
I don't see what would make it change without massive political
implication of Scala product owner (well, the team choosing what Scala
should look like in the futur).
Cheers,
--
Francois ARMAND
http://rudder-project.org
http://www.normation.com
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Going to iterators instead of views does not always work. For instance, consider, on an indexed seq:xs.view.slice(x, y).map(f)You can doxs.iterator.slice(x, y).map(f)
but then slice takes linear instead of constant time.
Note that this is the exact opposite of what Java 8 is doing. Java 8 makes collections lazy (views) by default. We seem to say that we only want strict collections. Can someone clarify the reasons why strict collections are better for Scala whereas lazy ones are better for Java? If anything, laziness plays badly with state (as you showed above), so that should make views more attractive for a more functional oriented language like Scala than a more imperative one like Java.
On Tue, Sep 10, 2013 at 11:44 AM, Johannes Rudolph <johannes...@googlemail.com> wrote:
On Tue, Sep 10, 2013 at 10:18 AM, martin odersky <martin....@epfl.ch> wrote:
On Tue, Sep 10, 2013 at 12:18 AM, Paul Phillips <pa...@improving.org> wrote:
As a side note, "map" shouldn't even exist on sets. It is a never-ending parade of invisible bugs. It should be an invariant of "map" that you get the same number of things out that you put in. If someone wanted some funky maplike thing which may or may not make pieces of the resulting collection vanish into the ether, they should call it funkyMap or setMap or something. Leave poor map alone.On Mon, Sep 9, 2013 at 2:59 PM, Jason Zaugg <jza...@gmail.com> wrote:
Thats a bug, IMO, and shows that you can't fuse operations for sets in general.I will always fondly remember the bug where Set's hashCode was calculated something likexs.map(_.##).sumHey, where are my sets disappearing to, sometimes?I disagree completely. There's nothing more natural than mapping a function over a set. If you want to maintain same length you need a multi-set, not a set. One could argue that it would be nice to have better support for multi-sets in the Scala library. But arguing that map should not exist on sets is ... weird.In practice it isn't weird at all and fits into this thread perfectly. There are those little things in the Scala collections library where you even after years cannot say with confidence why a certain operation has a certain effect. Of course, the above semantic of mapping over Maps or Sets is one possible solution. That's not the problem. The problem is that there's at least one other perfectly reasonable outcome which would be an intuitively correct choice in some cases. However, when using map you cannot confidently predict which one is chosen because there's no high-level rule to apply that would work in all cases. To be sure you then resort be being explicit about what you expect which is often made harder than necessary because you suddenly have to understand all of the CanBuildFrom typing rules and logic at once to make the choice.Just to be clear: If we pick the other "reasonable outcome", then
On Tue, Sep 10, 2013 at 11:27 AM, Francois <fan...@gmail.com> wrote:
On 10/09/2013 10:16, martin odersky wrote:
[...]
So, perhaps if ALL scala collection were lazy, with ALL user forced to
use them, and ALL bug on lazy collection being a bug in Scala collection
with no alternative, that would work. But with the actuall state of
things, I don't see who would pay for the price of using view (either
user or Scala developer). Even less if iterators allow to manage most of
the use cases with much less risks.
I agree that views do present more pitfalls to get things wrong - that's the price you pay for reducing storage requirements. And I also agree that this creates a vicious circle of under-use and under-maintenance.
But now that Java 8 comes out, the large majority of programmers will expect views as the standard because that's what they know from Java 8. So I expect that vicious cycle to be broken if we decide to fix views rather than abolish them.
Cheers
- Martin
On Tue, Sep 10, 2013 at 10:16 AM, martin odersky <martin....@epfl.ch> wrote:
Going to iterators instead of views does not always work. For instance, consider, on an indexed seq:xs.view.slice(x, y).map(f)You can doxs.iterator.slice(x, y).map(f)but then slice takes linear instead of constant time.Why? If an iterator made from IndexedSeq offers a slice method why shouldn't you expect it to run in constant time ? Actually, from looking at scaladoc, `Iterator.slice` is defined in terms of drop/take which make no such claim. For me this discussion is a sign that we are still missing some guidelines about how subtyping (and dynamic dispatch) and adhoc polymorphism would play together in a way that is obvious enough that you aren't surprised in so many cases.
I don't know if you are suggesting to make collection lazy by default but that's something I would agree to in general. Maybe it would mean that you cannot specify the evaluation mode for many of those methods but for those ones which always force the collection but maybe that would be more honest than the current way where strict and lazily evaluated collections share the same types but different expectations.
I am not suggesting we make all collections lazy. What I am suggesting is that we keep and improve the general idea of views (maybe along the lines of reducers in Clojure). Dropping views in favor of iterators is a major step backwards.
There is also the question of migration. If we have both strict and lazy variants working, why would anyone pick strict (and why are they more convenient to use) ?
On Tue, Sep 10, 2013 at 2:21 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
I am not suggesting we make all collections lazy. What I am suggesting is that we keep and improve the general idea of views (maybe along the lines of reducers in Clojure). Dropping views in favor of iterators is a major step backwards.
I would prefer that too, but I'm skeptical whether it's possible to a) fix views and b) to be competitive in performance compared to Java 8's Streams.
There is also the question of migration. If we have both strict and lazy variants working, why would anyone pick strict (and why are they more convenient to use) ?
I believe it has to do with the fact that evaluation of function arguments is more predictable for strict collections. Laziness requires a lot of discipline in a language with side effects.
That's why in Scala strictness is the default, whether for variables or for collections. But I believe laziness has its place as well. At the very least we need it when interoperating with Java 8 collections.Cheers- Martin
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
f
to each element of this iterable collection and collecting the results." It doesn't give any indication about how it is "collecting the results" but there's nothing that would make me expect that collection is done in a way which only collects distinct elements.That
which contains all elements of this iterable collection followed by all elements of that
.". Here, the question is what "followed by" means. Evidence from what Set.++ implements, the definition of "followed by" becomes pretty much useless because it could mean anything based on the concrete subclass of Iterable.--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
When I read "Iterable", I understand "able to be iterated over", and that's what Set definitely is.
And you don't need to take a journey into Monadland to understand what Iterable.map does: apply function to all members and add results to new collection of same collection semantics.
There are also plenty of uses for Iterable.map that work for Sets as well as for Lists, etc:def printThemAll(c : Iterable) = c.map(println(_))
def wrapThemAll(c : Iterable) = c.map(wrap(_))
And even disallow Set.map, you still may be burned by making "intuitive" assumptions:
scala> val whoShuffledMySet = Set(1, 2, 3, 4, 5, 6, 7)
whoShuffledMySet: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)
scala> val whyDoesMySetNotGrow = (Set(0) ++ List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).map(_/10)).size
whyDoesMySetNotGrow: Int = 1
Best,Oliver
There are also plenty of uses for Iterable.map that work for Sets as well as for Lists, etc:
def wrapThemAll(c : Iterable) = c.map(wrap(_))
When I read "Iterable", I understand "able to be iterated over", and that's what Set definitely is.
And you don't need to take a journey into Monadland to understand what Iterable.map does: apply function to all members and add results to new collection of same collection semantics.
There are also plenty of uses for Iterable.map that work for Sets as well as for Lists, etc:def printThemAll(c : Iterable) = c.map(println(_))
def wrapThemAll(c : Iterable) = c.map(wrap(_))And even disallow Set.map, you still may be burned by making "intuitive" assumptions:
scala> val whoShuffledMySet = Set(1, 2, 3, 4, 5, 6, 7)
whoShuffledMySet: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)Sets are unordered, by definition. This is only unintuitive if you don't know what a set is.It's about as unintuitive as wondering why your skateboard doesn't have a handle, after assuming it was a kind of scooter with 4 wheels.
scala> val whyDoesMySetNotGrow = (Set(0) ++ List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).map(_/10)).size
whyDoesMySetNotGrow: Int = 1This isn't disallowing map, this is emphatically *using* map, and demonstrates the exact point that PaulP already made!
On Tue, Sep 10, 2013 at 5:16 PM, Oliver Ruebenacker <cur...@gmail.com> wrote:
There are also plenty of uses for Iterable.map that work for Sets as well as for Lists, etc:
def wrapThemAll(c : Iterable) = c.map(wrap(_))How do you know it "works" for all of them (especially for "etc")? If Set.map's implementation is allowed why not other possible subtypes of Iterable where `wrapThemAll` suddenly doesn't work* any more? Like a collection that only contains elements where element.toString is less than 5 characters long with `map` implemented similar to Set.map. Sounds unreasonable but in lack of a specification of what to expect from Iterable's methods you can't make any assumptions. So, how would you program against Iterable?(I'm just trying to put the finger on what it is that makes Set's behavior as surprising as it is)
But it's somewhat hard to argue that the current implementation of map on sets does the right thing. One can certainly construct (admittedly contrived) examples where it doesn't obey the functor laws, for example:import org.scalacheck.Prop.forAllcase class BreaksIt(a:Int)(val b:Int)val f: Int => BreaksIt = i => BreaksIt(0)(i)val g: BreaksIt => Int = b => b.bcheck(forAll((s:Set[Int]) => (s map f map g) == (s map (f andThen g))))
On Tue, Sep 10, 2013 at 4:10 PM, Alec Zorab <alec...@gmail.com> wrote:
But it's somewhat hard to argue that the current implementation of map on sets does the right thing. One can certainly construct (admittedly contrived) examples where it doesn't obey the functor laws, for example:import org.scalacheck.Prop.forAllcase class BreaksIt(a:Int)(val b:Int)val f: Int => BreaksIt = i => BreaksIt(0)(i)val g: BreaksIt => Int = b => b.bcheck(forAll((s:Set[Int]) => (s map f map g) == (s map (f andThen g))))I don't think it's that hard to argue that Set does the right thing.
When I read "Iterable", I understand "able to be iterated over", and that's what Set definitely is.
And you don't need to take a journey into Monadland to understand what Iterable.map does: apply function to all members and add results to new collection of same collection semantics.
There are also plenty of uses for Iterable.map that work for Sets as well as for Lists, etc:def printThemAll(c : Iterable) = c.map(println(_))
def wrapThemAll(c : Iterable) = c.map(wrap(_))And even disallow Set.map, you still may be burned by making "intuitive" assumptions:
scala> val whoShuffledMySet = Set(1, 2, 3, 4, 5, 6, 7)
whoShuffledMySet: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 4)Sets are unordered, by definition. This is only unintuitive if you don't know what a set is.It's about as unintuitive as wondering why your skateboard doesn't have a handle, after assuming it was a kind of scooter with 4 wheels.That's exactly my point regarding Set.map.
scala> val whyDoesMySetNotGrow = (Set(0) ++ List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9).map(_/10)).size
whyDoesMySetNotGrow: Int = 1This isn't disallowing map, this is emphatically *using* map, and demonstrates the exact point that PaulP already made!This is using List.map, not Set.map.
I'm not sure what point of PaulP is demonstrated.
Best,Oliver--Be always grateful, but never satisfied.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
On Tue, Sep 10, 2013 at 6:17 PM, martin odersky <martin....@epfl.ch> wrote:
On Tue, Sep 10, 2013 at 4:10 PM, Alec Zorab <alec...@gmail.com> wrote:
But it's somewhat hard to argue that the current implementation of map on sets does the right thing. One can certainly construct (admittedly contrived) examples where it doesn't obey the functor laws, for example:import org.scalacheck.Prop.forAllcase class BreaksIt(a:Int)(val b:Int)val f: Int => BreaksIt = i => BreaksIt(0)(i)val g: BreaksIt => Int = b => b.bcheck(forAll((s:Set[Int]) => (s map f map g) == (s map (f andThen g))))I don't think it's that hard to argue that Set does the right thing.I agree that there's little choice about what Set's canonical monad is (when seeing Set in isolation). What I've not yet seen is convincing evidence that the current behavior is the most useful. You mentioned ScalaQuery and random number generators. Is there anywhere more information about those use cases? You can find a bit when googling for 'set monad', e.g. [1, 2], but I don't find those particularly convincing. I mean you can hardly argue against "In other cases, with many duplicates, the Set monad is exponentially worthwhile." [2], but is this really the way you use Sets commonly?
On Thu, Sep 12, 2013 at 7:05 AM, Jason Zaugg <jza...@gmail.com> wrote:I don't know whether this is true, but I will say in practice that you
> The bottom line is that you can treat List as a Monad, or even Set if used
> in isolation with functions that pure wrt element equality, but you can't do
> the same in general for Iterable.
don't want to use quite a lot of the methods currently available on
Iterable. Iterable is so far up the hierarchy that you don't know what
any of them will do.
Some examples are ++ and map, where you probably want to know if you
are dealing with a set.
Other examples would be tail, take, and init.
You are better off converting to a concrete type and *then* calling
these methods. It won't be any slower, because as far as you know,
they will iterate the whole collection anyway.
I use a lot more concrete collection types than when I first started
> In practice, I tend to convert to a concrete collection and operate on that.
writing some Scala examples on "nsc", the new and shiny self-hosted
Scala compiler. It's a good instinct to abstract to more general
types, but in the case of collections, you often really want to know
what the underlying type is. The "Iterable" type should only be used
if really all you want to do is iterate. If you want to create new
collections, you at least want to know if you are dealing with a Seq
or a Set, because they will behave differently. If you are dealing
with a Seq, you frequently want to know if it's a List or an Array or
a Vector. If you need to know something, then abstracting it away was
wrong to begin with.
Lex
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Agreed. As a user, I also often prefer the more concrete type over the abstract one. But as a library designer you want to make the abstract type available for those algorithms that are abstract in nature. I don't believe in crippling functionality because someone might be confused or might be taken to misuse it.
PS: even in the corner of the collection hierarchy that Sets inhabit, an upcast can show surprises. The polymorphic `newBuilder` mechanism steps in and spits out a Set, but we've switched from the provided ordering to universal equality.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
We need a concrete library to experiment with and to answer this question.
PS: even in the corner of the collection hierarchy that Sets inhabit, an upcast can show surprises. The polymorphic `newBuilder` mechanism steps in and spits out a Set, but we've switched from the provided ordering to universal equality.This is why I gave up trying implementing a UserDefinedSet collection, integrated in the current collection hierarchy, where the user can provide an equality function. One reason why this might not be possible is that Set is not a Functor, but that goes back to the previous discussion...
On Thu, Sep 12, 2013 at 3:19 PM, Lex Spoon <l...@lexspoon.org> wrote:
On Thu, Sep 12, 2013 at 7:05 AM, Jason Zaugg <jza...@gmail.com> wrote:I don't know whether this is true, but I will say in practice that you
> The bottom line is that you can treat List as a Monad, or even Set if used
> in isolation with functions that pure wrt element equality, but you can't do
> the same in general for Iterable.
don't want to use quite a lot of the methods currently available on
Iterable. Iterable is so far up the hierarchy that you don't know what
any of them will do.
Some examples are ++ and map, where you probably want to know if you
are dealing with a set.
Not necessarily. Say you want to search a space of possible candidates that get generated in some fashion. Then ++ is union (take all possibilities) and map a result transformation. Now, you might find it more efficient to remove duplicates from your search space changing your generators to produce sets instead of sequences. But the search functionality is completely unchanged. ++ and map make as much sense as they did before.
So it comes down to a question of naming and distinction. Is Iterable the right name for what it is?
I'd argue yes, because Iterable comes from Java where Sets are also Iterables.
"This is a base trait for all immutable Scala collections that define an iterator
method to step through one-by-one the collection's elements.
Implementations of this trait need to provide a concrete method with
signature:
def iterator: Iterator[A]"
Essentially this is due to employing a closure and the fact that mutable variables are allowed in pure functions, e.g.:def foldRight[A,B](xs: Functor[A], var v: B)(f: (B,A) => (B)) = xs.map( a => v = f(v,a) )// yeah I know Scala doesn't let me declare it 'var':
I decided to stop wasting my effort on scala, that's what happened. Views are yet another fine example of why I'm moving on.
Rallying the cause against baroque luggage is helpful, but I hope you abandon your hunger strike.
However, we can get map for free from foldr in a strict evaluation language.def map[A,B](xs: Foldable[A], var v: Monoid[B], f: A => B) = xs.foldRight(null)( (_1,a) => v += f(a); null )
On Monday, September 16, 2013 10:40:28 AM UTC+8, Shelby wrote:However, we can get map for free from foldr in a strict evaluation language.def map[A,B](xs: Foldable[A], var v: Monoid[B], f: A => B) = xs.foldRight(null)( (_1,a) => v += f(a); null )That wasn't returning the correct type and we can make the inner anonymous function pure when we fix:def map[A,B](xs: Foldable[A], v: Monoid[B], f: A => B) = xs.foldRight(v)( (mb,a) => mb += f(a) )Are closures now performance free on Java8 JVM? But Scala doesn't yet support that, so we want to discourage closures in inner loops for now?
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Hi Eric,
Their functionality have been superseded by context bounds.
As for <%< I have no idea.
Cheers,
V
Hi Martin,
Hadn't thought about that, thanks.
On Sep 18, 2013, at 11:16 PM, martin odersky <martin....@epfl.ch> wrote:
> They can, if you are willing to spend a type alias:
>
> type MapToInt[T] = Map[T, Int]
> type Str[T] = String
>
> T: MapToInt, T: Str
This is of course not so great, just like we prefer to be able to write anonymous functions instead of giving them a name just for a single use.
This suggests a more flexible definition of context bounds, such as:
T : C[T1...Tk _ Tk+1...Tn] means there exists an implicit value of type
C[T1...Tk T Tk+1...Tn].
Meaning one could directly write:
T: Map[_,Int]
T: Str
T: Foo[A,B,_,D]
(possibly using another symbol than _ to denote the hole)
Would that make sense?
Cheers,
-- Éric
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
On Sep 19, 2013, at 9:46 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:Thanks Viktor -- I didn't know about this mechanism. It's not really anonymous though, you had to come up with L in the first place.
> Well, if you want to get rid of the external type aliases you can provide a type lambda.
>
> def t[T : ({type L[T]=Map[T,Int]})#L] = ???
Ie., it's just like the difference between (x:Int) => x and
{ def id(x:Int) = x ; id _}
More importantly, I don't think it is hardly as readable as T: Map[_,Int], right?
(or T <% Map[T,Int])
Is there something inherently wrong/impossible with supporting something like
T: C[A,B,_,D]?
Thanks,
-- Éric
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
On Thu, Sep 19, 2013 at 2:26 PM, Eric Tanter <eta...@dcc.uchile.cl> wrote:
Hi Martin,
Hadn't thought about that, thanks.
On Sep 18, 2013, at 11:16 PM, martin odersky <martin....@epfl.ch> wrote:
> They can, if you are willing to spend a type alias:
>
> type MapToInt[T] = Map[T, Int]
> type Str[T] = String
>
> T: MapToInt, T: Str
This is of course not so great, just like we prefer to be able to write anonymous functions instead of giving them a name just for a single use.Well, if you want to get rid of the external type aliases you can provide a type lambda.def t[T : ({type L[T]=Map[T,Int]})#L] = ???
On Thu, Sep 19, 2013 at 2:46 PM, √iktor Ҡlang <viktor...@gmail.com> wrote:
On Thu, Sep 19, 2013 at 2:26 PM, Eric Tanter <eta...@dcc.uchile.cl> wrote:
Hi Martin,
Hadn't thought about that, thanks.
On Sep 18, 2013, at 11:16 PM, martin odersky <martin....@epfl.ch> wrote:
> They can, if you are willing to spend a type alias:
>
> type MapToInt[T] = Map[T, Int]
> type Str[T] = String
>
> T: MapToInt, T: Str
This is of course not so great, just like we prefer to be able to write anonymous functions instead of giving them a name just for a single use.Well, if you want to get rid of the external type aliases you can provide a type lambda.def t[T : ({type L[T]=Map[T,Int]})#L] = ???def t[T](implicit view: T => Map[T, Int])Just to step back a little, we've found that APIs designed using view bounds can lead to surprises for users of the API, and the feature tends not be be used by experienced Scala programmers. So we feel that leaving in this shorthand for a questionable design pattern isn't the best thing for new users.In the proposed deprecation,
we suggest you rewrite them as an implicit parameter, rather than as a context bound. Admittedly, it's a little boilerplatey, so you can use the type alias / context bound if you feel comfortable with it instead.
-jason
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Thanks Jason for the general explanation and link to the thread on scala-internals. That's precisely what I was looking for.
I see that a few people there also argue in favor of nicer syntactic support for things like [T: _ => Int].
Anyway, I agree that the implicit parameter notation tends to be clearer.
The overhead of the notation is when one does not need to use the evidence, so maybe just having a better notation for these cases would be enough (and potentially even make context bounds themselves not that interesting anymore).
For instance, instead of:
def t[T](x:T)(implicit ev: T => Map[T, Int])
something like
def t[T](x:T)(T => Map[T, Int])
then, even the typical context view case:
def foo[T: Ordering](x: T) ...
would read
def foo[T](x:T)(Ordering[T])
which is not too bad, considering the conceptual simplification.
Has this been considered?