Re: 2.6.1-RC1 and Array[].slice
<sean.mcdirmid <at> epfl.ch>
2007-12-01 08:04:58 GMT
I've thought of a better fix: have Array and Array.Projection
implement a common supertype Array.ArrayLike and define
the implicit coercion in Predef on that. Now the code will work
without the type annotation. I still think zip's argument should
be changed to Iterable or Seq given that there is nothing to gain
from accepting an Array (boxing has to be done regardless). Hmm,
there could be a name clash with an existing zip method, I'll
look into it.
Sean
Quoting Blair Zajac <blair <at> orcaware.com>:
> Thanks Sean for the description of the issue and the fixes.
>
> I've opened a ticket to bookmark your suggestion to modify zip().
>
> http://lampsvn.epfl.ch/trac/scala/ticket/260
>
> Regards,
> Blair
>
> sean.mcdirmid <at> epfl.ch wrote:
> > There is an implicit in Predefs that converts array projections into
> arrays
> > by calling force (toArray) automatically. It only works for array
> projections
> > and doesn't work for random access mutable projections. BUT you
> > are using type inference to combine an array with an array projection,
>
> > whose common superclass is mutable random access seq, so the
> implicit
> > coercion isn't firing.
> >
> > Here is one solution:
> >
> > val responses : Array[Int] =
> > if (flag) responses_from_rpc.drop(1) else
> > responses_from_rpc
> >
> > That will cause the implicit coercion to trigger early. The real
> solution
> > would be to change zip so that it takes an iterable or seq and not an
>
> > array, there is no good reason that I can see why it requires an
> array!
> >
> > Projections are more efficient because you can do N operations on an
> > array without creating/copying out an array each time. For
> slice/reverse
> > the projection of an array is really trivial (just transform the
> indices), so
> > it makes more sense to do them this way. The implicit coercion was
> > added to Predef to make it transparent to most users, but type
> inference
> > often defeats implicit coercions. You often can't have both!
> >
> > Sean
> >
> > Quoting Blair Zajac <blair <at> orcaware.com>:
> >
> >> I have code that does something like this for a RPC method to save
> a
> >> network
> >> round trip.
> >>
> >> // Just return the input for this example.
> >> def someRPCmethod[T](in : T) = in
> >>
> >> // Some flag if an additional parameter to the RPC should be added.
> >> val flag = true
> >>
> >> val requests = Array(1,2,3)
> >> val requests_for_rpc = if (flag) (Array(-1) ++ requests) else
> requests
> >> val responses_from_rpc = someRPCmethod(requests_for_rpc)
> >> val responses = if (flag) responses_from_rpc.drop(1) else
> >> responses_from_rpc
> >> requests.zip(responses).foreach { tuple => tuple }
> >>
> >> This works in 2.6.0 but in 2.6.1 the type of responses is not a
> >> Array[Int] but a
> >> RandomAccessSeq.Mutable[Int]{...} which cannot be passed to
> .zip():
> >>
> >> scala> <console>:7: error: type mismatch;
> >> found : RandomAccessSeq.Mutable[Int]{def reverse:
> >> Array.Projection[Int]; def
> >> slice(Int,Int): Array.Projection[Int]; def take(Int):
> >> Array.Projection[Int]; def
> >> drop(Int): Array.Projection[Int]}
> >> required: Array[?]
> >> requests.zip(responses).foreach { tuple => tuple }
> >>
> >>
> >> To get this to work in 2.6.1, I need to add a .toArray after the
> >> drop(1).
> >>
> >> I guess .drop doesn't generate a new array until requested for
> >> performance reasons?
> >>
> >> Is this intended? As a developer in Scala using arrays, do I need
> to
> >> use .toArray?
> >>
> >> Should I file a report for this?
> >>
> >> Blair
>