May 01, 2012
On Tuesday, 1 May 2012 at 14:31:25 UTC, Alex Rønne Petersen wrote:
>
> 1) So because some people might use a feature incorrectly due to lack of knowledge in algorithms and data structures, we should cripple the language?

It's not crippling the language. Nothing prevents you from writing a loop.
Or using a library find function that does the same thing. But the name "find" gives you a hint that it's not magical and that it has a cost, while with "if( foo in bar)", it is too easy to forget that we are actually potentially performing an O(n) operation. In an AA, the 'in' keyword performs a O(1) operation, so that's ok to use it as a syntactic sugar.


May 01, 2012
On 01-05-2012 16:41, SomeDude wrote:
> On Tuesday, 1 May 2012 at 14:31:25 UTC, Alex Rønne Petersen wrote:
>>
>> 1) So because some people might use a feature incorrectly due to lack
>> of knowledge in algorithms and data structures, we should cripple the
>> language?
>
> It's not crippling the language. Nothing prevents you from writing a loop.
> Or using a library find function that does the same thing. But the name
> "find" gives you a hint that it's not magical and that it has a cost,
> while with "if( foo in bar)", it is too easy to forget that we are
> actually potentially performing an O(n) operation. In an AA, the 'in'
> keyword performs a O(1) operation, so that's ok to use it as a syntactic
> sugar.
>
>

No, it is not an O(1) operation, it is *close* to O(1) (as much sense as that statement can make). I don't know why you associate any particular complexity with 'in' in the first place. And I do think we're crippling the language, considering Python (and probably other languages) has had this feature since forever.

I'm seriously worried. It seems to me like we're trying to cater to people who can't reason about the types in their program and the complexities of performing various operations on them. Since when did algorithmic complexity become a reason to take away syntax sugar?

-- 
- Alex
May 01, 2012
On Tuesday, May 01, 2012 16:31:25 Alex Rønne Petersen wrote:
> 1) So because some people might use a feature incorrectly due to lack of knowledge in algorithms and data structures, we should cripple the language?

If in is not restricted to a particular level Big-O complexity, then you cannot safely use it in generic code. That's why all of the functions in std.container give their Big-O complexity.

In C++ [] is supposed to be O(log n) at worst. I would expect it to be the same in D, and since in is doing essentially the same operation, I would expect it to have the same Big-O complexity.

No, nothing is stopping a programmer from giving it horrible complexity, but the standard library and language should _definitely_ stick to O(log n) worst case for in and []. It would be a disaster for generic algorithms if in worked on normal arrays, because it would not be possible to maintain the required Big-O complexity.

- Jonathan M Davis
May 01, 2012
On Tuesday, 1 May 2012 at 14:41:43 UTC, SomeDude wrote:
> On Tuesday, 1 May 2012 at 14:31:25 UTC, Alex Rønne Petersen wrote:
>>
>> 1) So because some people might use a feature incorrectly due to lack of knowledge in algorithms and data structures, we should cripple the language?
>
> It's not crippling the language. Nothing prevents you from writing a loop.
> Or using a library find function that does the same thing. But the name "find" gives you a hint that it's not magical and that it has a cost, while with "if( foo in bar)", it is too easy to forget that we are actually potentially performing an O(n) operation. In an AA, the 'in' keyword performs a O(1) operation, so that's ok to use it as a syntactic sugar.

I remember this was the argument Andrei also came up. Still can't
make any sense out of it. If someone have some detailed reference
please share! If you have it just for a niche usage, why do you
have it at all? With UFCS "bar.contains(foo)" precise enough.

You can make same argument for every operator in any language if
you have operator overloading. And it would be against operator
overloading, not particularly "in".

--
Didn't know "http://forum.dlang.org/" adopted that
unreadable/annoying to no end captchas.
May 01, 2012
On 01-05-2012 19:09, Jonathan M Davis wrote:
> On Tuesday, May 01, 2012 16:31:25 Alex Rønne Petersen wrote:
>> 1) So because some people might use a feature incorrectly due to lack of
>> knowledge in algorithms and data structures, we should cripple the language?
>
> If in is not restricted to a particular level Big-O complexity, then you
> cannot safely use it in generic code. That's why all of the functions in
> std.container give their Big-O complexity.

I don't think 'in' is actually used in any generic code (other than code specifically written for AAs, in which it *does* have a specific complexity in any case).

I know I wouldn't use 'in' in truly generic code in any case, exactly because it has no defined complexity (even today; it's overloadable just like most other binary operators).

>
> In C++ [] is supposed to be O(log n) at worst. I would expect it to be the
> same in D, and since in is doing essentially the same operation, I would
> expect it to have the same Big-O complexity.

This is a good point, but not one I would subscribe to; it only holds true if you consider 'in' to be an operation purely limited to AAs. But this is already not the case given that it can be overloaded. So, I don't think that it having different complexity for arrays is a big deal.

Personally, I consider 'in' to be syntax sugar for the language user. To me, it does not seem like a feature that a library of generic algorithms should be using at all.

>
> No, nothing is stopping a programmer from giving it horrible complexity, but
> the standard library and language should _definitely_ stick to O(log n) worst
> case for in and []. It would be a disaster for generic algorithms if in worked
> on normal arrays, because it would not be possible to maintain the required
> Big-O complexity.

I agree that any overload of [] and 'in' that Phobos does should stick to that constraint when possible (I say when possible, because sometimes innovative uses of these operators can't stick to this rather strict and mundane constraint; consider for example interaction with a database or what do I know...).

But again, I don't think 'in' is something a generic algorithm should be using. We have the functions in std.algorithm and std.container if we need to write generic code.

Also, I don't think language design should be *too* biased by the standard library's preferences. Not everyone agrees with Phobos conventions and we have to respect that IMHO. Just because it's a standard library doesn't mean that it should dictate users of the language who don't use the standard library.

>
> - Jonathan M Davis

-- 
- Alex
May 01, 2012
On Tuesday, 1 May 2012 at 17:50:38 UTC, Alex Rønne Petersen
wrote:
> On 01-05-2012 19:09, Jonathan M Davis wrote:
>> On Tuesday, May 01, 2012 16:31:25 Alex Rønne Petersen wrote:
>>> 1) So because some people might use a feature incorrectly due to lack of
>>> knowledge in algorithms and data structures, we should cripple the language?
>>
>> If in is not restricted to a particular level Big-O complexity, then you
>> cannot safely use it in generic code. That's why all of the functions in
>> std.container give their Big-O complexity.
>
> I don't think 'in' is actually used in any generic code (other than code specifically written for AAs, in which it *does* have a specific complexity in any case).
>
> I know I wouldn't use 'in' in truly generic code in any case, exactly because it has no defined complexity (even today; it's overloadable just like most other binary operators).
>
>>
>> In C++ [] is supposed to be O(log n) at worst. I would expect it to be the
>> same in D, and since in is doing essentially the same operation, I would
>> expect it to have the same Big-O complexity.
>
> This is a good point, but not one I would subscribe to; it only holds true if you consider 'in' to be an operation purely limited to AAs. But this is already not the case given that it can be overloaded. So, I don't think that it having different complexity for arrays is a big deal.
>
> Personally, I consider 'in' to be syntax sugar for the language user. To me, it does not seem like a feature that a library of generic algorithms should be using at all.
>
>>
>> No, nothing is stopping a programmer from giving it horrible complexity, but
>> the standard library and language should _definitely_ stick to O(log n) worst
>> case for in and []. It would be a disaster for generic algorithms if in worked
>> on normal arrays, because it would not be possible to maintain the required
>> Big-O complexity.
>
> I agree that any overload of [] and 'in' that Phobos does should stick to that constraint when possible (I say when possible, because sometimes innovative uses of these operators can't stick to this rather strict and mundane constraint; consider for example interaction with a database or what do I know...).
>
> But again, I don't think 'in' is something a generic algorithm should be using. We have the functions in std.algorithm and std.container if we need to write generic code.
>
> Also, I don't think language design should be *too* biased by the standard library's preferences. Not everyone agrees with Phobos conventions and we have to respect that IMHO. Just because it's a standard library doesn't mean that it should dictate users of the language who don't use the standard library.
>
>>
>> - Jonathan M Davis

vote++

I like your POV that operators are useful shortcuts (syntax
sugar) meant for the end user whereas library authors should use
the full function names for generic code. IIRC C++'s STL does the
same - for instance the map::operator[] is a simple wrapper
around map's functions.

Is this included in D's style guide?
May 02, 2012
On 4/30/12 5:15 AM, bearophile wrote:
> Jonathan M Davis:
>
>> Honestly, I don't think that you _can_ take much from this thread
>> other than
>
> I don't agree, I see some recurring patterns.
>
> People have spent energy and time to write lot of answers in this
> thread, some good answer bits too, so I expect such work to not let be
> fully wasted. Asking for opinions, receiving lot of them, and then
> ignoring them all is not a good way to run a community.

It's a bit inappropriate to bind Walter to such a social contract upon having asked an informal question. Besides, if we're talking about work of writing posts we should also consider the considerable work of reading certain posts, which are so patronizing as to make reading an exercise in eye rolling.

> And thank you for your answer, I always appreciate your answers, but you
> aren't Walter, that post was for him (and Andrei) to answer :-)

FWIW there is little agreement among answers. Eliminating today's semantics of comma inevitably underlies the hope that it can be retrofitted for something else, which I think is near impossible without changing semantics of working code. Then there's a lot of busywork. Eliminating e.g. "with" is going to leave things pretty much where they are with the note some innocently bystanding programs are going to break.

One feature to remove stands out - the struct initialization:

struct S { int x, y; }
S s = { 1, 2 };

This, was noted, makes the order of members effectively part of the struct's interface, which is subtly dangerous. I think we should remove this feature.


Andrei
May 02, 2012
On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu wrote:
> One feature to remove stands out - the struct initialization:
> S s = { 1, 2 };

I could live without that one, because D has an alternative:

auto s = S(1, 2);


And I'd be sad if you took that out, as I use it a lot, especially
for trivial types:

struct Html { string src; }
struct Text { string src; }
struct Point { int x; int y; }
struct Size { int width; int height; }

which I like because then we can use the types for overloading,
static checks, etc., and it is very very simple to drop in and
use.

I guess there could be opCalls or constructors, but poo, it
works now without that and I like it.

May 02, 2012
On Wednesday, 2 May 2012 at 03:38:41 UTC, Adam D. Ruppe wrote:
> On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu wrote:
>> One feature to remove stands out - the struct initialization:
>> S s = { 1, 2 };
>
> I could live without that one, because D has an alternative:
>
> auto s = S(1, 2);
>
>
> And I'd be sad if you took that out, as I use it a lot, especially
> for trivial types:
>
> struct Html { string src; }
> struct Text { string src; }
> struct Point { int x; int y; }
> struct Size { int width; int height; }
>
> which I like because then we can use the types for overloading,
> static checks, etc., and it is very very simple to drop in and
> use.
>
> I guess there could be opCalls or constructors, but poo, it
> works now without that and I like it.

S(...) does not exhibit the same problem as {...} exactly because it has constructors and static opCall. If you change the order of fields in S, you can write a constructor preserving the old behaviour.

May 02, 2012
On Wednesday, 2 May 2012 at 03:38:41 UTC, Adam D. Ruppe wrote:
> On Wednesday, 2 May 2012 at 03:22:02 UTC, Andrei Alexandrescu wrote:
>> One feature to remove stands out - the struct initialization:
>> S s = { 1, 2 };
>
> I could live without that one, because D has an alternative:
>
> auto s = S(1, 2);
>
>

It has the same problem as the first one: members are part of the interface and a new one: struct literals are impossible if opCall is defined (if I am not mistaken).