July 24, 2015
On 07/23/2015 11:22 AM, Chris wrote:
> On Wednesday, 22 July 2015 at 18:47:33 UTC, simendsjo wrote:
>> Long rant ahead - a bit dipsy..
> [snip]
>
> It's one thing to list "nice features", and it's another thing to use
> these features in production code. As a code base grows, the limitations
> become more and more obvious. Thus, I would be wary of jumping to
> conclusions or hailing new features as game changers, before having
> tested them thoroughly in the real world.  Only time will tell, if
> something really scales. I've learned to wait and see what people with
> experience report after a year or two of using a given language.

FWIW, most of the features in his list are very old.
July 24, 2015
On 07/24/15 20:29, Walter Bright via Digitalmars-d wrote:
> On 7/24/2015 4:55 AM, Artur Skawina via Digitalmars-d wrote:
>> Basically, it can work like this:
>>
>> - traits, like your 'hasPrefix', check that 'T' implements an
>>    interface (defined in hasPrefix).
>>    (this does the job that template constraints do right now, and
>>    more [1])
>>
>> - the compiler instantiates the template with a mock (defined
>>    inside 'hasPrefix').
>>    (this immediately catches every illegal access, like 't.suffix'
>>    and results in a clear and informative error message)
> 
> That really isn't any different from a user calling it with a 'hasPrefix' that doesn't have a 'suffix'.

The difference is that right now the developer has to write a unit-test per function that uses `hasPrefix`, otherwise the code might not even be verified to compile. 100% unit-test coverage is not going to happen in practice, and just like with docs, making things easier and reducing boilerplate to a minimum would improve the situation dramatically.


>> - the 'T' inside foo is still the original type that it was called
>>    with, so 'bar(t)' will succeed. But it needs to be conditionally
>>    enabled for just the types that implement 'hasColor' -- and this
>>    is exactly what you'd want from traits. So guard it, for example,
>>    `static if (is(T:hasColor)) bar(t);`; note that when 'bar(t)` is
>>    an alias or mixin, this can be done inside the aliased or mixed-in
>>    code.
> 
> As I mentioned in the antecedent, this pulls the teeth of the point of the trait, because what the function needs is 'hasPrefix && hasSuffix', and your position is that only 'hasPrefix' is required.

The function only needs what it uses, ie the i/f defined by `hasPrefix`.
It can optionally access other i/fs like `hasSuffix` if the type supports
them, and it can do so w/o affecting callers (or callees).
Iff you modify the function to /require/ both traits, then, yes, you need
to also update the traits, eg create and use a `hasAdfixes` trait instead.
This is a feature and not a problem; traits would of course be opt-in and
using them only makes sense when the interfaces are very stable, like
D's ranges -- if a required primitive is added, removed or modified then
the range-traits *should* be updated.


> This leaves us exactly where D is now.

No, right now D does not provide any (built-in) functionality for
restricting (and automatically documenting) non-dynamic interfaces.


>> [1] "and more": it allows for overloading on traits, something
>>      that can not be (cleanly) done with constraints.
> 
> Overloading with constraints is commonplace in Phobos. Haven't really had any trouble with it.

It doesn't work (ie does not scale) when the constraints are non- exclusive. At some point one reaches for:

   template _pick_f(T) {
      static if (is(T:ForwardRange)/*&&smth&&(!smth_else||wever)*/)
         enum _pick_f = 1;
      else static if (is(T:ForwardRange)/*&&!(smth&&(!smth_else||wever))*/)
         enum _pick_f = 2;
      else static if (is(T:InputRange))
         enum _pick_f = 3;
      /*...*/
   }
   auto f(T)(T a) if (_pick_f!T==1) {/*...*/}
   auto f(T)(T a) if (_pick_f!T==2) {/*...*/}
   auto f(T)(T a) if (_pick_f!T==3) {/*...*/}

Ugly as it is, it's still better than the alternative (where the ugliness isn't contained, but spread out over all `f` definitions and not guaranteed to be coherent).

artur
July 24, 2015
On Friday, 24 July 2015 at 19:10:33 UTC, Walter Bright wrote:
> On 7/24/2015 11:42 AM, Jacob Carlborg wrote:
>> I don't see the difference compared to a regular parameter. If you don't specify
>> any constraints/traits/whatever it like using "Object" for all your parameter
>> types in Java.
>
> So constraints then will be an all-or-nothing proposition? I believe that would make them essentially useless.
>
> I suspect I am not getting across the essential point. If I have a call tree, and at the bottom I add a call to interface X, then I have to add a constraint that additionally specifies X on each function up the call tree to the root. That is antiethical to writing generic code, and will prove to be more of a nuisance than an asset.
>
> Exactly what sunk Exception Specifications.

But thats exactly how normal interfaces work...

eg:
interface Iface{ void foo(){} }

void func1(Iface x){ func2(x); }
void func2(Iface x){ func3(x); }
void func3(Iface x){ x.bar(); } // ERROR no bar in Iface

Only options here are A: update Iface to have bar() or B: make a new interface and change it on the whole tree. The same "problem" would exist for the concepts, but its the reason why people want it.
July 24, 2015
On Friday, 24 July 2015 at 20:46:07 UTC, Tofu Ninja wrote:
> Is omitting the () not part of ufcs? Or does it have some other name, I can never remember.

No. That's simply omitting the parens from a function call that has no arguments. If it has a name, it's just "optional parens." Universal Function Call Syntax is the syntax that allows you to call a free function as if it were a member function, which is why stuff like

auto result = myRange.find(bar);

works. It _does_ mean that you can drop even more parens, because the first function argument is now to the left of the dot, and the parens are then empty if there was only one function argument, but being able to drop the parens has nothing to do with UFCS. We could still have UFCS and yet never be able to drop parens.

- Jonathan M Davis
July 24, 2015
On Friday, 24 July 2015 at 20:57:34 UTC, Artur Skawina wrote:
> The difference is that right now the developer has to write a unit-test per function that uses `hasPrefix`, otherwise the code might not even be verified to compile. 100% unit-test coverage is not going to happen in practice, and just like with docs, making things easier and reducing boilerplate to a minimum would improve the situation dramatically.

But you see. This is exactly wrong attitude. Why on earth should we make life easier for folks who don't bother to get 100% unit test coverage? A feature has to add more value than to simply make it so that you're slightly less screwed if you don't write unit tests.

- Jonathan M Davis
July 24, 2015
On Friday, 24 July 2015 at 06:42:47 UTC, Walter Bright wrote:
> On 7/23/2015 10:39 PM, Tobias Müller wrote:
>> You may aus well ask "How do interfaces in OO programming deal with this?".
>
> It's a good question. And the answer is, the top level function does not list every interface used by the call tree. Nested function calls test at runtime if a particular interface is supported by an object, using dynamic casting or QueryInterface() calls. It's fundamentally different from traits and concepts.

It is not required and probably shouldn't, or at least shouldn't in many cases.

This problem is the exact same one as strongly typed vs dynamically typed languages, except at compile time. And solution are the same: interface (concepts) or duck typing and hope for the best.

The end goal is pretty much the same: writing reusable code. The implementation differs, performances as well, but that is pretty much it.
July 24, 2015
On Friday, 24 July 2015 at 21:29:56 UTC, Jonathan M Davis wrote:
> On Friday, 24 July 2015 at 20:46:07 UTC, Tofu Ninja wrote:
>> Is omitting the () not part of ufcs? Or does it have some other name, I can never remember.
>
> No. That's simply omitting the parens from a function call that has no arguments. If it has a name, it's just "optional parens." Universal Function Call Syntax is the syntax that allows you to call a free function as if it were a member function, which is why stuff like
>
> auto result = myRange.find(bar);
>
> works. It _does_ mean that you can drop even more parens, because the first function argument is now to the left of the dot, and the parens are then empty if there was only one function argument, but being able to drop the parens has nothing to do with UFCS. We could still have UFCS and yet never be able to drop parens.
>
> - Jonathan M Davis

Ok I kinda assumed they were both included in the concept of UFCS, just replace "UFCS" in what I said before with "optional parens". Basicly I was just saying that I suppose optional parens do not really make sense on function pointers. Aka if "a" is a function pointer then auto b = a; should type "b" to a function pointer as well, which is how it currently works, afik.

But the part that I don't think makes sense for

     auto a = {return 4;};

to type "a" to a function pointer. I would expect {return 4;} to be treated as a function(not a function pointer). With it being treated as a function, I would expect it to be called with optional parens and type "a" to an int. I would expect auto

      a = &{return 4;};

to type "a" to a function pointer, which makes much more sense to me. But that's not how function literals work right now. Treating {return 4;} as a function(not a function pointer) makes a lot more sense and allows

     alias a = {return 4;};

to work as well, which is simply a function declaration.
July 24, 2015
On Friday, 24 July 2015 at 21:32:19 UTC, Jonathan M Davis wrote:
> This is exactly wrong attitude. Why on earth should we make life easier for folks who don't bother to get 100% unit test coverage?

Because that is 99% of D users...
July 24, 2015
On Friday, 24 July 2015 at 21:48:23 UTC, Tofu Ninja wrote:
> On Friday, 24 July 2015 at 21:32:19 UTC, Jonathan M Davis wrote:
>> This is exactly wrong attitude. Why on earth should we make life easier for folks who don't bother to get 100% unit test coverage?
>
> Because that is 99% of D users...

If so, they have no excuse. D has made it ridiculously easy to unit test your code. And I very much doubt that 99% of D users don't unit test their code.

There are cases where 100% isn't possible - e.g. because of an assert(0) or because you're dealing with UI code or the like where it simply isn't usable without running the program - but even then, the test coverage should be as close to 100% as can be achieved, which isn't usually going to be all that far from 100%.

We should be ashamed when our code is not as close to 100% code coverage as is feasible (which is usually 100%).

- Jonathan M Davis
July 24, 2015
On 07/24/15 23:32, Jonathan M Davis via Digitalmars-d wrote:
> On Friday, 24 July 2015 at 20:57:34 UTC, Artur Skawina wrote:
>> The difference is that right now the developer has to write a unit-test per function that uses `hasPrefix`, otherwise the code might not even be verified to compile. 100% unit-test coverage is not going to happen in practice, and just like with docs, making things easier and reducing boilerplate to a minimum would improve the situation dramatically.
> 
> But you see. This is exactly wrong attitude. Why on earth should we make life easier for folks who don't bother to get 100% unit test coverage?

How exactly does making it harder to write tests translate into having better coverage? Why is requiring the programmer to write unnecessary, redundant, and potentially buggy tests preferable?

artur