www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Just sayin', fwiw...

reply "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
Not to beat anyone over the head or push for any change (I know not to 
do that 'round these parts these days ;) )...but I've noticed a very 
frequent pattern in my own usage of D:

1. I write a bunch of code.
2. I take advantage of ranges and std.algorithm and think I'm being all 
hip and cool and awesome.
3. I hit compile.
4. Something in std.algorithm fails to find a matching overload.
5. I double check everything. Everything seems a-ok kosher.
6. Maybe I figure, "well, I haven't bothered to update my default D 
compiler in a while, maybe it's a bug or a hole in phobos's function 
signature that's been fixed", so to be safe I do a "dvm list | sort" and 
a "dvm use [newest]", maybe download & install a new version too.
7. After dub makes me wait a minute or two to recompile all of vibe.d, I 
get the same error.
8. I scratch my head wondering WTF I did wrong.
9. [If I'm lucky] I remember, "Oh, wait, I'm doing string processing...I 
need a bySomethingOrOther to kill autodecode"
10. I toss in ".byCodeUnit", it works, I go about the rest of my day.

And I'm a D veteran. I've been using D since before v1.0 (yes, pre-D1). 
I can't even imagine how painful this would be for a D newcomer.

To be clear...not to badger, not to request, not to hope for D to change 
for the better on any matter that isn't earth-shatteringly large (I know 
better by now), I'm just sayin' for the sake o' sayin' : It really 
*wound* be nice to be able to (even optionally) get SOME kind of clear 
notice anytime I've failed to implicitly CHOOSE between decode or no-decode.

I'm tempted to just always "alias String = immutable(byte)[]" and 
pedantically convert to that whenever and wherever possible. (Welcome to 
C++-land's 'my language sucks so individual projects have to re-invent 
their own string types. Yeee-hah!)

That is all.
May 15
next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Thursday, 16 May 2019 at 03:11:15 UTC, Nick Sabalausky 
(Abscissa) wrote:
 Not to beat anyone over the head or push for any change (I know 
 not to do that 'round these parts these days ;) )...but I've 
 noticed a very frequent pattern in my own usage of D:

 1. I write a bunch of code.
 2. I take advantage of ranges and std.algorithm and think I'm 
 being all hip and cool and awesome.
 3. I hit compile.
 4. Something in std.algorithm fails to find a matching overload.
...
 10. I toss in ".byCodeUnit", it works, I go about the rest of 
 my day.

 And I'm a D veteran. I've been using D since before v1.0 (yes, 
 pre-D1). I can't even imagine how painful this would be for a D 
 newcomer.

 To be clear...not to badger, not to request, not to hope for D 
 to change for the better on any matter that isn't 
 earth-shatteringly large (I know better by now), I'm just 
 sayin' for the sake o' sayin' : It really *wound* be nice to be 
 able to (even optionally) get SOME kind of clear notice anytime 
 I've failed to implicitly CHOOSE between decode or no-decode.
This is not a problem with string autodecoding, this is a problem with the utterly atrocious error reporting where if the compiler fails to find an overload match due to template constraints, it gives you precisely zero indication what the actual root cause is.
May 16
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, May 16, 2019 at 02:39:40PM +0000, FeepingCreature via Digitalmars-d
wrote:
 On Thursday, 16 May 2019 at 03:11:15 UTC, Nick Sabalausky (Abscissa) wrote:
 Not to beat anyone over the head or push for any change (I know not
 to do that 'round these parts these days ;) )...but I've noticed a
 very frequent pattern in my own usage of D:
 
 1. I write a bunch of code.
 2. I take advantage of ranges and std.algorithm and think I'm being
 all hip and cool and awesome.
 3. I hit compile.
 4. Something in std.algorithm fails to find a matching overload.
...
 10. I toss in ".byCodeUnit", it works, I go about the rest of my
 day.
 
 And I'm a D veteran. I've been using D since before v1.0 (yes,
 pre-D1).  I can't even imagine how painful this would be for a D
 newcomer.
[...]
 This is not a problem with string autodecoding, this is a problem with
 the utterly atrocious error reporting where if the compiler fails to
 find an overload match due to template constraints, it gives you
 precisely zero indication what the actual root cause is.
Inscrutable error messages involving unreadable sig constraints are only a symptom. The REAL problem as Walter has pointed out elsewhere is that Phobos uses far too much function overloading. I'd say Phobos abuses function overloading. There are far too many overloads that ought *not* to be overloads, but should be merged into a single, logical function with various cases differentiated by static ifs inside the function body, with a static assert at the end explaining the problem should none of the cases match. Function overloads should be used where there is a LOGICAL distinction in the public-facing API, e.g.: auto find(R,E)(R haystack, E needle) vs. auto find(alias pred, R)(R haystack) They are logically distinct because one overload takes the object being searched as an argument, whereas the other takes a predicate to evaluate. But where the distinction is in implementation details, such as: auto find(R,E)(R haystack, E needle) if (isSomeString!R) auto find(R,E)(R haystack, E needle) if (!isSomeString!R) then they really should NOT be overloads, but should instead be a SINGLE logical function with the implementation details hidden inside the function body: auto find(R,E)(R haystack, E needle) { static if (isSomeString!R) ... // implementation #1 else // !isSomeString!R) ... // implementation #2 } Why should the user care that find's implementation treats strings and non-string separately? That's an irrelevant implementation detail that should be hidden inside the function body. Exposing it as a sig constraint in a public-facing API breaks encapsulation, and is an anti-pattern. I've already repeated this many, many times, but there still remains a lot of Phobos/druntime code written according to this anti-pattern, including a recent example of hashOf being a *21*-function overload set in druntime. Insane!! Glancing through those overloads reveals that the sig constraints are all implementation details, i.e., they should NOT be sig constraints in a public-facing API, but static if conditions inside the function body dispatching to various different implementations. Abusing overload sets for this purpose is an anti-pattern, and needs to stop. T -- If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell
May 16
next sibling parent "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 5/16/19 1:47 PM, H. S. Teoh wrote:
 
 Why should the user care that find's implementation treats strings and
 non-string separately?  That's an irrelevant implementation detail that
 should be hidden inside the function body.  Exposing it as a sig
 constraint in a public-facing API breaks encapsulation, and is an
 anti-pattern.
 
You make a good point.
 I've already repeated this many, many times, but there still remains a
 lot of Phobos/druntime code written according to this anti-pattern,
 including a recent example of hashOf being a *21*-function overload set
 in druntime.  Insane!!  Glancing through those overloads reveals that
 the sig constraints are all implementation details, i.e., they should
 NOT be sig constraints in a public-facing API, but static if conditions
 inside the function body dispatching to various different
 implementations.
 
 Abusing overload sets for this purpose is an anti-pattern, and needs to
 stop.
 
Sounds like someone has good qualifications to put together a PR ;)
May 16
prev sibling next sibling parent Johan Coder <johan coder.org> writes:
On Thursday, 16 May 2019 at 17:47:26 UTC, H. S. Teoh wrote:
 The REAL problem as Walter has pointed out elsewhere is that 
 Phobos uses far too much function overloading. I'd say Phobos 
 abuses function overloading. There are far too many overloads 
 that ought *not* to be overloads, but should be merged into a 
 single, logical function with various cases differentiated by 
 static ifs inside the function body, with a static assert at 
 the end explaining the problem should none of the cases match.
...
 I've already repeated this many, many times, but there still 
 remains a lot of Phobos/druntime code written according to this 
 anti-pattern, including a recent example of hashOf being a 
 *21*-function overload set in druntime.  Insane!!  Glancing 
 through those overloads reveals that the sig constraints are 
 all implementation details, i.e., they should NOT be sig 
 constraints in a public-facing API, but static if conditions 
 inside the function body dispatching to various different 
 implementations.

 Abusing overload sets for this purpose is an anti-pattern, and 
 needs to stop.
More than stop it needs to be repaired. Documentation is bizarre because of them. But so much discussion changing bool and <...
May 16
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 5/16/19 6:47 PM, H. S. Teoh wrote:

 I've already repeated this many, many times, but there still remains a
 lot of Phobos/druntime code written according to this anti-pattern,
 including a recent example of hashOf being a *21*-function overload set
 in druntime.  Insane!!  Glancing through those overloads reveals that
 the sig constraints are all implementation details, i.e., they should
 NOT be sig constraints in a public-facing API, but static if conditions
 inside the function body dispatching to various different
 implementations.
 
Context is important. I think this code was trying to replace 21 overloads of TypeInfo calls IIRC. So at least it's better than the previous solution. Refactoring would probably make sense, but not before you replace exactly the existing solution. -Steve
May 16
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, May 16, 2019 at 04:20:48PM -0400, Steven Schveighoffer via
Digitalmars-d wrote:
 On 5/16/19 6:47 PM, H. S. Teoh wrote:
 
 I've already repeated this many, many times, but there still remains
 a lot of Phobos/druntime code written according to this
 anti-pattern, including a recent example of hashOf being a
 *21*-function overload set in druntime.  Insane!!  Glancing through
 those overloads reveals that the sig constraints are all
 implementation details, i.e., they should NOT be sig constraints in
 a public-facing API, but static if conditions inside the function
 body dispatching to various different implementations.
 
Context is important. I think this code was trying to replace 21 overloads of TypeInfo calls IIRC. So at least it's better than the previous solution.
Instead of replacing 21 overloads of TypeInfo calls with 21 overloads of hashOf, the refactoring should have been done with a single overload of hashOf with 21 static if branches.
 Refactoring would probably make sense, but not before you replace
 exactly the existing solution.
[...] I'm tempted to submit a PR to unify toHash overloads like above. Would it be accepted? T -- May you live all the days of your life. -- Jonathan Swift
May 17
prev sibling parent reply Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Friday, May 17, 2019 12:21:04 PM MDT H. S. Teoh via Digitalmars-d wrote:
 On Thu, May 16, 2019 at 04:20:48PM -0400, Steven Schveighoffer via 
Digitalmars-d wrote:
 Refactoring would probably make sense, but not before you replace
 exactly the existing solution.
[...] I'm tempted to submit a PR to unify toHash overloads like above. Would it be accepted?
If you create a PR with much cleaner code that demonstrably does the same thing, then presumably, it would be accepted - especially since it's clear that we should be reducing the number of unnecessary overloads in general. - Jonatham M Davis
May 17
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/17/19 7:48 PM, Jonathan M Davis wrote:
 On Friday, May 17, 2019 12:21:04 PM MDT H. S. Teoh via Digitalmars-d wrote:
 On Thu, May 16, 2019 at 04:20:48PM -0400, Steven Schveighoffer via
Digitalmars-d wrote:
 Refactoring would probably make sense, but not before you replace
 exactly the existing solution.
[...] I'm tempted to submit a PR to unify toHash overloads like above. Would it be accepted?
If you create a PR with much cleaner code that demonstrably does the same thing, then presumably, it would be accepted - especially since it's clear that we should be reducing the number of unnecessary overloads in general.
The union of overloads will have the OR of restrictions. The right unification will lead to simplification of said conditions. If we end up with a large disjunction then that's not progress.
May 18
prev sibling parent dayllenger <dayllenger protonmail.com> writes:
On Thursday, 16 May 2019 at 14:39:40 UTC, FeepingCreature wrote:
 This is not a problem with string autodecoding, this is a 
 problem with the utterly atrocious error reporting where if the 
 compiler fails to find an overload match due to template 
 constraints, it gives you precisely zero indication what the 
 actual root cause is.
BTW: https://github.com/dlang/dmd/pull/9715. The PR hung a bit, I'll write tests and make it mergeable.
May 16
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Thursday, 16 May 2019 at 03:11:15 UTC, Nick Sabalausky 
(Abscissa) wrote:
 I'm tempted to just always "alias String = immutable(byte)[]"
Well actually, because "string" is just an alias defined in object.d, you can actually redeclare it to be something else in your own code. ----- import std.stdio; alias string = int[long]; void main() { string im_not_a_string = [1: 10, 2: 20]; writeln(im_not_a_string); } ----- Have fun. :P
May 20
parent "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com> writes:
On 5/20/19 9:39 PM, Andrej Mitrovic wrote:
 On Thursday, 16 May 2019 at 03:11:15 UTC, Nick Sabalausky (Abscissa) wrote:
 I'm tempted to just always "alias String = immutable(byte)[]"
Well actually, because "string" is just an alias defined in object.d, you can actually redeclare it to be something else in your own code. ----- import std.stdio; alias string = int[long]; void main() {     string im_not_a_string = [1: 10, 2: 20];     writeln(im_not_a_string); } ----- Have fun. :P
Hmmm...I think I'll just hold off on that trick until I ever enter a code obfuscation contest... ;)
May 20