This page is no longer maintained — Please continue to the home page at www.scala-lang.org

No doubt it's much too late now, but wouldn't it be nice to have negative indices in sequences?

36 replies
Ken McDonald
Joined: 2011-02-13,
User offline. Last seen 42 years 45 weeks ago.
Like, where, seq(-1) is the last element of the sequence, etc. Python does things this way, and it's a really nice convenience.
Ken
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 9:38 AM, Ken McDonald wrote:
> Like, where, seq(-1) is the last element of the sequence, etc. Python
> does things this way, and it's a really nice convenience.

It's much too late for Seq.apply (a method I'd much rather get rid of
entirely to be honest: I am completely convinced it should only be on
IndexedSeq) and I was wontfixed on negative indices even in a narrow
context with specific motivation.

https://issues.scala-lang.org/browse/SI-4500
"splitAt should work with negative indices"

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 9:38 AM, Ken McDonald wrote:
> Like, where, seq(-1) is the last element of the sequence, etc. Python
> does things this way, and it's a really nice convenience.
>
> Ken

I agree with you. It is probably too late to change apply(), but
perhaps a new method could be created, such as .at(-1)?

Cheers,
Greg

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to


On Wed, May 18, 2011 at 9:24 PM, Gregory Crosswhite <gcrosswhite@gmail.com> wrote:
On 5/18/11 9:38 AM, Ken McDonald wrote:
Like, where, seq(-1) is the last element of the sequence, etc. Python does things this way, and it's a really nice convenience.

Ken

I agree with you.  It is probably too late to change apply(), but perhaps a new method could be created, such as .at(-1)?

No. We are now at a point where we need to treat collections as more or less fixed. No new methods just for nicety's sake. Sometimes I envie Java for its imposed rigidity. Nobody proposes new methods for Java collections because the price to pay (re-implement all implementations) is obviously too high. In Scala, the costs of bloat and change are less obvious but nevertheless real.

Cheers

 -- Martin

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to
On 5/18/11 12:42 PM, martin odersky wrote:
BANLkTimQ-91LZr-yoCvstiCgQcYtSDH7ag [at] mail [dot] gmail [dot] com" type="cite">

On Wed, May 18, 2011 at 9:24 PM, Gregory Crosswhite <gcrosswhite [at] gmail [dot] com" rel="nofollow">gcrosswhite@gmail.com> wrote:
On 5/18/11 9:38 AM, Ken McDonald wrote:
Like, where, seq(-1) is the last element of the sequence, etc. Python does things this way, and it's a really nice convenience.

Ken

I agree with you.  It is probably too late to change apply(), but perhaps a new method could be created, such as .at(-1)?

No. We are now at a point where we need to treat collections as more or less fixed. No new methods just for nicety's sake. Sometimes I envie Java for its imposed rigidity. Nobody proposes new methods for Java collections because the price to pay (re-implement all implementations) is obviously too high. In Scala, the costs of bloat and change are less obvious but nevertheless real.

Cheers

 -- Martin



Would it really be that difficult to implement, though?  It seems to me (probably naively) that all it would take to implement it would be a single addition to the scala.collection.Seq trait which would look something like:

    def at(index: Int): A =
        if(index >= 0)
            apply(index)
        else
            apply(size()-1+index)

Cheers,
Greg
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 1:09 PM, Gregory Crosswhite wrote:
>> No. We are now at a point where we need to treat collections as more
>> or less fixed. No new methods just for nicety's sake. Sometimes I
>> envie Java for its imposed rigidity. Nobody proposes new methods for
>> Java collections because the price to pay (re-implement all
>> implementations) is obviously too high. In Scala, the costs of bloat
>> and change are less obvious but nevertheless real.
>
> Would it really be that difficult to implement, though?

It is unfortunate that it is unbecoming to say things like "whoosh" or
make references to the missing the point olympics. If today were
opposite day and those things were ununbecoming, then today would be
looking pretty good.

> def at(index: Int): A =
> if(index >= 0)
> apply(index)
> else
> apply(size()-1+index)

With the minor detail that it changes the semantics of every piece of
scala code on the planet.

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

also, what's so hard about writing seq(seq.size - 1) if you need to access the last element of an indexed sequence? i find seq(-1) quite esoteric to be part of and useful in a standard collections library.

On 18 May 2011, at 21:17, Paul Phillips wrote:

> On 5/18/11 1:09 PM, Gregory Crosswhite wrote:
>>> No. We are now at a point where we need to treat collections as more
>>> or less fixed. No new methods just for nicety's sake. Sometimes I
>>> envie Java for its imposed rigidity. Nobody proposes new methods for
>>> Java collections because the price to pay (re-implement all
>>> implementations) is obviously too high. In Scala, the costs of bloat
>>> and change are less obvious but nevertheless real.
>>
>> Would it really be that difficult to implement, though?
>
> It is unfortunate that it is unbecoming to say things like "whoosh" or
> make references to the missing the point olympics. If today were
> opposite day and those things were ununbecoming, then today would be
> looking pretty good.
>
>> def at(index: Int): A =
>> if(index >= 0)
>> apply(index)
>> else
>> apply(size()-1+index)
>
> With the minor detail that it changes the semantics of every piece of
> scala code on the planet.

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 1:17 PM, Paul Phillips wrote:
> It is unfortunate that it is unbecoming to say things like "whoosh" or
> make references to the missing the point olympics. If today were
> opposite day and those things were ununbecoming, then today would be
> looking pretty good.
>
>> > def at(index: Int): A =
>> > if(index>= 0)
>> > apply(index)
>> > else
>> > apply(size()-1+index)
> With the minor detail that it changes the semantics of every piece of
> scala code on the planet.

How exactly does adding a new method with a brand new name intentionally
chosen to *not* conflict with any existing method name change the
semantics of every piece of scala code on the planet?

Methinks I am not the one who has had a "whoosh" moment here...

Cheers,
Greg

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 1:40 PM, Gregory Crosswhite wrote:
> How exactly does adding a new method with a brand new name intentionally
> chosen to *not* conflict with any existing method name change the
> semantics of every piece of scala code on the planet?
>
> Methinks I am not the one who has had a "whoosh" moment here...

I'll split it with you. You are still whooshing on the fact that the
implementation in isolation represents a negligible fraction of the
total cost to be borne. But being a fiery competitor, I wasn't going to
let that keep me off the track in today's olympic trials.

Alex Repain
Joined: 2010-07-27,
User offline. Last seen 1 year 31 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to


2011/5/18 Gregory Crosswhite <gcrosswhite@gmail.com>
On 5/18/11 1:17 PM, Paul Phillips wrote:
It is unfortunate that it is unbecoming to say things like "whoosh" or
make references to the missing the point olympics.  If today were
opposite day and those things were ununbecoming, then today would be
looking pretty good.

>       def at(index: Int): A =
>           if(index>= 0)
>               apply(index)
>           else
>               apply(size()-1+index)
With the minor detail that it changes the semantics of every piece of
scala code on the planet.

How exactly does adding a new method with a brand new name intentionally chosen to *not* conflict with any existing method name change the semantics of every piece of scala code on the planet?

One could think of a class inheriting the Seq trait where apply is overriden. Therefore an access by .at(-1) should also be overriden if a particular semantics must be conserved. If the user of an API uses .at() of that SeqChild class, thinking it would produce the same result as a regular apply() access, he would run into problems. That, indeed, is a semantic problem, although not obvious if you think only in terms of compilation compatibility.

Methinks I am not the one who has had a "whoosh" moment here...

Cheers,
Greg

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 1:45 PM, Paul Phillips wrote:
> On 5/18/11 1:40 PM, Gregory Crosswhite wrote:
>> How exactly does adding a new method with a brand new name intentionally
>> chosen to *not* conflict with any existing method name change the
>> semantics of every piece of scala code on the planet?
>>
>> Methinks I am not the one who has had a "whoosh" moment here...
> I'll split it with you. You are still whooshing on the fact that the
> implementation in isolation represents a negligible fraction of the
> total cost to be borne. But being a fiery competitor, I wasn't going to
> let that keep me off the track in today's olympic trials.

I have a suggestion. Rather than just saying "whoosh!" and alienating a
newcomer (namely myself) to this list who was genuinely curious and
looking forward to an explanation as to exactly what he is missing that
would make it so difficult to implement this method beyond his proposal,
why don't you actually explain what it is that you are getting at?

I am sufficiently familiar with programming and programming languages in
general to conceive of the possibility of cross-cutting concerns, but I
am not familiar enough with the Scala collection classes in particular
to be able to see what it is that I am missing that would make such a
seemingly simple addition to them as monstrously complicated as you all
seem to be making it out to be.

Cheers,
Greg

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to
On 5/18/11 1:46 PM, Alex Repain wrote:
YXJXZk6J1Rk4sMMgp0nn_t23w [at] mail [dot] gmail [dot] com" type="cite">

2011/5/18 Gregory Crosswhite <gcrosswhite [at] gmail [dot] com" rel="nofollow">gcrosswhite@gmail.com>
On 5/18/11 1:17 PM, Paul Phillips wrote:
It is unfortunate that it is unbecoming to say things like "whoosh" or
make references to the missing the point olympics.  If today were
opposite day and those things were ununbecoming, then today would be
looking pretty good.

>       def at(index: Int): A =
>           if(index>= 0)
>               apply(index)
>           else
>               apply(size()-1+index)
With the minor detail that it changes the semantics of every piece of
scala code on the planet.

How exactly does adding a new method with a brand new name intentionally chosen to *not* conflict with any existing method name change the semantics of every piece of scala code on the planet?

One could think of a class inheriting the Seq trait where apply is overriden. Therefore an access by .at(-1) should also be overriden if a particular semantics must be conserved. If the user of an API uses .at() of that SeqChild class, thinking it would produce the same result as a regular apply() access, he would run into problems. That, indeed, is a semantic problem, although not obvious if you think only in terms of compilation compatibility.


That is certainly a fair counterpoint (and one that I had thought of and probably should have mentioned if I hadn't been so annoyed at the "woosh!" tone of the response and thus disinclined to give any ground in my response :-) ).  Clearly though this is a trade-off that the Scala community has been willing to make since methods have continued to be added.  Since new versions have tended to break compatibility with application code anyway, making changes to code to migrate to a new version is something to which people are accustomed.

Cheers,
Greg
extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

It is likely the literally thousands of hours I have spent diagnosing
and fixing bugs which are consequences of the interaction of elements
which are trivial when considered in isolation has lowered my patience
for glib replies about how easy something would be to implement,
especially when in direct response to an email which has as its central
point that such costs exist. If you would really like to consider
examples we have hundred and hundreds of open bugs for your review (now
in a flashy new database) the majority of which are a direct result of
unanticipated permutations amongst the 2^N configurations of our beloved
N features.

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 05/18/2011 01:46 PM, Alex Repain wrote:
> One could think of a class inheriting the Seq trait where apply is
> overriden. Therefore an access by .at(-1) should also be overriden if
> a particular semantics must be conserved. If the user of an API uses
> .at() of that SeqChild class, thinking it would produce the same
> result as a regular apply() access, he would run into problems. That,
> indeed, is a semantic problem, although not obvious if you think only
> in terms of compilation compatibility.

Oh wait, my brain was fogged and I see now that I did not fully process
your message before responding to it. :-) I was actually thinking in
terms of what would happen if someone had already created an "at" method
in their subclass with completely different behavior, but that wasn't
what you were getting at. Your point was that introducing an .at()
method requires that all subclasses obey the contract that the semantics
of .at() be conserved and thus they must override it if necessary in
order to make their interface have consistent behavior. This actually
is a point that I hadn't considered --- it is essentially the same point
I had in mind that changing a superclass changes the semantics of its
subclasses, but it is a different variation on this theme that I hadn't
considered --- so I appreciate you taking the time to mention it to me,
though it is hard to see how .at() could ever cause problems this way in
practice.

Cheers,
Greg

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On Wed, May 18, 2011 at 1:09 PM, Gregory Crosswhite
wrote:
> On 5/18/11 12:42 PM, martin odersky wrote:
>
> On Wed, May 18, 2011 at 9:24 PM, Gregory Crosswhite
> wrote:
>>
>> On 5/18/11 9:38 AM, Ken McDonald wrote:
>>>
>>> Like, where, seq(-1) is the last element of the sequence, etc. Python
>>> does things this way, and it's a really nice convenience.
>>>
>>> Ken
>>
>> I agree with you.  It is probably too late to change apply(), but perhaps
>> a new method could be created, such as .at(-1)?
>
> No. We are now at a point where we need to treat collections as more or less
> fixed. No new methods just for nicety's sake. Sometimes I envie Java for its
> imposed rigidity. Nobody proposes new methods for Java collections because
> the price to pay (re-implement all implementations) is obviously too high.
> In Scala, the costs of bloat and change are less obvious but nevertheless
> real.
>
> Cheers
>
>  -- Martin
>
>
>
> Would it really be that difficult to implement, though?

Who cares? Littering the library with method names with superset
functionality of other methods is a horrid idea. There's nothing in
the name "at" that suggests that its functionality is a superset of
"apply". How will you explain this to your grandchildren?

> It seems to me
> (probably naively) that all it would take to implement it would be a single
> addition to the scala.collection.Seq trait which would look something like:
>
>     def at(index: Int): A =
>         if(index >= 0)
>             apply(index)
>         else
>             apply(size()-1+index)

You do realize that, if size() is O(N), that this is a grossly
inefficient implementation, don't you? That there's an implementation
that only requires one traversal?

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On Wed, May 18, 2011 at 9:38 AM, Ken McDonald wrote:
> Like, where, seq(-1) is the last element of the sequence, etc. Python does
> things this way, and it's a really nice convenience.
> Ken

Really? Python has a stack of collection classes with varying
implementations and big-O performance? Or do you mean that Python's
"lists", actually vectors, with O(1) indexing and length, provide
this convenience?

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 1:21 PM, Sciss wrote:
> also, what's so hard about writing seq(seq.size - 1) if you need to access the last element of an indexed sequence? i find seq(-1) quite esoteric to be part of and useful in a standard collections library.

Nothing, but that kind of argument can be used against every convenience
library function...

Cheers,
Greg

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On Wed, May 18, 2011 at 2:35 PM, Gregory Crosswhite
wrote:
> On 5/18/11 1:21 PM, Sciss wrote:
>>
>> also, what's so hard about writing seq(seq.size - 1) if you need to access
>> the last element of an indexed sequence? i find seq(-1) quite esoteric to be
>> part of and useful in a standard collections library.
>
> Nothing, but that kind of argument can be used against every convenience
> library function...

Which methods currently in the library save the typing of 8
characters? And to both of you: seq(seq.size - 1) takes twice as long
as the efficient implementation for sequences where size is O(N). The
equivalence holds in Python for its vectors; it does not hold
generally for Seqs ... and libraries should have efficient
implementations, especially for usages so common that they warrant
"convenience".

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

convenient when? in very special cases maybe, but not generally. convenient is also to have mean, median, variance, standard deviation, histogram, choose (get me a random element), etc., and still they are not in the standard interface.

i don't see how your wrapped index is useful in general scenarios. i could equally argue that it should be clipped:

def at( idx: Int ) : T = apply( math.max( 0, math.min( size - 1, idx ))

and from looking at my code base i would argue that this case is much more likely than wanting the index to wrap.

best, -sciss-

On 18 May 2011, at 22:35, Gregory Crosswhite wrote:

> On 5/18/11 1:21 PM, Sciss wrote:
>> also, what's so hard about writing seq(seq.size - 1) if you need to access the last element of an indexed sequence? i find seq(-1) quite esoteric to be part of and useful in a standard collections library.
>
> Nothing, but that kind of argument can be used against every convenience library function...
>
> Cheers,
> Greg

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 2:41 PM, Sciss wrote:
> convenient when? in very special cases maybe, but not generally.

Grr, unfortunately I can't think of examples off the top of my head, but
essentially there are times in algorithms where you are subtracting
numbers from indices and it is useful for them to just wrap around. So
a generalization of this feature is really not just accepting negative
indices but to take the index modulo the size.

It's one of those features that you miss when you don't have it but that
when you wonder how you could have lived without it when you do. :-)

> convenient is also to have mean, median, variance, standard deviation, histogram, choose (get me a random element), etc., and still they are not in the standard interface.
>

True, my point is just saying that the fact that you could accomplish
something by other means doesn't mean that it therefore doesn't belong
outside the library, but in retrospect I see that the grandparent post
was really saying something more along the lines that the benefits of
seq(-1) are not nearly strong enough to merit being a library function
so my reply was not a particularly good response and therefore I
actually officially retract it. :-)

> i don't see how your wrapped index is useful in general scenarios. i could equally argue that it should be clipped:
>
> def at( idx: Int ) : T = apply( math.max( 0, math.min( size - 1, idx ))
>
> and from looking at my code base i would argue that this case is much more likely than wanting the index to wrap.
>
> best, -sciss-

Hmm, that is a good point. In that case, I propose that *both* exist!

Thank you for replying in an insightful and non-hostile manner. :-)

Cheers,
Greg

Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 2:42 PM, Jim Balter wrote:
> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald wrote:
>> Like, where, seq(-1) is the last element of the sequence, etc. Python does
>> things this way, and it's a really nice convenience.
>> Ken
> Really? Python has a stack of collection classes with varying
> implementations and big-O performance? Or do you mean that Python's
> "lists", actually vectors, with O(1) indexing and length, provide
> this convenience?
>

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On Wed, May 18, 2011 at 2:54 PM, Gregory Crosswhite
wrote:
> On 5/18/11 2:42 PM, Jim Balter wrote:
>>
>> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald  wrote:
>>>
>>> Like, where, seq(-1) is the last element of the sequence, etc. Python
>>> does
>>> things this way, and it's a really nice convenience.
>>> Ken
>>
>> Really? Python has a stack of collection classes with varying
>> implementations and big-O performance? Or do you mean that Python's
>> "lists",  actually vectors, with O(1) indexing and length, provide
>> this convenience?
>>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to
Gregory Crosswhite
Joined: 2011-05-18,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On 5/18/11 3:08 PM, Jim Balter wrote:
> On Wed, May 18, 2011 at 2:54 PM, Gregory Crosswhite
> wrote:
>> On 5/18/11 2:42 PM, Jim Balter wrote:
>>> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald wrote:
>>>> Like, where, seq(-1) is the last element of the sequence, etc. Python
>>>> does
>>>> things this way, and it's a really nice convenience.
>>>> Ken
>>> Really? Python has a stack of collection classes with varying
>>> implementations and big-O performance? Or do you mean that Python's
>>> "lists", actually vectors, with O(1) indexing and length, provide
>>> this convenience?
>>>
>>> -- Jim
>> Sheesh, I subscribe to many programming language lists, and I have never
>> seen such casual hostility like I have on this one...
> Given the remarkable hostility in your own comment, I simply do not believe you.

Okay, you all win. Clearly I am the one who does not belong on this
list. Have fun!

- Greg

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On Wed, May 18, 2011 at 3:08 PM, Jim Balter wrote:
> On Wed, May 18, 2011 at 2:54 PM, Gregory Crosswhite
> wrote:
>> On 5/18/11 2:42 PM, Jim Balter wrote:
>>>
>>> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald  wrote:
>>>>
>>>> Like, where, seq(-1) is the last element of the sequence, etc. Python
>>>> does
>>>> things this way, and it's a really nice convenience.
>>>> Ken
>>>
>>> Really? Python has a stack of collection classes with varying
>>> implementations and big-O performance? Or do you mean that Python's
>>> "lists",  actually vectors, with O(1) indexing and length, provide
>>> this convenience?
>>>
>>> -- Jim
>>
>> Sheesh, I subscribe to many programming language lists, and I have never
>> seen such casual hostility like I have on this one...
>
> Given the remarkable hostility in your own comment, I simply do not believe you.
>
>> Yes, clearly that is what he meant.
>
> WHOOSH!
>
>> Ergo, charitably, if such a feature
>> existed we would probably want it to be a feature only of IndexedSeq and not
>> of Seq in general.
>
> Who would want that? Not anyone sensible who recognizes the value of
> consistency.

To clarify: it would be a (nother) horrid idea for apply() or at() to
take negative arguments only for IndexedSeq and not for Seq. It would
not be a horrid idea for apply to be a method of IndexedSeq but not
Seq, as Paul urged (for another universe where Seq#apply doesn't yet
exist).

jibal
Joined: 2010-12-01,
User offline. Last seen 1 year 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On Wed, May 18, 2011 at 1:46 PM, Alex Repain wrote:
>
>
> 2011/5/18 Gregory Crosswhite
>>
>> On 5/18/11 1:17 PM, Paul Phillips wrote:
>>>
>>> It is unfortunate that it is unbecoming to say things like "whoosh" or
>>> make references to the missing the point olympics.  If today were
>>> opposite day and those things were ununbecoming, then today would be
>>> looking pretty good.
>>>
>>>> >       def at(index: Int): A =
>>>> >           if(index>= 0)
>>>> >               apply(index)
>>>> >           else
>>>> >               apply(size()-1+index)
>>>
>>> With the minor detail that it changes the semantics of every piece of
>>> scala code on the planet.
>>
>> How exactly does adding a new method with a brand new name intentionally
>> chosen to *not* conflict with any existing method name change the semantics
>> of every piece of scala code on the planet?
>
> One could think of a class inheriting the Seq trait where apply is
> overriden. Therefore an access by .at(-1) should also be overriden if a
> particular semantics must be conserved. If the user of an API uses .at() of
> that SeqChild class, thinking it would produce the same result as a regular
> apply() access, he would run into problems. That, indeed, is a semantic
> problem, although not obvious if you think only in terms of compilation
> compatibility.

I'm not following this. Seq#apply has a contract, "returns the element
of this sequence at index idx, where 0 indicates the first element",
that any subclass must obey. Given that, and discounting his buggy
arithmetic, Gregory's naive implementation should yield the right
result for any subclass of Seq.

Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to
Hi All,

I'm not sure what WHOOSH means yet, but I just wanted to point out that anyone who likes that at method that takes a negative index can have their cake and eat it too with an implicit conversion. I actually quite liked that feature of Python myself, but it never occurred to me or felt like it was "missing" in Scala.

Bill

On Wed, May 18, 2011 at 3:08 PM, Jim Balter <Jim@balter.name> wrote:
On Wed, May 18, 2011 at 2:54 PM, Gregory Crosswhite
<gcrosswhite@gmail.com> wrote:
> On 5/18/11 2:42 PM, Jim Balter wrote:
>>
>> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald<ykkenmcd@gmail.com>  wrote:
>>>
>>> Like, where, seq(-1) is the last element of the sequence, etc. Python
>>> does
>>> things this way, and it's a really nice convenience.
>>> Ken
>>
>> Really? Python has a stack of collection classes with varying
>> implementations and big-O performance? Or do you mean that Python's
>> "lists",  actually vectors, with O(1) indexing and length, provide
>> this convenience?
>>
>> -- Jim
>
> Sheesh, I subscribe to many programming language lists, and I have never
> seen such casual hostility like I have on this one...

Given the remarkable hostility in your own comment, I simply do not believe you.

> Yes, clearly that is what he meant.

WHOOSH!

> Ergo, charitably, if such a feature
> existed we would probably want it to be a feature only of IndexedSeq and not
> of Seq in general.

Who would want that? Not anyone sensible who recognizes the value of
consistency.

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to
On Wed, May 18, 2011 at 5:52 PM, Jim Balter <Jim@balter.name> wrote:
On Wed, May 18, 2011 at 2:35 PM, Gregory Crosswhite
<gcrosswhite@gmail.com> wrote:
> On 5/18/11 1:21 PM, Sciss wrote:
>>
>> also, what's so hard about writing seq(seq.size - 1) if you need to access
>> the last element of an indexed sequence? i find seq(-1) quite esoteric to be
>> part of and useful in a standard collections library.
>
> Nothing, but that kind of argument can be used against every convenience
> library function...

Which methods currently in the library save the typing of 8
characters?

That's not a serious question is it?

x.filter(!f(_))
x.filterNot(f)  // Saves one character!

x.insertAll(5, Seq('a', 'b'))
x.insert(5, 'a', 'b')  // Saves 8 characters--5 if it didn't take the "insert" name!

!x.isEmpty
x.isDefined  // Saves -1 character!

Range(0, x.size)
x.indices  // Saves 7 characters!

x.foldLeft(0)(_ max _)
(0 /: x)(_ max _)  // Saves 5 characters!

And so on.

The library is full of things that save typing a few characters, or save needing to read a ! or two, or provide a specific implementation rather than a general one.

  --Rex

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

(sorry, some typos)

BTW: SuperCollider's collection classes have four methods:

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

foldAt is probably a bad name as in scala fold has a predefined meaning. maybe bounceAt is better?

class RichIndexedSeq[ T ]( xs: IndexedSeq[ T ]) {
def wrapAt( idx: Int ) : T = {
val sz = xs.size
if( sz == 0 ) throw new IndexOutOfBoundsException()
val i = if( idx >= 0 ) idx % sz else (sz - 1) - ((-1 - idx) % sz)
xs( i )
}
def clipAt( idx: Int ) : T = xs( math.max( 0, math.min( xs.size - 1, idx )))
def bounceAt( idx: Int ) : T = {
val sz = xs.size
if( sz == 0 ) throw new IndexOutOfBoundsException()
val sz2 = (sz - 1) << 1
val i = if( idx >= 0 ) idx % sz2 else (sz2 - 1) - ((-1 - idx) % sz2)
val j = if( i < sz ) i else sz2 - i
xs( j )
}
}

implicit def enrichIndexedSeq[ T ]( xs: IndexedSeq[ T ]) = new RichIndexedSeq[ T ]( xs )

val x = Vector(0,1,2,3)
val i = (-10 to 10)
i.map( x.wrapAt( _ ))
i.map( x.clipAt( _ ))
i.map( x.bounceAt( _ ))

best, -sciss-

On 18 May 2011, at 23:14, Sciss wrote:

> (sorry, some typos)
>
> BTW: SuperCollider's collection classes have four methods:
>
> at -- plain lookup; syntactic sugar is square brackets, e.g. seq[1]
> clipAt -- clips index to 0 ... size-1
> wrapAt -- does a modulo-size to the index
> foldAt -- does a ping-pong (e.g. an index of size gets mapped to size - 1, an index of size + 1 gets mapped to size - 2 etc.)
>
> :)
>
> best, -sciss-
>
> On 18 May 2011, at 23:10, Sciss wrote:
>
>> BTW: SuperCollider's collection classes have four methods:
>>
>> at -- plain lookup; syntactic sugar is square brackets, e.g. seq[1]
>> clipAt -- clips index to 0 ... size-1
>> wrapAt -- does a module size to the index
>> foldAt -- does a ping-pong (e.g. an index of size gets mapped to size - 1, an index of size - 1 gets mapped to size - 2 etc.)
>>
>> :)
>>
>> best, -sciss-
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

def foldAt( idx: Int ) : T = {
val sz = xs.size
if( sz == 0 ) throw new IndexOutOfBoundsException()
val sz2 = (sz - 1) << 1
val i = if( sz2 == 0 ) 0 else if( idx >= 0 ) idx % sz2 else (sz2 - 1) - ((-1 - idx) % sz2)
val j = if( i < sz ) i else sz2 - i
xs( j )
}

On 18 May 2011, at 23:34, Sciss wrote:

> foldAt is probably a bad name as in scala fold has a predefined meaning. maybe bounceAt is better?
>
> class RichIndexedSeq[ T ]( xs: IndexedSeq[ T ]) {
> def wrapAt( idx: Int ) : T = {
> val sz = xs.size
> if( sz == 0 ) throw new IndexOutOfBoundsException()
> val i = if( idx >= 0 ) idx % sz else (sz - 1) - ((-1 - idx) % sz)
> xs( i )
> }
> def clipAt( idx: Int ) : T = xs( math.max( 0, math.min( xs.size - 1, idx )))
> def bounceAt( idx: Int ) : T = {
> val sz = xs.size
> if( sz == 0 ) throw new IndexOutOfBoundsException()
> val sz2 = (sz - 1) << 1
> val i = if( idx >= 0 ) idx % sz2 else (sz2 - 1) - ((-1 - idx) % sz2)
> val j = if( i < sz ) i else sz2 - i
> xs( j )
> }
> }
>
> implicit def enrichIndexedSeq[ T ]( xs: IndexedSeq[ T ]) = new RichIndexedSeq[ T ]( xs )
>
> val x = Vector(0,1,2,3)
> val i = (-10 to 10)
> i.map( x.wrapAt( _ ))
> i.map( x.clipAt( _ ))
> i.map( x.bounceAt( _ ))
>
> best, -sciss-
>
>
>
> On 18 May 2011, at 23:14, Sciss wrote:
>
>> (sorry, some typos)
>>
>> BTW: SuperCollider's collection classes have four methods:
>>
>> at -- plain lookup; syntactic sugar is square brackets, e.g. seq[1]
>> clipAt -- clips index to 0 ... size-1
>> wrapAt -- does a modulo-size to the index
>> foldAt -- does a ping-pong (e.g. an index of size gets mapped to size - 1, an index of size + 1 gets mapped to size - 2 etc.)
>>
>> :)
>>
>> best, -sciss-
>>
>> On 18 May 2011, at 23:10, Sciss wrote:
>>
>>> BTW: SuperCollider's collection classes have four methods:
>>>
>>> at -- plain lookup; syntactic sugar is square brackets, e.g. seq[1]
>>> clipAt -- clips index to 0 ... size-1
>>> wrapAt -- does a module size to the index
>>> foldAt -- does a ping-pong (e.g. an index of size gets mapped to size - 1, an index of size - 1 gets mapped to size - 2 etc.)
>>>
>>> :)
>>>
>>> best, -sciss-
>>
>

Ken McDonald
Joined: 2011-02-13,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

It's just the "code smell" that Martin talks about at various times. It's inelegant to have to repeat names simply because the designers of an API didn't go to the trouble to make their API more general. (NOTE: I'm NOT implying this is the case with Scala, though I have seen it many other places.) And from working quite extensively with Python over the years, I've found this little convenience to be, well, quite convenient.

I want to make clear I wasn't implying changing any parts of the Scala library to support this--I hope that was clear from the title of my original post. I'd just come across a situation where this would have been useful, and would curious as to other people's thoughts and why it had not originally been done.

Thanks,
Ken

On May 18, 2011, at 4:35 PM, Gregory Crosswhite wrote:

> On 5/18/11 1:21 PM, Sciss wrote:
>> also, what's so hard about writing seq(seq.size - 1) if you need to access the last element of an indexed sequence? i find seq(-1) quite esoteric to be part of and useful in a standard collections library.
>
> Nothing, but that kind of argument can be used against every convenience library function...
>
> Cheers,
> Greg

Ken McDonald
Joined: 2011-02-13,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

No, of course I didn't mean that--I writing to a sophisticated audience with a pretty wide range of programming, and I don't feel the need to dot all my i's and cross all my t's unless I'm asking a very technical question. (And then I often get it wrong anyway :-) ). It was really just a casual observation about a feature which many years of use has led me to value.

Ken

On May 18, 2011, at 4:42 PM, Jim Balter wrote:

> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald wrote:
>> Like, where, seq(-1) is the last element of the sequence, etc. Python does
>> things this way, and it's a really nice convenience.
>> Ken
>
> Really? Python has a stack of collection classes with varying
> implementations and big-O performance? Or do you mean that Python's
> "lists", actually vectors, with O(1) indexing and length, provide
> this convenience?
>

Ittay Dror 2
Joined: 2010-05-05,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to


martin odersky wrote:
BANLkTimQ-91LZr-yoCvstiCgQcYtSDH7ag [at] mail [dot] gmail [dot] com" type="cite">

On Wed, May 18, 2011 at 9:24 PM, Gregory Crosswhite <gcrosswhite [at] gmail [dot] com" rel="nofollow">gcrosswhite@gmail.com> wrote:
On 5/18/11 9:38 AM, Ken McDonald wrote:
Like, where, seq(-1) is the last element of the sequence, etc. Python does things this way, and it's a really nice convenience.

Ken

I agree with you.  It is probably too late to change apply(), but perhaps a new method could be created, such as .at(-1)?

No. We are now at a point where we need to treat collections as more or less fixed. No new methods just for nicety's sake. Sometimes I envie Java for its imposed rigidity. Nobody proposes new methods for Java collections because the price to pay (re-implement all implementations) is obviously too high. In Scala, the costs of bloat and change are less obvious but nevertheless real.

Maybe have a way of easily extending the sdk with external libraries? E.g., the compiler as argument a list of jars where the classes are annotated as @Extending another class. Methods have as first argument objects of the extended class. So then to get an 'as' method I just pass a jar with its implementation to the compiler.

Similar to implicit conversions, but without the import and wrapping tax.

Ittay


BANLkTimQ-91LZr-yoCvstiCgQcYtSDH7ag [at] mail [dot] gmail [dot] com" type="cite">
Cheers

 -- Martin

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

On Wed, May 18, 2011 at 19:11, Bill Venners wrote:
> Hi All,
>
> I'm not sure what WHOOSH means yet, but I just wanted to point out that
> anyone who likes that at method that takes a negative index can have their
> cake and eat it too with an implicit conversion. I actually quite liked that
> feature of Python myself, but it never occurred to me or felt like it was
> "missing" in Scala.

For that matter, I like that feature as well, and, if Scala had it
default like Python, I'd have spent much more time last Saturday
figuring out why my code wasn't working, when it was just a matter of
off-by-1 errors.

>
> Bill
>
> On Wed, May 18, 2011 at 3:08 PM, Jim Balter wrote:
>>
>> On Wed, May 18, 2011 at 2:54 PM, Gregory Crosswhite
>> wrote:
>> > On 5/18/11 2:42 PM, Jim Balter wrote:
>> >>
>> >> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald
>> >>  wrote:
>> >>>
>> >>> Like, where, seq(-1) is the last element of the sequence, etc. Python
>> >>> does
>> >>> things this way, and it's a really nice convenience.
>> >>> Ken
>> >>
>> >> Really? Python has a stack of collection classes with varying
>> >> implementations and big-O performance? Or do you mean that Python's
>> >> "lists",  actually vectors, with O(1) indexing and length, provide
>> >> this convenience?
>> >>
>> >> -- Jim
>> >
>> > Sheesh, I subscribe to many programming language lists, and I have never
>> > seen such casual hostility like I have on this one...
>>
>> Given the remarkable hostility in your own comment, I simply do not
>> believe you.
>>
>> > Yes, clearly that is what he meant.
>>
>> WHOOSH!
>>
>> > Ergo, charitably, if such a feature
>> > existed we would probably want it to be a feature only of IndexedSeq and
>> > not
>> > of Seq in general.
>>
>> Who would want that? Not anyone sensible who recognizes the value of
>> consistency.
>>

Bill Venners
Joined: 2008-12-18,
User offline. Last seen 31 weeks 5 days ago.
Re: No doubt it's much too late now, but wouldn't it be nice to
Hi Daniel,

On Thu, May 19, 2011 at 5:16 AM, Daniel Sobral <dcsobral@gmail.com> wrote:
On Wed, May 18, 2011 at 19:11, Bill Venners <bill@artima.com> wrote:
> Hi All,
>
> I'm not sure what WHOOSH means yet, but I just wanted to point out that
> anyone who likes that at method that takes a negative index can have their
> cake and eat it too with an implicit conversion. I actually quite liked that
> feature of Python myself, but it never occurred to me or felt like it was
> "missing" in Scala.

For that matter, I like that feature as well, and, if Scala had it
default like Python, I'd have spent much more time last Saturday
figuring out why my code wasn't working, when it was just a matter of
off-by-1 errors.

Yes, I think that's why I didn't miss it in Scala. I program differently in Scala than I did in Python, using indexes a lot less often.

Bill
 
>
> Bill
>
> On Wed, May 18, 2011 at 3:08 PM, Jim Balter <Jim@balter.name> wrote:
>>
>> On Wed, May 18, 2011 at 2:54 PM, Gregory Crosswhite
>> <gcrosswhite@gmail.com> wrote:
>> > On 5/18/11 2:42 PM, Jim Balter wrote:
>> >>
>> >> On Wed, May 18, 2011 at 9:38 AM, Ken McDonald<ykkenmcd@gmail.com>
>> >>  wrote:
>> >>>
>> >>> Like, where, seq(-1) is the last element of the sequence, etc. Python
>> >>> does
>> >>> things this way, and it's a really nice convenience.
>> >>> Ken
>> >>
>> >> Really? Python has a stack of collection classes with varying
>> >> implementations and big-O performance? Or do you mean that Python's
>> >> "lists",  actually vectors, with O(1) indexing and length, provide
>> >> this convenience?
>> >>
>> >> -- Jim
>> >
>> > Sheesh, I subscribe to many programming language lists, and I have never
>> > seen such casual hostility like I have on this one...
>>
>> Given the remarkable hostility in your own comment, I simply do not
>> believe you.
>>
>> > Yes, clearly that is what he meant.
>>
>> WHOOSH!
>>
>> > Ergo, charitably, if such a feature
>> > existed we would probably want it to be a feature only of IndexedSeq and
>> > not
>> > of Seq in general.
>>
>> Who would want that? Not anyone sensible who recognizes the value of
>> consistency.
>>
>> -- Jim
>
>
>
> --
> Bill Venners
> Artima, Inc.
> http://www.artima.com
>



--
Daniel C. Sobral

I travel to the future all the time.



--
Bill Venners
Artima, Inc.
http://www.artima.com
Arioch
Joined: 2009-08-06,
User offline. Last seen 42 years 45 weeks ago.
Re: No doubt it's much too late now, but wouldn't it be nice to

В письме от Thu, 19 May 2011 02:05:18 +0400, Jim Balter
сообщал:

>> One could think of a class inheriting the Seq trait where apply is
>> overriden. Therefore an access by .at(-1) should also be overriden if a
>> particular semantics must be conserved. If the user of an API uses
>> .at() of
>> that SeqChild class, thinking it would produce the same result as a
>> regular
>> apply() access, he would run into problems.

> I'm not following this. Seq#apply has a contract, "returns the element
> of this sequence at index idx, where 0 indicates the first element",
> that any subclass must obey. Given that, and discounting his buggy
> arithmetic, Gregory's naive implementation should yield the right
> result for any subclass of Seq.

True - as long as it remains naive.
But then optimizations may be implemented, working directly with data
structure bypassing apply().
Say, in a couple of years, when everyone already forgotten this
discussion, and would be surprised by strange bugs.

---

And - already asked - why Seq ?

When u load a database table, it might be one-directional or
bi-directional.

Same way for sequences, fixed-size array (is it Python's Vector mentioned
above?) would be very easy and fast to implement at on top of apply.

For usual one-way List or Stack it would be not so efficient though.
So either use of .reverse() would be better or iterating all item of List
required.
But .reverse() is nice when u save (cache) the result, for at (-2),
at(-3), etc.
Should List cache it ? if yes, then when to dispose it ? What about
mutable List ?
Isolation vs optimisation, common trait :-D
If u implement negative indice ouside the class, in your code, you can
.reverse() the list and hold it as long as u need. But inside the List
class, how can the lib know what u try to do ?

I also think that non-effective method over List would be like provoking
to use it without thinking.

---

My guess, is that those wrapping, bouncing and clipping methods might be
nice for SOME sequences, with easy cheap access to any random item and
easy cheap access to current length.

Yet for Seq in general they would have to choose the implementation:
* either naive one, provoking slow ineffective coding
* or optimised complicated ones, including changing the internal data
structures as well not only code, and provoking sudden bugs in the future.

Maybe that would really be better made as an syntactic sugar - implicit
conversion lib for some carefully selected subclasses of Seq, but not the
Seq in general.
Or some trait, that only can be applied to "some carefully selected
subclasses of Seq", if this is possible.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland