www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 7177] New: $ should forward to length by default

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177

           Summary: $ should forward to length by default
           Product: D
           Version: D2
          Platform: Other
        OS/Version: Linux
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: dsimcha yahoo.com


--- Comment #0 from David Simcha <dsimcha yahoo.com> 2011-12-28 06:54:28 PST ---
See the following pull request:

https://github.com/D-Programming-Language/phobos/pull/365

Andrei and I agree that this kind of boilerplate is unacceptable.  To get the
benefits of opDollar without it, there needs to be some default behavior that
forwards to .length if no explicit opDollar exists.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 28 2011
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


Don <clugdbug yahoo.com.au> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |clugdbug yahoo.com.au


--- Comment #1 from Don <clugdbug yahoo.com.au> 2011-12-28 23:52:29 PST ---
The effect of this would be that people would declare 'length' instead of
'opDollar' in nearly all cases. This would mean that you declare opDollar if
and only if you want $ without defining 'length'. (or if $ should be different
to length). Is this what we want?
Is there anything in the existing language which behaves in this way? Or would
this be introducing an unprecedented funky behaviour?

(Just want to think through the implications, I'm not intrinsically opposed to
the idea).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 28 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


Andrei Alexandrescu <andrei metalanguage.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrei metalanguage.com


--- Comment #2 from Andrei Alexandrescu <andrei metalanguage.com> 2011-12-29
12:30:22 PST ---
I'm unclear what the best approach this is. One guiding element is that
https://github.com/D-Programming-Language/phobos/pull/365 is pure boilerplate,
which goes quite against the grain of D. It's also something that affects a lot
of ranges (essentially all that define a length).

The way I see it, we should automate things such that 1-dimensional ranges that
have a notion of "length" should define length (and opDollar should
automatically work for them), and multi-dimensional ranges with more refined
needs would define opDollar and also length.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 29 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #3 from Andrei Alexandrescu <andrei metalanguage.com> 2011-12-29
12:31:58 PST ---
Let me add that it's not impossible there are ranges that do have
multi-dimensional slicing but possibly no notion of "length". Sparse matrices
come to mind.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 29 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #4 from Don <clugdbug yahoo.com.au> 2011-12-29 13:49:15 PST ---
(In reply to comment #3)
 Let me add that it's not impossible there are ranges that do have
 multi-dimensional slicing but possibly no notion of "length". Sparse matrices
 come to mind.

Yes. Another difference is that length is generally an integer. opDollar doesn't need to be, it could be any object. It can also be cheap to calculate opDollar but expensive to determine length. I guess the question is, for what fraction of use cases will opDollar and length coincide? It seems to be true for most ranges, which is interesting because they didn't even exist when this feature was first implemented -- it was designed for matrices -- yet they're now shaping us an important use of it. I don't think that there will be much application code that uses multi-dimensional opDollar, so it doesn't matter so much if those cases have a fair bit of boilerplate. How commonly will people declare new ranges in application code? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 29 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


bearophile_hugs eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs eml.cc


--- Comment #5 from bearophile_hugs eml.cc 2011-12-29 14:53:04 PST ---
At first sight I like this proposal.

(In reply to comment #4)
 How commonly will people declare new ranges in application code?

Not often enough, I think. In Python and C#4 you define new generators and iterators quite often (using the yield keyword, and in Python using lazy list comps too), but in D they are much less handy to write. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 29 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #6 from Andrei Alexandrescu <andrei metalanguage.com> 2011-12-29
15:50:54 PST ---
(In reply to comment #4)
 (In reply to comment #3)
 Let me add that it's not impossible there are ranges that do have
 multi-dimensional slicing but possibly no notion of "length". Sparse matrices
 come to mind.

Yes. Another difference is that length is generally an integer. opDollar doesn't need to be, it could be any object. It can also be cheap to calculate opDollar but expensive to determine length. I guess the question is, for what fraction of use cases will opDollar and length coincide?

Given a value x of type T, if the user is able to write both x.length and x[0 .. $] then it should be reasonable to expect the latter is interchangeable with x[0 .. x.length].
 It seems to be true for most ranges, which is interesting because they didn't
 even exist when this feature was first implemented -- it was designed for
 matrices -- yet they're now shaping us an important use of it. I don't think
 that there will be much application code that uses multi-dimensional opDollar,
 so it doesn't matter so much if those cases have a fair bit of boilerplate.
 
 How commonly will people declare new ranges in application code?

Hard to estimate, but I suspect a fair amount (and we want to encourage that). In STL defining an iterator is an act of courage, but we'd ideally hope that people can easily define ranges that integrate with a variety of algorithms. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Dec 29 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


Jonathan M Davis <jmdavisProg gmx.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jmdavisProg gmx.com


--- Comment #7 from Jonathan M Davis <jmdavisProg gmx.com> 2012-10-30 22:07:29
PDT ---
It would be great to be able to rely on $ working with slicing with any range
type, but right now, that would require that all sliceable ranges overload
opDollar, which obviously isn't the case right now and is arguably unreasonable
to expect (especially given the boilerplate involved). So, if we're going to
require that $ work with slicing (which we really should do), then this
proposal is pretty much required.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Oct 30 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #8 from github-bugzilla puremagic.com 2012-12-17 21:38:34 PST ---
Commit pushed to master at https://github.com/D-Programming-Language/phobos

https://github.com/D-Programming-Language/phobos/commit/a0b82a53b89c69102a0ab0c2e16cbb013550c723
Add some requirements for opDollar to hasSlicing.

Ideally, opDollar would be outright required for any range with slicing,
but unless/until it's changed so that length automatically aliases to
opDollar when opDollar isn't defined (issue# 7177), that's probably not
a reasonable requirement to make.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 17 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #9 from Lionello Lunesu <lio+bugzilla lunesu.com> 2013-02-06
19:53:03 PST ---
*** Issue 2635 has been marked as a duplicate of this issue. ***

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 06 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


Kenji Hara <k.hara.pg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull


--- Comment #10 from Kenji Hara <k.hara.pg gmail.com> 2013-03-21 03:58:04 PDT
---
https://github.com/D-Programming-Language/dmd/pull/1779

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


monarchdodra gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |monarchdodra gmail.com


--- Comment #11 from monarchdodra gmail.com 2013-03-21 06:18:01 PDT ---
(In reply to comment #10)
 https://github.com/D-Programming-Language/dmd/pull/1779

I'm a bit on the fence about this. I don't think it's the compiler's job to translate $ into length. length is not a magic word, it is just a range primitive. The compiler should have no knowledge about either of these. Further more, I think it could be dangerous to forward $ to length for any indiscriminate type. Couldn't we implement this instead as a library solution, inside std.range? For example, std.array provides (pop)[front|back] for arrays. This is library, not compiler. We could have std.range provide an global opDollar function that returns it's range argument's length instead? Simply: //-------- import std.stdio; import std.range; auto opDollar(R)(auto ref R r) if (isInputRange!R && hasLength!R) { return r.length; } struct S { property { enum empty = false; int front(){return 1;} size_t length(){return 10;} } void popFront(){} int opIndex(size_t i){return i;} } void main() { S s; writeln(s[$]); } //-------- Idea being that if you call: R r; r[$ - 1]; Then: Either R defines opDollar, and everyone is happy. If not, and if range is imported, the the compiler "sees" an available std.range.opDollar function, and uses that instead. That doesn't work right now (it just says "undefined identifier __dollar"), so it would still require a bit of compiler improvement, but I think it would be a better direction to take. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #12 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-21 07:05:45
PDT ---
If you have a type which defines length and has slicing or indexing, does it
make any sense whatsoever for length _not_ to be the same as opDollar? I'd
strongly argue that any type (be it a range or otherwise) which had indexing or
slicing and had length and made opDollar something else other than length (or
length something else than one past the last index) would be very badly
designed.

If we don't make it so that length automatically aliases to opDollar if
opDollar isn't already defined, then almost every single finite random-access
range ever will have to manually alias length to opDollar, and we'll never be
able to require that ranges with slicing define opDollar, because it would
break too much code if we did.

I see no downside to this and huge problems if we don't do this. This is the
key to being able to rely on opDollar existing for ranges types that should
define it.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #13 from monarchdodra gmail.com 2013-03-21 07:18:13 PDT ---
(In reply to comment #12)
 If we don't make it so that length automatically aliases to opDollar if
 opDollar isn't already defined, then almost every single finite random-access
 range ever will have to manually alias length to opDollar, and we'll never be
 able to require that ranges with slicing define opDollar, because it would
 break too much code if we did.
 
 I see no downside to this and huge problems if we don't do this. This is the
 key to being able to rely on opDollar existing for ranges types that should
 define it.

They point of dissension here (as I see it), is that you are saying that a range must define opDollar one way or another, whereas I think all we need is for r[$ - 1]/r[0 .. $] to work. My proposal would not prevent isSliceable for checking this, any less than isInputRange says that slices are ranges. Slices have front defined externally, which allows us to use them as ranges all over the place. I don't see why we can't use the same approach with ranges and opDollar. I agree it is a HUGE boost to be able to rely on "r[0 .. $]" being legal. I just find it is kind of iffy to rely on the compiler for that... But just to be clear, I prefer this than no solution. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #14 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
07:30:56 PDT ---
(In reply to comment #12)
 If you have a type which defines length and has slicing or indexing, does it
 make any sense whatsoever for length _not_ to be the same as opDollar? I'd
 strongly argue that any type (be it a range or otherwise) which had indexing or
 slicing and had length and made opDollar something else other than length (or
 length something else than one past the last index) would be very badly
 designed.

Yes, it makes sense in some cases for opDollar not to be length. In the case of dcollections, I want opDollar to map to .end() (which is the last cursor), not .length. Please don't make $ map to .length, it will break current dcollections. Example: I allow slicing based on index for TreeMap, because indexes are in order. This code, would potentially compile, but return the unexpected slice of half the elements in the TreeMap: auto m = new TreeMap!(int, int); m[0] = 0; m[2] = 2; m[4] = 4; m[6] = 6; assert(m.length == 4); auto sl = m[0..$]; // translates to m[0..m.length]; assert(sl.walkLength() == 2); // only 2 elements! What I would like is for $ to map to m.end(). Another example is int[int]: int[int] x; x[1] = 14; x[100] = 42; assert(x[$-1] == 14); if $ maps to x.length, then it happens to coincide with x[1], but that isn't necessarily the "last" element in the AA (which is how it reads). In fact, I would argue x[$-1] shouldn't compile, it's value is meaningless. Sorry that it makes you have to add boilerplate, but I think it's incorrect to always equate length with $. The boilerplate isn't actually that bad, it's just an alias. In generated code it adds NO bloat. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #15 from Kenji Hara <k.hara.pg gmail.com> 2013-03-21 07:50:48 PDT
---
(In reply to comment #14)
 Another example is int[int]:
 
 int[int] x;
 x[1] = 14;
 x[100] = 42;
 assert(x[$-1] == 14);

That's a strong case. If compiler tries to translate $ to length automatically, library AA implementation will become impossible. I'll close my pull request. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #16 from Kenji Hara <k.hara.pg gmail.com> 2013-03-21 07:59:47 PDT
---
The idea in comment #11 is interesting, but one problem point is that current
compiler does not see UFCS fallback for operator overloading.

If we accept it, should we also accept this?

string opBinary(string op)(string s1, string s2) if (op == "+") {
    return s1 ~ s2;
}
void main() {
    assert("hello " + "world!" == "hello world!");
    // --> "hello ".opBinary!"+"("world!")    // op-overloading
    // --> .opBinary!"+"("hello ", "world!")  // UFCS
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


Steven Schveighoffer <schveiguy yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy yahoo.com


--- Comment #17 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
08:24:32 PDT ---
(In reply to comment #16)
 The idea in comment #11 is interesting, but one problem point is that current
 compiler does not see UFCS fallback for operator overloading.

That is a deficiency that is easily worked around: struct Concatable { private string str; this(string str) {this.str = str;} string opBinary(string op)(string other) if (op == "+") {return str ~ other;} } Concatable c(string s) { return Concatable(s);} auto s = "hello".c + "world";
 If we accept it, should we also accept this?
 
 string opBinary(string op)(string s1, string s2) if (op == "+") {
     return s1 ~ s2;
 }

Should we accept that this is now possible? Sure, I don't see why not, it is quite possible without additions to the language to make that a reality with a tiny insignificant annoyance. Should we accept string + string as a feature of D/phobos? No. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #18 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-21 08:27:16
PDT ---
 That's a strong case. If compiler tries to translate $ to length
 automatically, library AA implementation will become impossible.

That's not a problem at all. As long as the logic is that length is aliased to opDollar as long as opDollar isn't defined, then it won't break anything. Anything that needs to define opDollar differently will define opDollar, and for the rest, if they define length, then it gets aliased to opDollar. I really don't see the problem with that. And without this, requiring opDollar with hasSlicing will break tons of code. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #19 from monarchdodra gmail.com 2013-03-21 08:32:44 PDT ---
(In reply to comment #14)
 Yes, it makes sense in some cases for opDollar not to be length.

 [SNIP]

Note though that opDollar would *fallback* to length if you did not implement opDollar. You are still free to implement your own opDollar if you wish, so your DCollections would still be fine. (In reply to comment #15)
 (In reply to comment #14)
 Another example is int[int]:
 
 int[int] x;
 x[1] = 14;
 x[100] = 42;
 assert(x[$-1] == 14);

That's a strong case. If compiler tries to translate $ to length automatically, library AA implementation will become impossible. I'll close my pull request.

No need! Please don't close it quite yet. A simple " disable opDollar();" or "private opDollar();" should shut down this problem. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #20 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
09:11:43 PDT ---
(In reply to comment #18)
 That's a strong case. If compiler tries to translate $ to length
 automatically, library AA implementation will become impossible.

That's not a problem at all. As long as the logic is that length is aliased to opDollar as long as opDollar isn't defined, then it won't break anything. Anything that needs to define opDollar differently will define opDollar, and for the rest, if they define length, then it gets aliased to opDollar. I really don't see the problem with that. And without this, requiring opDollar with hasSlicing will break tons of code.

The point of the AA example is that opDollar should be illegal, not that it should map to something else. I don't think we need to require opDollar with hasSlicing, why would you think that? (In reply to comment #19)
 Note though that opDollar would *fallback* to length if you did not implement
 opDollar. You are still free to implement your own opDollar if you wish, so
 your DCollections would still be fine.

My point is that I have to opt out of that behavior. This means it breaks my current code.
 No need! Please don't close it quite yet. A simple " disable opDollar();" or
 "private opDollar();" should shut down this problem.

This is a good thing to bring up, but I don't really understand why opDollar needs to be implemented by default. It's only valid inside indexers, and only makes sense for indexes that are integers, begin at 0, and end at .length. Isn't that a lot of assumptions to make for opIndex, which can take any type of argument, and whose domain space can mean anything? We can prove that a type has indexing, that it has length, even possibly that it's indexer takes the same type as length returns, but I think it's too assuming to guess at the domain space of the index. Why is it so bad to explicitly alias opDollar to length? It seems we are using anecdotal evidence (phobos requires a few aliases) to apply to all code in existence and that ever will exist. An alias consumes NO code space, it's free. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #21 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
09:16:14 PDT ---
(In reply to comment #20)
 My point is that I have to opt out of that behavior.  This means it breaks my
 current code.

To expand on this point, I would say implementing opDollar by default to mean .length should be semantically correct in all existing code that defines indexing and length. If not (and I think I've shown that it's not always correct), it should not be done. It breaks too much existing code otherwise. The gain is so little since aliasing already works. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #22 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-21 09:22:30
PDT ---
 I don't think we need to require opDollar with hasSlicing, why would you think
 that?

Because if you don't, then you can never use $ when slicing a range. And really, isRandomAccessRange should require that $ work with finite ranges for the same reason. As it stands, you pretty much can't use $ in generic code. It's only good for arrays, because you can't count on it working for anything else. The appropriate range templates must be able to require them for us to be able to use them, and if we change them to require opDollar without this enhancement request, then it's going to break a lot of code. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #23 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-21 09:55:37
PDT ---
If we forgo this enhancement request, then we have two choices with regards to
ranges and $:

1. Never be able to use $ with ranges, because none of the range traits check
for it.

2. Warn people that we're going to soon require opDollar for random-access
ranges and ranges with slicing and then change isRandomAccessRange and
hasSlicing accordingly (at which point, there's bound to be a fair bit of code
which will break).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #24 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
10:14:53 PDT ---
(In reply to comment #22)
 Because if you don't, then you can never use $ when slicing a range.

This is extreme. You certainly CAN use $ with ranges that support $.
 And really, isRandomAccessRange should require that $ work with finite ranges
for
 the same reason. As it stands, you pretty much can't use $ in generic code.
 It's only good for arrays, because you can't count on it working for anything
 else.

Yes you can, it just requires the range supports $. Define supportsDollar trait. Done.
 The appropriate range templates must be able to require them for us to be
 able to use them, and if we change them to require opDollar without this
 enhancement request, then it's going to break a lot of code.

Then don't change them. Requiring $ is as simple as defining a trait that checks for $ support. There is no reason slicing has to be predicated on having an end point. And having an end point does not require having a length (see strings) and is not necessarily an integer value equivalent to the length. If, for example, we add requiring $ for isRandomAccessRange, and then have a function that requires a random access range but doesn't use $, what is the benefit of doing that? Either you need $ or you don't, and that is quantifiable with a separate trait. Support for slicing or indexing is a precondition for having $ but $ is not required in order to slice or index. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #25 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-21 10:23:01
PDT ---
I really don't think that it makes sense to define ranges with slicing which
don't have opDollar or finite random-access ranges which don't have opDollar.
And having hasOpDollar or supportsOpDollar just complicates ranges even
further. I expect that the main reason that opDollar wasn't required in the
first place was that it didn't even work until recently (though it may also
have simply been forgotten).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #26 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
10:47:03 PDT ---
(In reply to comment #25)
 I really don't think that it makes sense to define ranges with slicing which
 don't have opDollar or finite random-access ranges which don't have opDollar.

Then why is this necessary? If it only makes sense to define opDollar, then it will be defined, and you can use it.
 And having hasOpDollar or supportsOpDollar just complicates ranges even
 further.

What? How does it do anything to make ranges more complex? If anything, adding it to isRandomAccessRange makes them more complex, because now ranges that previously satisfied that trait may now not satisfy it. Defining a new trait does not make anything more complex, nothing is required to implement a new trait, because nothing currently uses that trait. No more changes are required to satisfy a new hasOpDollar trait than are required to satisfy an isRandomAccessRange trait that now requires opDollar. In fact the same code is required. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #27 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-21 11:14:37
PDT ---
 How does it do anything to make ranges more complex?

Because it makes yet another thing that range-based functions must test for. We arguably have too many such traits already. The _only_ reason I see to not require that opDollar work with ranges which have slicing and finite random-access ranges is the fact that the change will break code. IMHO, everything else about it is exactly the right thing to do. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #28 from monarchdodra gmail.com 2013-03-21 11:22:48 PDT ---
(In reply to comment #27)
 How does it do anything to make ranges more complex?

Because it makes yet another thing that range-based functions must test for. We arguably have too many such traits already. The _only_ reason I see to not require that opDollar work with ranges which have slicing and finite random-access ranges is the fact that the change will break code. IMHO, everything else about it is exactly the right thing to do.

Yeah, exactly what he said. Having yet another trait means: a) Don't test the trait and ignore opDollar. b) Test the trait and fork the code even more. Neither is satisfactory. Requiring RA and slicing to support $ is just what makes sense and is natural. Making it "yet another trait" would be wrong. Just... wrong. What we are trying to do is: a) Not break code by adding more to the requirements. b) Provide an external solution for ranges that don't define opDollar (because for a range, defining opDollar as an alias of length IS natural). And as long as we don't have this, $ is just as good as useless in generic code. The only place I know of where we use it is for popFrontN, and even then we jump through hoops to get it to work. Getting this ER to work, in one way or another, is very important for the natural and generic usage of ranges. Right around now, I'm kind of wishing I had kept my mouth shut, because I too have been waiting for this for a while :/ -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #29 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
12:47:14 PDT ---
(In reply to comment #28)
 Yeah, exactly what he said. Having yet another trait means:
 a) Don't test the trait and ignore opDollar.

By your own definition (1. we don't check for it, and 2. you can't write generic code with $), that is exactly what is done now.
 b) Test the trait and fork the code even more.

Huh? If your algorithm requires opDollar, use it. If not, then it didn't exist before. Where is the forking? I looked at isRandomAccessRange. It can be true if the range is infinite, which most likely do NOT define $. If that is the case, how can generic code use $ simply if isRandomAccessRange is true?
 What we are trying to do is:
 a) Not break code by adding more to the requirements.

Wait, I thought we are adding opDollar to the requirements?
 b) Provide an external solution for ranges that don't define opDollar (because
 for a range, defining opDollar as an alias of length IS natural).

As I previously stated, I don't have a problem with this, as long as it only applies to ranges you define, and NOT ranges or types where it makes no sense. 1. opDollar is NOT equivalent to length in all cases. Therefore, making it equivalent by default BY DEFINITION breaks existing code that purposely defines length and purposely omits opDollar. 2. Adding opDollar requirements to range traits requires all existing ranges that could define opDollar DO define opDollar. 3. You wish to avoid immediate breakage of code that has not yet implemented opDollar but satisfies current implementation of said traits. So in other words your goal is to break existing code so other existing code doesn't break? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177


timon.gehr gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr gmx.ch


--- Comment #30 from timon.gehr gmx.ch 2013-03-21 12:56:04 PDT ---
(In reply to comment #16)
 The idea in comment #11 is interesting, but one problem point is that current
 compiler does not see UFCS fallback for operator overloading.
 

Making this work enables transparent introduction of the opDollar requirement for eg. finite RandomAccessRanges.
 If we accept it, should we also accept this?
 
 string opBinary(string op)(string s1, string s2) if (op == "+") {
     return s1 ~ s2;
 }
 void main() {
     assert("hello " + "world!" == "hello world!");
     // --> "hello ".opBinary!"+"("world!")    // op-overloading
     // --> .opBinary!"+"("hello ", "world!")  // UFCS
 }

IMO yes. In any case, there is nothing in the spec that would indicate that it does not work. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #31 from timon.gehr gmx.ch 2013-03-21 13:02:41 PDT ---
(In reply to comment #24)
 (In reply to comment #22)
 ...
 the same reason. As it stands, you pretty much can't use $ in generic code.
 It's only good for arrays, because you can't count on it working for anything
 else.

Yes you can, it just requires the range supports $. Define supportsDollar trait. Done. ...

Needing to state in the template constraint that a type supports syntax sugar appears to be sub-optimal at best. (Whether or not it is used will usually be an implementation detail.) IMO adding opDollar using UFCS makes the most sense. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #32 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
13:15:39 PDT ---
(In reply to comment #31)
 Needing to state in the template constraint that a type supports syntax sugar
 appears to be sub-optimal at best. (Whether or not it is used will usually be
 an implementation detail.) IMO adding opDollar using UFCS makes the most sense.

I think the mistake here is the assumption that $ is syntax sugar. opDollar is a function, and is not required to return length, otherwise we wouldn't be having this discussion. A more semantically named trait would be hasEnd. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #33 from monarchdodra gmail.com 2013-03-21 14:14:50 PDT ---
(In reply to comment #29)
 (In reply to comment #28)
 Yeah, exactly what he said. Having yet another trait means:
 a) Don't test the trait and ignore opDollar.

By your own definition (1. we don't check for it, and 2. you can't write generic code with $), that is exactly what is done now.
 b) Test the trait and fork the code even more.

Huh? If your algorithm requires opDollar, use it. If not, then it didn't exist before. Where is the forking? I looked at isRandomAccessRange. It can be true if the range is infinite, which most likely do NOT define $. If that is the case, how can generic code use $ simply if isRandomAccessRange is true?

What's your point? isRandomAccessRange doesn't require length either. Does that mean code that tests isRandomAccessRange can't use length? That's why we usually test RA+hasLength. However, once you have an RA range that defines length, it would make little sense for r[$ - 1] to not function. Also, *sliceable* infinite ranges most definitely *do* define opDollar, and it is part of the requirements we'd like to add to *isSliceable*. Heck, at one point, it was argued that that should be the *only* requirement (int to $) This would be breaking change, but sliceable infinite is new concept, so it would break very little. And in this case, it would actually be a functional upgrade. Take a look at popFrontN's implementation for an example of how this would help tons. I have an open pull for chunks. Making slicing work trying to work around opDollar is a nightmare. Having the guarantee that r[1 .. $] works means we wouldn't even have to worry about whether or not r is finite. Or if it defines opDollar for that matter.
 What we are trying to do is:
 a) Not break code by adding more to the requirements.

Wait, I thought we are adding opDollar to the requirements?

No. What we want is that if a range is finite and random access, then writing "r[$ - 1]" should be legal. And "r[0 .. $]" should be legal for sliceables (regardless of length). That is the goal. We are discussing the how. One idea is to change the trait. What we'd want is a functionality that would allow us to do this without breaking existing code.
 b) Provide an external solution for ranges that don't define opDollar (because
 for a range, defining opDollar as an alias of length IS natural).

As I previously stated, I don't have a problem with this, as long as it only applies to ranges you define, and NOT ranges or types where it makes no sense. 1. opDollar is NOT equivalent to length in all cases. Therefore, making it equivalent by default BY DEFINITION breaks existing code that purposely defines length and purposely omits opDollar. 2. Adding opDollar requirements to range traits requires all existing ranges that could define opDollar DO define opDollar. 3. You wish to avoid immediate breakage of code that has not yet implemented opDollar but satisfies current implementation of said traits.

Ranges is a phobos concept we can define ourselves as we so wish. If you decide to adhere to the interface, but do non-sense with it, that becomes _your_ problem. In regards to *ranges*, if one defines length, but not opDollar, then it would make *0* sense for r[0 .. $] to not mean r[0 .. r.length]. If you have a "ranges [...] where it makes no sense", then it is the range that makes no sense. The range may also decide to implement it's own opDollar if it so wishes. But if it doesn't, we can do it. We do this with UFCS all the time. I don't see why we can't do it for opDollar to, either via a global function, or compiler help.
 So in other words your goal is to break existing code so other existing code
 doesn't break?

-- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #34 from timon.gehr gmx.ch 2013-03-21 14:32:09 PDT ---
(In reply to comment #32)
 (In reply to comment #31)
 Needing to state in the template constraint that a type supports syntax sugar
 appears to be sub-optimal at best. (Whether or not it is used will usually be
 an implementation detail.) IMO adding opDollar using UFCS makes the most sense.

I think the mistake here is the assumption that $ is syntax sugar. opDollar is a function, and is not required to return length, otherwise we wouldn't be having this discussion. A more semantically named trait would be hasEnd.

Ok. Still, a finite RandomAccessRange should always satisfy hasEnd. opDollar is syntax sugar. I do not think there is a halfway decent API where opDollar is not an alias to a more aptly named member. For ranges, it is length, for dcollections, it might be end, etc. If opDollar is not considered syntax sugar, you have: auto end = m.opDollar(); However, why does it even make sense to make opDollar denote end? There is no analogue for begin. m[m.begin()..m.end()] ... m[m.begin()..$] ... uh. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #35 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
18:49:56 PDT ---
(In reply to comment #34)
 opDollar is syntax sugar. I do not think there is a halfway decent API where
 opDollar is not an alias to a more aptly named member.

Maybe true. But maybe that's only true because opDollar didn't work for a long time. What about an infinite range where the "end" is not really defined, but you need something to say that the upper bound is unbounded? would that have a use case besides being used in slicing?
 However, why does it even make sense to make opDollar denote end? There is no
 analogue for begin.
 
 m[m.begin()..m.end()]
 ...
 m[m.begin()..$]
 ...

I suggested it, it was shot down. Walter seems convinced that 0 fills that role despite all attempts to explain. http://forum.dlang.org/post/op.vco5zwhreav7ka localhost.localdomain -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #36 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-21
19:42:41 PDT ---
(In reply to comment #33)
 What's your point? isRandomAccessRange doesn't require length either. Does that
 mean code that tests isRandomAccessRange can't use length? That's why we
 usually test RA+hasLength. However, once you have an RA range that defines
 length, it would make little sense for r[$ - 1] to not function.

And it probably would function. You don't need a trait to write code that expects $ to work. And even if $ DID work, it may not work the way you expect, that is, length and $ may not be equivalent. In other words, it's impossible to write a trait that says "$ must be equivalent to length." It is OK with me, however, if you want to say that a RA range with hasLength requires $ to function as length. I just don't want the compiler to assume that $ means length for all types.
 No. What we want is that if a range is finite and random access, then writing
 "r[$ - 1]" should be legal. And "r[0 .. $]" should be legal for sliceables
 (regardless of length).

r[0..$] is equivalent to r[], there is no need to require it.
 That is the goal. We are discussing the how. One idea is to change the trait.
 What we'd want is a functionality that would allow us to do this without
 breaking existing code.

Changing the trait will break existing code, making the assumption will break existing code. There is nothing that can be done I can think of that wouldn't break existing code. So if you have to break existing code, break phobos code that can be fixed in the same commit!
 Ranges is a phobos concept we can define ourselves as we so wish. If you decide
 to adhere to the interface, but do non-sense with it, that becomes _your_
 problem. In regards to *ranges*, if one defines length, but not opDollar, then
 it would make *0* sense for r[0 .. $] to not mean r[0 .. r.length]. If you have
 a "ranges [...] where it makes no sense", then it is the range that makes no
 sense.

That is fine, as I've already said. If you want to change the trait, go right ahead!
 The range may also decide to implement it's own opDollar if it so wishes. But
 if it doesn't, we can do it. We do this with UFCS all the time. I don't see why
 we can't do it for opDollar to, either via a global function, or compiler help.

Doing it in the compiler is not correct, the compiler shouldn't care what opDollar means. Otherwise, it should just make $ mean length. Ranges are a phobos concept. If you want to define it for isRandomAccessRange + hasLength only, I think that is fair too (I'm assuming here we can change the compiler to allow adding opDollar using UFCS). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #37 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-21 21:27:07
PDT ---
I think that having opDollar work with UFCS would set a bad precedent. That's
opening the door for 3rd party code to be able to overload operators on your
types, and I think that that's a pretty bad can of worms to open.

On the whole, I don't see a problem with length being aliased to opDollar if
opDollar isn't defined except for the case where you _don't_ want opDollar to
be defined, and I don't know if requiring that opDollar be explicitly disabled
in that case is a good idea or not.

If we don't implement this enhancement request though, I'm very much inclined
to put a note in the changelog (probably in red) which warns people that
hasSlicing will soon be requiring opDollar as will isRandomAccessRange for
finite ranges, so people should update their code to have opDollar (even if
it's just an alias to length) so that it doesn't break when we make the changes
in hasSlicing and isRandomAccess range in a release or two. That's not ideal,
but it would at least give people a chance to avoid the code breakage if
they're proactive.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #38 from Kenji Hara <k.hara.pg gmail.com> 2013-03-21 22:15:44 PDT
---
For the discussion, I created experimental patch for dmd and Phobos.

https://github.com/9rnsr/dmd/branches/fix7177alt
https://github.com/9rnsr/phobos/branches/fix7177alt

Automatic opDollar completion by std.range would work well.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 21 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #39 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-22
08:33:31 PDT ---
(In reply to comment #37)
 I think that having opDollar work with UFCS would set a bad precedent. That's
 opening the door for 3rd party code to be able to overload operators on your
 types, and I think that that's a pretty bad can of worms to open.

This can already be done with a wrapping type and alias this. See my earlier example. However, we can probably make opDollar a special case, it's not really an operator but a special symbol that $ gets translated into. I don't think it would be inconsistent to allow UFCS opDollar and not allow other operators via UFCS. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 22 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #40 from monarchdodra gmail.com 2013-03-22 09:05:10 PDT ---
(In reply to comment #39)
 However, we can probably make opDollar a special case, it's not really an
 operator but a special symbol that $ gets translated into.

By that logic, opBinary is not really an operator, but a special symbol "+" gets translated into. Besides, you could do very stupid stuff with opDollar the same as with any operator. //Convenience to transform a pointer into a slice: size_t opDollar(T)(T* p) { return 1; } ... void main() { int i = 1; int* p = &i; int[] s = p[0 .. $]; //Now legal! } So allowing opDollar as non-member operator could be used unsafely just the same as any other operator.
 I don't think it
 would be inconsistent to allow UFCS opDollar and not allow other operators via
 UFCS.

I'm really just questioning why we don't allow UFCS for *all* operators? Seems like a restriction when you take into account the fact that you have UFCS. After all, it can already be used to give built-in types new attributes. Why are operators different from functions? There will always be stupid users to do stupid things with code. I don't see why it should prevent us from having useful and smart tools. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 22 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #41 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-22
09:23:48 PDT ---
(In reply to comment #40)
 (In reply to comment #39)
 However, we can probably make opDollar a special case, it's not really an
 operator but a special symbol that $ gets translated into.

By that logic, opBinary is not really an operator, but a special symbol "+" gets translated into. Besides, you could do very stupid stuff with opDollar the same as with any operator.

It's most definitely not an operator, despite the name. It's a property. To say opDollar is an operator is like saying length is an operator.
 So allowing opDollar as non-member operator could be used unsafely just the
 same as any other operator.

You misunderstand, what I meant was because it's not technically an operator, we could give it special permission to allow UFCS and technically be correct saying we don't allow operator overloading with UFCS. I didn't say it would always be safe!
 I'm really just questioning why we don't allow UFCS for *all* operators? Seems
 like a restriction when you take into account the fact that you have UFCS.
 After all, it can already be used to give built-in types new attributes. Why
 are operators different from functions?

I don't have a problem with it, I was suggesting we could allow it only for opDollar as a compromise for those who feel operators shouldn't be UFCS-able. In fact, we already can add operators via type-wrapping and alias this. I don't see the issue with allowing UFCS as a cleaner solution for that. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 22 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #42 from monarchdodra gmail.com 2013-03-22 14:52:19 PDT ---
(In reply to comment #41)
 (In reply to comment #40)
 (In reply to comment #39)
 However, we can probably make opDollar a special case, it's not really an
 operator but a special symbol that $ gets translated into.

By that logic, opBinary is not really an operator, but a special symbol "+" gets translated into. Besides, you could do very stupid stuff with opDollar the same as with any operator.

It's most definitely not an operator, despite the name. It's a property. To say opDollar is an operator is like saying length is an operator.

You play on words. Both are not exclusive. It is an operator that is a property. BTW, is opUnary++ as operator? opUnary! ? In any case, I see no point in arguing over this particular point.
 So allowing opDollar as non-member operator could be used unsafely just the
 same as any other operator.

You misunderstand, what I meant was because it's not technically an operator, we could give it special permission to allow UFCS and technically be correct saying we don't allow operator overloading with UFCS. I didn't say it would always be safe!
 I'm really just questioning why we don't allow UFCS for *all* operators? Seems
 like a restriction when you take into account the fact that you have UFCS.
 After all, it can already be used to give built-in types new attributes. Why
 are operators different from functions?

I don't have a problem with it, I was suggesting we could allow it only for opDollar as a compromise for those who feel operators shouldn't be UFCS-able. In fact, we already can add operators via type-wrapping and alias this. I don't see the issue with allowing UFCS as a cleaner solution for that.

I think we are on the same page. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 22 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #43 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-22 14:56:19
PDT ---
I think that being able to do something like overload + for strings would be
very bad (which having UFCS work with overloaded operators would allow), and
the fact that there would be no way to differentiate between functions when
overloaded operators which used UFCS conflicted just makes it worse.

But opDollar is quite different from other operators (it's really not any
different from overloading any function with a particular name, since it's
quite restricted it what it's used for), so maybe it's okay for it. I'd be
quite opposed to allowing it in general though.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 22 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #44 from Andrei Alexandrescu <andrei erdani.com> 2013-03-24
08:24:46 PDT ---
I gave this long thread a read and reached a decision. Sorry for the
dictatorial approach but this seems to be a matter in which reasonable people
may disagree so at some point we need to just choose a way and stick with it.
Among my priorities in choosing a behavior is that of simplicity - we can't
require people to mind a trait such as supportsOpDollar, or require them to
define an alias for opDollar in casual ranges.

So, there are a few cases to look at. Given a type T:

1. hasLength!T || isNarrowString!T, but T does not define a member opDollar.

Then ALL uses of expr.$ in indexing expressions involving values of type T will
automatically alias themselves to expr.length. This includes UFCS, i.e. if user
code defines a module-level property length(T), then expr.$ lowers into
expr.length which in turn may lower to length(expr).

(Note that hasLength!T currently does work with UFCS.)

2. T defines opDollar.

Great - nothing to do, it's all explicit.

3. expr.length has no meaning and T does not define opDollar.

In this case there is a compile-time error.

===========

Regarding having opDollar and/or other operators work as UCSF, this would be
desirable from a completeness/expectability/consistency standpoint. I don't
quite buy the argument that that opens a can of worms. However, seeing as
there's already a compiler change for that, I suggest we go this
least-committal route for now and defer that decision for later.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #45 from Andrei Alexandrescu <andrei erdani.com> 2013-03-24
08:26:27 PDT ---
s/UCSF/UFCS/

University of California San Francisco for the win!

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #46 from Steven Schveighoffer <schveiguy yahoo.com> 2013-03-24
12:55:40 PDT ---
(In reply to comment #44)
 1. hasLength!T || isNarrowString!T, but T does not define a member opDollar.

this can be shortened to hasLength!T, all strings define $, they are arrays. The compiler shouldn't be trying to guess whether something is a narrow string or not according to phobos (or maybe I read this too literally?) The rest of this is not unreasonable, and aside from breaking current code (albeit less common current code in a non-obvious way), this proposal misses one situation: you want to define .length, but NOT opDollar. In this case, disable opDollar should be allowed (if it's not already) as monarchdodra suggested. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #47 from Andrei Alexandrescu <andrei erdani.com> 2013-03-24
13:08:46 PDT ---
(In reply to comment #46)
 (In reply to comment #44)
 1. hasLength!T || isNarrowString!T, but T does not define a member opDollar.

this can be shortened to hasLength!T, all strings define $, they are arrays. The compiler shouldn't be trying to guess whether something is a narrow string or not according to phobos (or maybe I read this too literally?)

Good point, thanks.
 The rest of this is not unreasonable, and aside from breaking current code
 (albeit less common current code in a non-obvious way), this proposal misses
 one situation:  you want to define .length, but NOT opDollar.  In this case,
  disable opDollar should be allowed (if it's not already) as monarchdodra
 suggested.

Yah, I was thinking of private or disable'd symbols as "defined". Good to clarify that. Kenji, shall we go for this? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #48 from monarchdodra gmail.com 2013-03-24 13:47:32 PDT ---
(In reply to comment #47)
 (In reply to comment #46)
 (In reply to comment #44)
 1. hasLength!T || isNarrowString!T, but T does not define a member opDollar.

this can be shortened to hasLength!T, all strings define $, they are arrays. The compiler shouldn't be trying to guess whether something is a narrow string or not according to phobos (or maybe I read this too literally?)

Good point, thanks.
 The rest of this is not unreasonable, and aside from breaking current code
 (albeit less common current code in a non-obvious way), this proposal misses
 one situation:  you want to define .length, but NOT opDollar.  In this case,
  disable opDollar should be allowed (if it's not already) as monarchdodra
 suggested.

Yah, I was thinking of private or disable'd symbols as "defined". Good to clarify that. Kenji, shall we go for this?

I apologize, but this isn't clear to me. I understand the what/why of the goal, but I don't understand the how? Is it the compiler that is translating $ to length? Then if so, how does "hasLength!T" come into play? Or are we doing this "via" the compiler as a workaround until we can implement opDollar as non-member? (since you mentioned the possibility of allowing non-member operators) I'm sorry, I just want to fully understand which direction we are taking. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #49 from Andrei Alexandrescu <andrei erdani.com> 2013-03-24
14:51:44 PDT ---
 I apologize, but this isn't clear to me. I understand the what/why of the goal,
 but I don't understand the how? Is it the compiler that is translating $ to
 length?

Yes.
Then if so, how does "hasLength!T" come into play?

Whenever I wrote "hasLength!T" I meant "The expression (expr).length exists for expr of type T".
 Or are we doing this "via" the compiler as a workaround until we can implement
 opDollar as non-member? (since you mentioned the possibility of allowing
 non-member operators)

I'm thinking of putting this decision in the compiler for now, it's the least committal change. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #50 from Kenji Hara <k.hara.pg gmail.com> 2013-03-24 17:52:41 PDT
---
(In reply to comment #47)
  Kenji, shall we go for this?

I always think that is not good to enforce particular semantics to the user programs. This enhancement violates the rule, and we already have an example that we should not do it (AA and containers like that). (I know we already have special treatement for ranges - foreach can recognize the object with input range primitives is iterable. But this enhancement just only works for random access range. It is too specialized.) And I found that this is not sufficient - it does not work for infinite forward range! https://github.com/9rnsr/phobos/commit/dd0d4c139828013c34e76acc74884341f31db298#L0R1379 struct IFR // infinite forward range { enum empty = false; property front() { return 1; } auto popFront() {} property save() { return this; } auto opSlice(size_t b, size_t e) { return this.take(e - b); } auto opSlice(size_t b, Infinity) { return this; } } IFR does not have 'length' primitive, but should be slicable like r[n .. $]; (see std.range.hasSlicing definition) But this enhancement cannot cover this - therefore user defined IFR should always define their own opDollar. So, I think the combination of std.range.opDollar and UFCS would be much better than compiler's implicit alias just only for 'length' primitive. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #51 from Kenji Hara <k.hara.pg gmail.com> 2013-03-24 17:56:57 PDT
---
(In reply to comment #49)
 I'm thinking of putting this decision in the compiler for now, it's the least
 committal change.

To make my suggestion "committal change", I posted it as a pull request. https://github.com/D-Programming-Language/dmd/pull/1793 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 24 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #52 from monarchdodra gmail.com 2013-03-25 03:53:11 PDT ---
(In reply to comment #50)
 And I found that this is not sufficient - it does not work for
 infinite forward range!
 
 https://github.com/9rnsr/phobos/commit/dd0d4c139828013c34e76acc74884341f31db298#L0R1379
 
     struct IFR  // infinite forward range
     {
         enum empty = false;
          property front() { return 1; }
         auto popFront() {}
 
          property save() { return this; }
 
         auto opSlice(size_t b, size_t e) { return this.take(e - b); }
         auto opSlice(size_t b, Infinity) { return this; }
     }
 
 IFR does not have 'length' primitive, but should be slicable like r[n .. $];
 (see std.range.hasSlicing definition) But this enhancement cannot cover this
 - therefore user defined IFR should always define their own opDollar.
 
 So, I think the combination of std.range.opDollar and UFCS would be much better
 than compiler's implicit alias just only for 'length' primitive.

Well, I think the compiler can't do *everything* for the user. If you want an infinite range to adhere to "hasSlicing", then at the very least, it has to implement the slicing primitive. The notion of "slice-able infinite range" has always been ambiguous, but IMO, "slice to end" primitive is the important one that *must* be implemented and checked. I'd doubt we'd break much code enforcing this. Besides, at worst, ranges that can't be sliced to end would seize being considered sliceable, which, IMO, is a good thing anyways. I think we should make this change (for which there would be no automatic workaround) sooner rather than later. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 25 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #53 from Jonathan M Davis <jmdavisProg gmx.com> 2013-03-26 19:22:26
PDT ---
Implementing it in the language has the advantage of avoiding making it so that
opDollar works with UFCS and avoids the risk of someone overloading opDollar in
another module and causing stuff to break when it clashes with the one in
std.range. It has the disadvantage of not working for infinite ranges while
also making $ mean length in cases when we don't want it to, forcing us to
 disable it.

Implementing it in the library has the advantage of making it only work with
ranges (unless another overload of opDollar is created for non-ranges) and
making it so that it works with infinite ranges. But it has the disadvantage of
allowing opDollar to be used with UFCS and risks conflicts if other code also
overloads it that way.

However, even if we go with the library route, opSlice will still have to
explicitly support the type that opDollar returns, so it can't really be
supported automatically for infinite ranges. We just save them the trouble of
actually aliasing the type to opDollar and make it so that there's a standard
type to use with infinite ranges and opDollar (which we could already do by
simply declaring something like std.range.InfiniteDollar with the idea that all
infinite ranges with slicing would alias it to opDollar and use it with
opSlice).

So, I don't think that it really matters which way we go as far as infinite
ranges go. In either case, some work is required to support it, and requiring
opDollar on infinite ranges with slicing will break code (though likely not a
lot, since infinite ranges are likely to be a lot rarer than finite ones, and
sliceable ones even more so).

I think that it mainly comes down to whether we'd rather require that types
with length in addition to opIndex and/or opSlice  disable opDollar if they
don't want it, or whether we'd rather risk 3rd party code defining opDollar as
a free function, causing conflicts with std.range.opDollar (conflicts which
wouldn't be  resolvable in the normal fashion, because $ is an operator, and
you can use an import path with it without explicitly calling opDollar). Beyond
that, I don't think that it matters much which route we take (though I do worry
somewhat that making opDollar UFCS-able would open the door to making other
operators UFCS-able, which I think would be a big mistake; but we wouldn't
actually be required to do that if we made opDollar UFCS-able), as beyond that,
the two routes seem pretty much functionally equivalent.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 26 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #54 from monarchdodra gmail.com 2013-03-27 10:43:35 PDT ---
I think I agree that implementing it in the language is a better choice. For
one, it means $ will *always* work, as opposed to having to import std.range
just to expect generic code to work. As long as it's properly documented, I
don't really view the length => $ conversion problematic. Yes, it allows
illegal code to compile, but doesn't break anything existing (except for
strange static ifs?), and we would be giving users a way to prevent it.

I don't view that it wouldn't work "out of the box" with infinite ranges as
problematic. There is really no way around the fact that for an infinite range
to support "slice to end", it must implement it via a "DollarToken" approach,
which pretty much means the code *has* to be deployed. So there is no way to
"accidently" forget opDollar.

--------

That said, if we do go ahead and implement this, I STRONGLY urge we enforce
"hasSlicing" => "can slice to end", even for infinite ranges. Having used
infinite ranges in phobos, I can say that:
1. A *LOT* of the slicing that occurs is very often of the form r[i .. $].
2. A *LOT* of algorithms in phobos would naturally support sliceable infinite
ranges with no extra code, if they could rely on being able to write r[i .. $].

Being able *reliably* slice *finite* ranges with opDollar is only half of what
we need.

I don't think this would break a lot of code as:
1. We are modifying a *trait*, so code that slices would not actually be broken
2. Most of *our* algorithms have fall-backs should a range seize to be
sliceable.
3. There are very little infinite ranges anyways

 jmdavis: Would you be willing to go forward with such a change? You said "I'm
very much inclined to put a note in the changelog (probably in red) [...]"
would you be inclined to do such a note for only infinite ranges?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 27 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #55 from Andrei Alexandrescu <andrei erdani.com> 2013-03-31
09:41:17 PDT ---
(In reply to comment #50)
 (In reply to comment #47)
  Kenji, shall we go for this?

I always think that is not good to enforce particular semantics to the user programs. This enhancement violates the rule, and we already have an example that we should not do it (AA and containers like that). (I know we already have special treatement for ranges - foreach can recognize the object with input range primitives is iterable. But this enhancement just only works for random access range. It is too specialized.)

Kenji: I'm a bit unclear on your view on this. You mention you'd prefer a library solution but your pull request seems to go for a in-compiler solution.
 And I found that this is not sufficient - it does not work for
 infinite forward range!
 
 https://github.com/9rnsr/phobos/commit/dd0d4c139828013c34e76acc74884341f31db298#L0R1379
 
     struct IFR  // infinite forward range
     {
         enum empty = false;
          property front() { return 1; }
         auto popFront() {}
 
          property save() { return this; }
 
         auto opSlice(size_t b, size_t e) { return this.take(e - b); }
         auto opSlice(size_t b, Infinity) { return this; }
     }
 
 IFR does not have 'length' primitive, but should be slicable like r[n .. $];
 (see std.range.hasSlicing definition) But this enhancement cannot cover this
 - therefore user defined IFR should always define their own opDollar.

There is no intent to cover infinite forward ranges with default behavior. Again, the primary goal here should be, I think, to make code defining casual ranges easy and boilerplate-free. Infinite ranges or ranges that don't define length yet want to define slicing through to the end are comparatively rare. It is reasonable to request people defining those to define opDollar appropriately.
 So, I think the combination of std.range.opDollar and UFCS would be much better
 than compiler's implicit alias just only for 'length' primitive.

If we go for a library solution, we should define opDollar in object.d so it's available by default. It should look something like this (in the 1-dimensional case): auto ref opDollar(R)(auto ref R r) if (is(typeof(r.length))) { return r.length; } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 31 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #56 from Kenji Hara <k.hara.pg gmail.com> 2013-03-31 10:21:20 PDT
---
(In reply to comment #55)
  Kenji: I'm a bit unclear on your view on this. You mention you'd prefer a
 library solution but your pull request seems to go for a in-compiler solution.

As Steven already mentioned in comment#14, automatically forwarding from $ to 'length' would break user-defined containers. The fact clearly represents that we cannot always regard $ as "length". Indeed, it is true in built-in arrays and range concept, but isn't true in associative arrays and some user-defined containers. So I think that this enhancement has a bias toward range concept. And, as far as possible, compiler should be a neutral. In other words, this is just reasonable for std.range users. Most of D programmers would use std.range, but not all.
 There is no intent to cover infinite forward ranges with default behavior.
 Again, the primary goal here should be, I think, to make code defining casual
 ranges easy and boilerplate-free. Infinite ranges or ranges that don't define
 length yet want to define slicing through to the end are comparatively rare. It
 is reasonable to request people defining those to define opDollar
 appropriately.

I don't mention that infinite range _should_ have r[n..$], rather mention that it is possible.
 If we go for a library solution, we should define opDollar in object.d so it's
 available by default. It should look something like this (in the 1-dimensional
 case):

     auto ref opDollar(R)(auto ref R r) if (is(typeof(r.length))) {
         return r.length;
     }

This is bad. druntime should not have things for range concept. It is a job of std.range. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 31 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #57 from Andrei Alexandrescu <andrei erdani.com> 2013-03-31
11:04:45 PDT ---
(In reply to comment #56)
 (In reply to comment #55)
  Kenji: I'm a bit unclear on your view on this. You mention you'd prefer a
 library solution but your pull request seems to go for a in-compiler solution.

As Steven already mentioned in comment#14, automatically forwarding from $ to 'length' would break user-defined containers.

I don't think there's any breakage. My understanding is that those containers already need to define opDollar. If opDollar is defined there is no change in semantics.
 The fact clearly represents that we cannot always regard $ as "length".
 Indeed, it is true in built-in arrays and range concept, but isn't true in
 associative arrays and some user-defined containers. So I think that this
 enhancement has a bias toward range concept.

I'd have quite a bit of difficulty agreeing with this. The notion that "$" is a synonym for "length" predates ranges and has been there for strings and arrays ever since they were defined. On the contrary, I'd argue that notions such as length-less ranges and infinite ranges contributed to the notion that opDollar may be (rarely) something distinct from length.
 And, as far as possible, compiler should be a neutral.

That shouldn't be done to a fault, either. The D language is not neutral on user-defined expr++ vs. ++expr; it forces both to have similar semantics to their built-in counterparts. In contrast, the C++ language allows defining ++expr and expr++ with different semantics. But wait, it's worse: (a) C++ forces a net loss of efficiency for expr++ barring heroic optimization efforts that are not generally applicable, and (b) C++ requires actual boilerplate to ensure both variants work. I think it is plain that C++ made the wrong decision and D learned from it and made the right decision. Similarly, we should not require boilerplate for $ just to convince it to do what it's always done for arrays and strings. Associative arrays and user-defined containers are free to disable it or define it, depending on what's most useful for them.
 In other words, this is just reasonable for std.range users. Most of D
 programmers would use std.range, but not all.

Again, I find it very difficult to agree with this. $ has always been length wherever meaningful - long before ranges came up.
 I don't mention that infinite range _should_ have r[n..$], rather mention that
 it is possible.

Yes, and defaulting $ to length does not prevent that. Again, if a range does define opDollar, that will always be chosen. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 31 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #58 from Kenji Hara <k.hara.pg gmail.com> 2013-03-31 12:09:31 PDT
---
(In reply to comment #57)
 I don't think there's any breakage. My understanding is that those containers
 already need to define opDollar. If opDollar is defined there is no change in
 semantics.

No. This enhancement will suddenly change a "correctly invalid" code to "accepts-invalid". SparseArray a; // SparseArray does not have opDollar, // because it is unnecessary now. auto n = a.length; // actually contains element count, or maximum index number a[$-1]; // now: Error: undefined identifier __dollar // after: incorrectly translated to a[a.length-1]; Finally SparseArray's author should add disable opDollar().
 The fact clearly represents that we cannot always regard $ as "length".
 Indeed, it is true in built-in arrays and range concept, but isn't true in
 associative arrays and some user-defined containers. So I think that this
 enhancement has a bias toward range concept.

I'd have quite a bit of difficulty agreeing with this. The notion that "$" is a synonym for "length" predates ranges and has been there for strings and arrays ever since they were defined.

"$" is a synonym for "length" in D - yes. But, **in general**, "$" is not a synonym for "length". The difference is important. The advantage of UFCS and std.range.opDollar approach is that is "opt-in" for the "$" meaning. It does not change the meaning of current existing code. (Again, "change" == "currently invalid/meaningless code will be changed to acceptable, potentially and unintendedly") On the other hand, your compiler approach is "opt-out". It moves boilerplate code from all range definition to SparseArray definition. This is unacceptable to me.
 And, as far as possible, compiler should be a neutral.

That shouldn't be done to a fault, either. The D language is not neutral on user-defined expr++ vs. ++expr; it forces both to have similar semantics to their built-in counterparts. In contrast, the C++ language allows defining ++expr and expr++ with different semantics. But wait, it's worse: (a) C++ forces a net loss of efficiency for expr++ barring heroic optimization efforts that are not generally applicable, and (b) C++ requires actual boilerplate to ensure both variants work. I think it is plain that C++ made the wrong decision and D learned from it and made the right decision.

It is entirely different thing.
 Similarly, we should not require boilerplate for $ just to convince it to do
 what it's always done for arrays and strings. Associative arrays and
 user-defined containers are free to disable it or define it, depending on
 what's most useful for them. 

Why you enforce disabling opDollar to other container authors? It is equivalent to enforce writing "alias opDollar = length;` to all range authors. I cannot see any difference there. If you favor the former, I can say it is definitely a kind of bias. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 31 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #59 from Andrei Alexandrescu <andrei erdani.com> 2013-03-31
17:30:22 PDT ---
(In reply to comment #58)
 (In reply to comment #57)
 I don't think there's any breakage. My understanding is that those containers
 already need to define opDollar. If opDollar is defined there is no change in
 semantics.

No. This enhancement will suddenly change a "correctly invalid" code to "accepts-invalid". SparseArray a; // SparseArray does not have opDollar, // because it is unnecessary now. auto n = a.length; // actually contains element count, or maximum index number a[$-1]; // now: Error: undefined identifier __dollar // after: incorrectly translated to a[a.length-1]; Finally SparseArray's author should add disable opDollar().

Understood. I would argue that behavior changes from "invalid" to "valid and correct". I think it would be hard to find one D programmer who'd write s[$ - 1] and expect it to be anything else than a[a.length - 1]. This behavior has been built in forever. Whether SparseArray should support operator [] and length are separate questions. If it does, and if anyone ever writes a[$ - 1], that should be correct code and there is no other possible semantics than a[a.length - 1].
 I'd have quite a bit of difficulty agreeing with this. The notion that "$" is a
 synonym for "length" predates ranges and has been there for strings and arrays
 ever since they were defined.

"$" is a synonym for "length" in D - yes. But, **in general**, "$" is not a synonym for "length". The difference is important.

Agreed.
 The advantage of UFCS and std.range.opDollar approach is that is "opt-in" for
 the "$" meaning. It does not change the meaning of current existing code.
 (Again, "change" == "currently invalid/meaningless code will be changed to
 acceptable, potentially and unintendedly")

I'd say the change is to a behavior that has a null surprise factor. If anyone writes a[$ - 1] or whatnot, it is clear what they meant and what they expect.
 On the other hand, your compiler approach is "opt-out". It moves boilerplate
 code from all range definition to SparseArray definition. This is unacceptable
 to me.

Let me submit for your consideration that (a) it's undecided whether that's bad for SparseArray, and (b) the vast majority of ranges simply want opDollar be the same as length. This is the case for all of Phobos, and this bug originated in wake of a large diff that added very many "alias length opDollar;" to virtually all ranges that support [] and length. It's just what everybody expects. I would argue we can't afford to make everybody pay for the sake of a rare occurrence.
 And, as far as possible, compiler should be a neutral.

That shouldn't be done to a fault, either. The D language is not neutral on user-defined expr++ vs. ++expr; it forces both to have similar semantics to their built-in counterparts. In contrast, the C++ language allows defining ++expr and expr++ with different semantics. But wait, it's worse: (a) C++ forces a net loss of efficiency for expr++ barring heroic optimization efforts that are not generally applicable, and (b) C++ requires actual boilerplate to ensure both variants work. I think it is plain that C++ made the wrong decision and D learned from it and made the right decision.

It is entirely different thing.

I agree it is a different thing. I was replying to the part with "As far as possible, compiler should be neutral" by simply showing that sometimes being neutral is exactly the wrong thing to do.
 Similarly, we should not require boilerplate for $ just to convince it to do
 what it's always done for arrays and strings. Associative arrays and
 user-defined containers are free to disable it or define it, depending on
 what's most useful for them. 

Why you enforce disabling opDollar to other container authors?

I think most container authors will benefit of that behavior.
 It is equivalent
 to enforce writing "alias opDollar = length;` to all range authors.
 I cannot see any difference there. If you favor the former, I can say it is
 definitely a kind of bias.

Yes, there is a bias - frequency. My core argument is that the vast majority of ranges simply want $ and length to mean the same thing, and very few need to have them mean different things. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 31 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #60 from bearophile_hugs eml.cc 2013-03-31 18:16:21 PDT ---
(In reply to comment #59)

 Yes, there is a bias - frequency. My core argument is that the vast majority of
 ranges simply want $ and length to mean the same thing, and very few need to
 have them mean different things.

I have lost part of the track of this long thread. Adding one alias to a whole class/struct container is a really small amount of simple boilerplate code. So I think having to add it is not bad. On the other hand in most cases such alias is desired, so it's good for it to be the default, and have some syntax (even a longish one) to disallow it in the rare cases when it's not desired. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Mar 31 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #61 from timon.gehr gmx.ch 2013-04-01 01:37:34 PDT ---
(In reply to comment #59)
 ...
 
 Yes, there is a bias - frequency. My core argument is that the vast majority of
 ranges simply want $ and length to mean the same thing, and very few need to
 have them mean different things.

His proposal is to make it work for all ranges. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #62 from Andrei Alexandrescu <andrei erdani.com> 2013-04-01
05:19:35 PDT ---
(In reply to comment #61)
 (In reply to comment #59)
 ...
 
 Yes, there is a bias - frequency. My core argument is that the vast majority of
 ranges simply want $ and length to mean the same thing, and very few need to
 have them mean different things.

His proposal is to make it work for all ranges.

Not sure I understand. It's possible I am confused. Could you please summarize what you mean giving some more context? Thanks. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #63 from timon.gehr gmx.ch 2013-04-01 16:11:54 PDT ---
(In reply to comment #62)
 (In reply to comment #61)
 (In reply to comment #59)
 ...
 
 Yes, there is a bias - frequency. My core argument is that the vast majority of
 ranges simply want $ and length to mean the same thing, and very few need to
 have them mean different things.

His proposal is to make it work for all ranges.

Not sure I understand. It's possible I am confused. Could you please summarize what you mean giving some more context? Thanks.

Your proposal is to make opDollar refer to length whenever there is a length, auto ref opDollar(R)(auto ref R r) if (is(typeof(r.length))) { return r.length; } by default allowing things like: int[int] x = [1:0,3:2]; x[$]=1; assert(x==[1:0,2:1,3:2]); As far as I understand it, his proposal is to restrict $ to ranges. auto ref opDollar(R)(auto ref R r) if (isInputRange!R && hasLength!R) { return r.length; } std.range vs. object.d is a separate issue. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #64 from timon.gehr gmx.ch 2013-04-01 16:13:22 PDT ---
(In reply to comment #63)
 ...
 
 As far as I understand it, his proposal is to restrict $ to ranges.
 ...

Unlucky formulation. It should read "to restrict the default opDollar to ranges". -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 01 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #65 from Andrei Alexandrescu <andrei erdani.com> 2013-04-02
04:06:03 PDT ---
(In reply to comment #63)
 Your proposal is to make opDollar refer to length whenever there is a length,
 
     auto ref opDollar(R)(auto ref R r) if (is(typeof(r.length))) {
         return r.length;
     }

Well whenever there's a length and [].
 by default allowing things like:
 
     int[int] x = [1:0,3:2];
     x[$]=1;
 
     assert(x==[1:0,2:1,3:2]);

That's not necessarily the case. Under the proposed semantics built-in hash tables would disable opDollar. BTW disabling opDollar should mean "pass through". Consider: import std.stdio; void main(){ int[size_t] a; int[] b = [ 1, 2, 3, 4, 5 ]; a[5] = 1; a[2] = 2; writeln(b[a[a.length]]); writeln(b[a[b.length]]); writeln(b[a[$]]); } This program prints "3 2 2" so the $ is transparently interpreted as the array's length. I'm not a fan of that particular behavior, but probably we need to preserve it.
 As far as I understand it, his proposal is to restrict $ to ranges.
 
     auto ref opDollar(R)(auto ref R r) if (isInputRange!R && hasLength!R) {
         return r.length;
     }
 
 std.range vs. object.d is a separate issue.

Is that correct, Kenji? (I don't think we should mix ranges into this without necessity.) -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 02 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #66 from Kenji Hara <k.hara.pg gmail.com> 2013-04-02 04:30:35 PDT
---
(In reply to comment #65)
 BTW disabling opDollar should mean "pass through". Consider:

I think it would introduce one more "special case" in operator overloading mechanism. I hate special rules.
 As far as I understand it, his proposal is to restrict $ to ranges.
 
     auto ref opDollar(R)(auto ref R r) if (isInputRange!R && hasLength!R) {
         return r.length;
     }
 
 std.range vs. object.d is a separate issue.

Is that correct, Kenji? (I don't think we should mix ranges into this without necessity.)

Yes. It is correct. See my experimental implementation.
 https://github.com/9rnsr/dmd/branches/fix7177alt
 https://github.com/9rnsr/phobos/branches/fix7177alt

https://github.com/9rnsr/phobos/commit/dd0d4c139828013c34e76acc74884341f31db298#L0R1326 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 02 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #67 from Andrei Alexandrescu <andrei erdani.com> 2013-04-02
07:47:20 PDT ---
(In reply to comment #66)
 (In reply to comment #65)
 BTW disabling opDollar should mean "pass through". Consider:

I think it would introduce one more "special case" in operator overloading mechanism. I hate special rules.
 As far as I understand it, his proposal is to restrict $ to ranges.
 
     auto ref opDollar(R)(auto ref R r) if (isInputRange!R && hasLength!R) {
         return r.length;
     }
 
 std.range vs. object.d is a separate issue.

Is that correct, Kenji? (I don't think we should mix ranges into this without necessity.)

Yes. It is correct. See my experimental implementation.

I agree this is a good counter-argument to my proposed approach.
 https://github.com/9rnsr/dmd/branches/fix7177alt
 https://github.com/9rnsr/phobos/branches/fix7177alt

https://github.com/9rnsr/phobos/commit/dd0d4c139828013c34e76acc74884341f31db298#L0R1326

I think this is a good compromise. Unless there are other issues found by others, I agree moving forward with this. More thoughts? -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 02 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #68 from Andrei Alexandrescu <andrei erdani.com> 2013-04-02
07:48:14 PDT ---
(In reply to comment #67)
 (In reply to comment #66)
 (In reply to comment #65)
 BTW disabling opDollar should mean "pass through". Consider:

I think it would introduce one more "special case" in operator overloading mechanism. I hate special rules.


I meant to insert "I agree this is a good counter-argument to my proposed approach." here! -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 02 2013
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #69 from monarchdodra gmail.com 2013-04-02 08:13:42 PDT ---
(In reply to comment #67)
 (In reply to comment #66)
 
 https://github.com/9rnsr/phobos/commit/dd0d4c139828013c34e76acc74884341f31db298#L0R1326

I think this is a good compromise. Unless there are other issues found by others, I agree moving forward with this. More thoughts?

So to wrap things up, both for myself or those who have lost track: What we are finally doing is allowing opDollar (and only opDollar) to be implemented UFCS style, correct? Then, inside std.range, we provide a "global range" opDollar function. This will mean that ranges (and only ranges) will have $ => length? Is this correct so far? And in the special case of infinite ranges, it will convert to an empty object (Infinity)? Sounds good to me. We'll just have to keep in mind that: a) $ will be automatically provided *only* if the user imports std.range (failure to import it will mean failure to use opDollar) b) Implementations may still want to explicitly provide the alias, for "native" opDollar: std.range.opDollar will only be "fall back" implementation. To be frank, I'm 100% fine with that. Other than that: Nitpick time! 1) The "Infinity" struct name is pretty vague. J.M. Davis and I have been using the term "DollarToken" so far. Any chance we use that instead? It has the advantage of being bound to the word "dollar". It can also be used for non-infinite ranges that still want to exploit end slicing. 2) I think providing opDollar for InputRanges (as opposed to ForwardRange) is better. I don't see why we'd want to go out of our way to cripple InputRanges. That's it. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Apr 02 2013
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=7177



--- Comment #70 from Steven Schveighoffer <schveiguy yahoo.com> 2013-04-03
08:36:58 PDT ---
FWIW, if it's not apparent from all I've said in the past, I'm on board with
the proposed compromise.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Apr 03 2013