www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - C++ UFCS update

reply Daniel N <ufo orbiting.us> writes:
"Abstract
This is the proposed wording for a unified call syntax based on 
the idea that f(x,y) can invoke a member function, x.f(y), if 
there are no f(x,y). The inverse transformation, from x.f(y) to 
f(x,y) is not proposed."

They were considering 6 alternatives and chose the worst...
https://isocpp.org/files/papers/P0251R0.pdf
Feb 13 2016
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Saturday, 13 February 2016 at 10:27:59 UTC, Daniel N wrote:
 They were considering 6 alternatives and chose the worst...
 https://isocpp.org/files/papers/P0251R0.pdf
I'm not so sure this is the worst, given the C++ history. Think about this for a minute: "f(x,y) can invoke a member function, x.f(y), if there are no f(x,y)" That means you can override member functions with local non-member functions, that it will encourage programmers to write `f(x, y)` and thus be more compatible with older compilers via freestanding shims, and just plain be more convincing for them to actually use non-friend, non-member functions which is the key encapsulation goal of UFCS. It might not be an ideal decision, but I do think it is an OK one for C++.
Feb 13 2016
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/13/2016 2:27 AM, Daniel N wrote:
 "Abstract
 This is the proposed wording for a unified call syntax based on the idea that
 f(x,y) can invoke a member function, x.f(y), if there are no f(x,y). The
inverse
 transformation, from x.f(y) to f(x,y) is not proposed."

 They were considering 6 alternatives and chose the worst...
 https://isocpp.org/files/papers/P0251R0.pdf
Wasn't it us who chose the term UFCS?
Feb 14 2016
next sibling parent deadalnix <deadalnix gmail.com> writes:
On Monday, 15 February 2016 at 06:12:30 UTC, Walter Bright wrote:
 On 2/13/2016 2:27 AM, Daniel N wrote:
 "Abstract
 This is the proposed wording for a unified call syntax based 
 on the idea that
 f(x,y) can invoke a member function, x.f(y), if there are no 
 f(x,y). The inverse
 transformation, from x.f(y) to f(x,y) is not proposed."

 They were considering 6 alternatives and chose the worst...
 https://isocpp.org/files/papers/P0251R0.pdf
Wasn't it us who chose the term UFCS?
These aren't the acronyms you are looking for.
Feb 14 2016
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 02/14/2016 10:12 PM, Walter Bright wrote:

 Wasn't it us who chose the term UFCS?
Can't be. Other languages take features from C++ but never admit it. ;) Ali
Feb 16 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 16 February 2016 at 08:24:50 UTC, Ali Çehreli wrote:
 On 02/14/2016 10:12 PM, Walter Bright wrote:

 Wasn't it us who chose the term UFCS?
Can't be. Other languages take features from C++ but never admit it. ;)
I think it would be a good idea to drop this microscopic search for novelty. It is borderline pathetic... I don't think Stroustrup has said that C++ has introduced novel features. What C++ has done is to integrate many known features with few restrictions on how to use them. D has done much of the same, but with more restrictions. Other languages have provided various OO syntaxes and extension methods etc since the 70s or 80s, and it has probably been discussed for C++ before it was implemented in D. UFCS/UCS is more a sign of starting with a non-OO language and adding OO-methods at a later stage. Pure OO languages implement the global scope as an object and "free functions" are just members of an outer scope.
Feb 16 2016
prev sibling next sibling parent deadalnix <deadalnix gmail.com> writes:
On Saturday, 13 February 2016 at 10:27:59 UTC, Daniel N wrote:
 "Abstract
 This is the proposed wording for a unified call syntax based on 
 the idea that f(x,y) can invoke a member function, x.f(y), if 
 there are no f(x,y). The inverse transformation, from x.f(y) to 
 f(x,y) is not proposed."

 They were considering 6 alternatives and chose the worst...
 https://isocpp.org/files/papers/P0251R0.pdf
It makes a lot of sense in C++ actually. It allow to unify begin/end for instance.
Feb 14 2016
prev sibling next sibling parent reply w0rp <devw0rp gmail.com> writes:
Personally, I find this proposal for C++ to be laughable. It's 
like hitch hiking from New York to California, and only getting 
as far as Texas and calling it good.

The great thing about our UFCS is the left-to-right chaining of 
algorithms.

x.map!(...).filter!(...).reduce!(...)

It beats the Hell out of...

reduce!(...)(filter!(...)(map!(...)(x)))

This proposal will encourage non member functions, which is good, 
but will never reach the "aha" moment D had which gave us UFCS 
chaining.
Feb 15 2016
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 16 February 2016 at 07:59:49 UTC, w0rp wrote:
 Personally, I find this proposal for C++ to be laughable. It's 
 like hitch hiking from New York to California, and only getting 
 as far as Texas and calling it good.

 The great thing about our UFCS is the left-to-right chaining of 
 algorithms.

 x.map!(...).filter!(...).reduce!(...)

 It beats the Hell out of...

 reduce!(...)(filter!(...)(map!(...)(x)))

 This proposal will encourage non member functions, which is 
 good, but will never reach the "aha" moment D had which gave us 
 UFCS chaining.
Ugh, that syntax is abusing the implied semantics of dot-notation; member-access. Better to have a pipeline operator. Such syntax abuse is common in other languages too, so I don't get the "aha". It is more a case of "ugh, repeated mistake"... Explicit extension methods is a much better alternative.
Feb 16 2016
parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
On Tue, 16 Feb 2016 08:08:46 +0000, Ola Fosheim Grøstad wrote:

 On Tuesday, 16 February 2016 at 07:59:49 UTC, w0rp wrote:
 Personally, I find this proposal for C++ to be laughable. It's like
 hitch hiking from New York to California, and only getting as far as
 Texas and calling it good.

 The great thing about our UFCS is the left-to-right chaining of
 algorithms.

 x.map!(...).filter!(...).reduce!(...)

 It beats the Hell out of...

 reduce!(...)(filter!(...)(map!(...)(x)))

 This proposal will encourage non member functions, which is good, but
 will never reach the "aha" moment D had which gave us UFCS chaining.
Ugh, that syntax is abusing the implied semantics of dot-notation; member-access. Better to have a pipeline operator. Such syntax abuse is common in other languages too, so I don't get the "aha". It is more a case of "ugh, repeated mistake"... Explicit extension methods is a much better alternative.
+1 !! I *completely* agree with this. UFCS is OK in some places but not everywhere like people do lately. What you said about abusing the dot- notation is on the spot. It is not uncommon nowadays to see D code that I have absolutely no idea what it does, because of UFCS. I have to go through each piece separated by dots to understand what it is... -- Dejan Lekic ✉ dejan.lekic (at) gmail.com ➚ http://dejan.lekic.org
Feb 19 2016
next sibling parent reply David Nadlinger <code klickverbot.at> writes:
On Friday, 19 February 2016 at 16:18:12 UTC, Dejan Lekic wrote:
 I have to go through each piece separated by dots to understand 
 what it is...
Let me play devil's advocate here: How would this be any different if UFCS were not used? — David
Feb 19 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Friday, 19 February 2016 at 16:42:36 UTC, David Nadlinger 
wrote:
 On Friday, 19 February 2016 at 16:18:12 UTC, Dejan Lekic wrote:
 I have to go through each piece separated by dots to 
 understand what it is...
Let me play devil's advocate here: How would this be any different if UFCS were not used?
// if a has a process if( a.process ) … // if processing a was successful if( process(a) ) ... // copy a to b a.copy_to(b) // copy b to a copy_to(a,b) // print a on stream f f.print(a) // print f and a on std out print(f,a) // count the number of people, cars and drinks count(people,cars,drinks) // count the number of cars and drinks people has people.count(cars,drinks) If you have namespace operator "::" in c++ or "'" in Ada (IIRC) and extension methods // access library "as" extension method string obj1.as'string etc…
Feb 20 2016
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, 19 February 2016 at 16:18:12 UTC, Dejan Lekic wrote:
 I *completely* agree with this. UFCS is OK in some places but 
 not everywhere like people do lately. What you said about 
 abusing the dot- notation is on the spot. It is not uncommon 
 nowadays to see D code that I have absolutely no idea what it 
 does, because of UFCS. I have to go through each piece 
 separated by dots to understand what it is...
Well, you could actually argue the exact same thing about function overloading and overriding, which is part of why Linus Torvalds prefers C to C++ - ostensibly, you can look at a chunk of C code and know exactly what it's doing without a lot of context, which is often not at all true in languages which have overloading and the like (especially when operator overloading gets added into the mix). Now, how big a deal that is is debatable, but it's something that some folks have complained about, whereas many folks would never want to have to deal with not having function overloading. With regards to UFCS, some folks think that it makes code way cleaner and easier to figure out what's going on, whereas others think that it's worse. Personally, I'm enough used to dealing with functional languages, that not having UFCS doesn't bother me that much, though it's easier to have clean, long UFCS chains than it is to have clean, long normal function call chains, because the number of parens tend to drown things out. As for a pipe operator, I expect that it wouldn't really help any. It would be a lot like . vs -> in that it's an unnecessary complication, but it would actually probably be worse. If | meant that a function call could be either a member function or a free function, you'd still have no more clue about which functions were member functions than you do now, and there would be plenty of incentive to just not bother using . in order to be consistent. Certainly, . would become unnecessary. It's the fact that there is a way to call a function without caring whether it's a member function or a free function which causes the confusion. The syntax itself doesn't really matter. But ultimately, regardless of the syntax, it's a big win, because it allows us to do stuff like have find be a free function and then have a range which can implement find more efficiently overload it as a member function, and the calling code doesn't need to care. So, UFCS is almost always worth the confusion about whether you're calling a member function or not, and the confusion is just inherent to UFCS regardless of the syntax. So, I really don't see how another syntax would help any. - Jonathan M Davis
Feb 21 2016
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 21 February 2016 at 10:16:19 UTC, Jonathan M Davis 
wrote:
 As for a pipe operator, I expect that it wouldn't really help 
 any. It would be a lot like . vs -> in that it's an unnecessary 
 complication,
"." vs "->" isn't an unnecessary complication it is a strong typing issue, as can be seen when trying to implement a smart pointer.
 but it would actually probably be worse. If | meant that a 
 function call could be either a member function or a free 
 function, you'd still have no more clue about which functions 
 were member functions than you do now,
There are many options. It could require function objects (instantiated or non-instantiated) that provide the right opXXX members. If the protocol is well designed and fully specified then the compiler can figure out what glue-code to generate even if connecting nodes aren't directly compatible, or choose the most efficient interface (e.g. one node provides a SIMD interface) If iterators (ranges) are a main selling point for D, then you might as well give pipelining language support, make it better than a library solution, open up for parallel execution and hardware dependent cache and loop optimizations. A pure library solution cannot do this well.
 the syntax. So, I really don't see how another syntax would 
 help any.
Stronger typing helps when programs grow in size...
Feb 21 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
Anyway, adding extension methods to C++ could be as trivial as 
the name of the first parameter being "this":

std::string reverse(const std::string& this){…}

auto s = somestring.reverse();
Feb 21 2016
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/21/2016 2:16 AM, Jonathan M Davis wrote:
 As for a pipe operator, I expect that it wouldn't really help any. It would be
a
 lot like . vs -> in that it's an unnecessary complication, but it would
actually
 probably be worse. If | meant that a function call could be either a member
 function or a free function, you'd still have no more clue about which
functions
 were member functions than you do now, and there would be plenty of incentive
to
 just not bother using . in order to be consistent. Certainly, . would become
 unnecessary.
I'm not thrilled about overloading | with a non-arithmetic purpose. I hated iostreams' use of << from the beginning.
 It's the fact that there is a way to call a function without caring
 whether it's a member function or a free function which causes the confusion.
 The syntax itself doesn't really matter. But ultimately, regardless of the
 syntax, it's a big win, because it allows us to do stuff like have find be a
 free function and then have a range which can implement find more efficiently
 overload it as a member function, and the calling code doesn't need to care.
So,
 UFCS is almost always worth the confusion about whether you're calling a member
 function or not, and the confusion is just inherent to UFCS regardless of the
 syntax. So, I really don't see how another syntax would help any.
Big reasons for allowing f(x) and x.f() equivalence are: 1. Head off the temptation to fill up a class declaration with every conceivable member function: http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197 2. Allow users to 'extend' a class without having to modify the original. 3. And, of course, to chain calls together.
Feb 21 2016
next sibling parent Era Scarecrow <rtcvb32 yahoo.com> writes:
On Sunday, 21 February 2016 at 22:32:23 UTC, Walter Bright wrote:
 I'm not thrilled about overloading | with a non-arithmetic 
 purpose. I hated iostreams' use of << from the beginning.
Ditto, I've always hated it as well. I recall reading that the original iostream class was an example class (and badly designed), not only does the implementation look ugly to use, but it has no value in a logical/mathematical way unlike how those operators are intended to work natively (unlike say gmp or BigNum or something). At least overloading the + in Java was limited strictly to concatenation of strings. I can sort of see how the | (pipe) might be overloaded acceptably if you're working a lot with shell (script programmers) where you send the output of one program as the input of another, but that doesn't appear to offer any real advantage compared to what is already being used with UFCS. Best not to break what's not broke.
Feb 21 2016
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Sunday, 21 February 2016 at 22:32:23 UTC, Walter Bright wrote:
 I'm not thrilled about overloading | with a non-arithmetic 
 purpose. I hated iostreams' use of << from the beginning.
Adding a new token is done in less than an hour, and a non-breaking change...
Feb 22 2016
parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Monday, 22 February 2016 at 08:07:03 UTC, Ola Fosheim Grøstad 
wrote:
 Adding a new token is done in less than an hour, and a 
 non-breaking change...
I have to ask: How will adding a new token help us or improve the language?
Feb 22 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Monday, 22 February 2016 at 10:09:47 UTC, Era Scarecrow wrote:
 I have to ask: How will adding a new token help us or improve 
 the language?
How will it not help?
Feb 22 2016
parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Tuesday, 23 February 2016 at 07:22:26 UTC, Ola Fosheim Grøstad 
wrote:
 I have to ask: How will adding a new token help us or improve 
 the language?
How will it not help?
How about let's rephrase this as a short example. Let's say we add for a symbol which by default just duplicates +. So: a b; //is a + b So: x[] y[] //is legal now too. foreach(i,a; x) { //I'll assume $ is also the same as multiply, just for fun //also no clue what this code would be for zz =x[i b] y[i$(b c) z]$a; //vs zz+=x[i+b]+y[i*(b+c)+z]*a; } If | effectively does the same as . (at least that's the impression I get, maybe I'm totally wrong), what benefit does it give other than confusing or obfuscating code? Before adding it in, I'd need a clean proof of concept of why it's a good idea to add.
Feb 22 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 23 February 2016 at 07:46:08 UTC, Era Scarecrow wrote:
  If | effectively does the same as . (at least that's the 
 impression I get, maybe I'm totally wrong), what benefit does 
 it give other than confusing or obfuscating code?
It doesn't confuse or obfuscate code, on the contrary, it brings clarity and makes the code more legible.
  Before adding it in, I'd need a clean proof of concept of why 
 it's a good idea to add.
*toss arms up in the air*
Feb 23 2016
parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Tuesday, 23 February 2016 at 10:16:43 UTC, Ola Fosheim Grøstad 
wrote:
 On Tuesday, 23 February 2016 at 07:46:08 UTC, Era Scarecrow 
 wrote:
  If | effectively does the same as . (at least that's the 
 impression I get, maybe I'm totally wrong), what benefit does 
 it give other than confusing or obfuscating code?
It doesn't confuse or obfuscate code, on the contrary, it brings clarity and makes the code more legible.
You know, i remember that in C there was a dereferencing symbol, it was ->, and that was thrown out for UFCS as well as simplicity. c->x and c.x were basically the same. Why not use -> instead of | ? That would be fun wouldn't it. To borrow from w0rp's post earlier as I don't do this much. x.map!(...).filter!(...).reduce!(...) x.map!(...)|filter!(...)|reduce!(...) x.map!(...)->filter!(...)->reduce!(...) Honestly looking at them side by side, I don't like |, -> is almost preferable except I sometimes don't hit the > and have to re-edit it, unlike using ., but that's a minor gripe there. Hell why not extend to the rest of the operators? Don't forget C++'s iostream pushes using very specific low level operations to do weird things. x.map!(...)>>filter!(...)>>reduce!(...) x.map!(...)<<filter!(...)<<reduce!(...) x.map!(...)^filter!(...)^reduce!(...) x.map!(...)-filter!(...)-reduce!(...) x.map!(...)+filter!(...)+reduce!(...) x.map!(...)&filter!(...)&reduce!(...) x.map!(...)*filter!(...)*reduce!(...) x.map!(...)!filter!(...)!reduce!(...) x.map!(...)~filter!(...)~reduce!(...) x.map!(...)%filter!(...)%reduce!(...) Why stop there? x.map!(...)&&filter!(...)&&reduce!(...) x.map!(...)||filter!(...)||reduce!(...) x.map!(...)::filter!(...)::reduce!(...) x.map!(...)=>filter!(...)=>reduce!(...) x.map!(...)++filter!(...)++reduce!(...) x.map!(...)--filter!(...)--reduce!(...) x.map!(...)<=>filter!(...)<=>reduce!(...) x.map!(...)<>filter!(...)<>reduce!(...) x.map!(...)>=<filter!(...)>=<reduce!(...) x.map!(...)><filter!(...)><reduce!(...) x.map!(...)!!filter!(...)!!reduce!(...) x.map!(...)~~filter!(...)~~reduce!(...) x.map!(...)%%filter!(...)%%reduce!(...) I still stand by that _unless_ it shows it really improves it somehow, or adds something vital that it shouldn't be there.
Feb 23 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 23 February 2016 at 20:11:01 UTC, Era Scarecrow wrote:
  c->x and c.x were basically the same. Why not use -> instead 
 of | ?
Sure, you can do that. Other languages use "->" for pushing parameters. But in C/C++ "x->m" is a shorthand for "(*x).f". C++ also have "and" and "or" as a shorthand for "&&" and "||", btw. I think "and" and "or" often makes code look more readable, yet I've never seen them used.
 Honestly looking at them side by side, I don't like |, -> is 
 almost preferable except I sometimes don't hit the > and have 
 to re-edit it, unlike using ., but that's a minor gripe there.
Yes, I also like arrows for suggesting the direction when you have pipelines.
  Hell why not extend to the rest of the operators? Don't forget 
 C++'s iostream pushes using very specific low level operations 
 to do weird things.
The primary issue I have with iostream is that floating point formatting gets ugly. The "<<" works out ok for iostream in practice, mostly because it is not common to do bit-shifts in combination with IO. And I have to say that I find it ironic that Walter objects to reusing operators such as "<<" while he is reusing "!" for templates, which I find waaay more annoying than iostream.
Feb 23 2016
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 23.02.2016 21:35, Ola Fosheim Grøstad wrote:
 I find it ironic that Walter objects to reusing operators such as "<<"
 while he is reusing "!" for templates
No reusing and no irony here. "!" for template instantiation is a binary usage.
Feb 23 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 23 February 2016 at 20:49:40 UTC, Timon Gehr wrote:
 On 23.02.2016 21:35, Ola Fosheim Grøstad wrote:
 I find it ironic that Walter objects to reusing operators such 
 as "<<"
 while he is reusing "!" for templates
No reusing and no irony here. "!" for template instantiation is a binary usage.
Wrong. Unary, postfix, prefix, mixfix does not matter. It still affects usability. Definition for "operator": «a symbol or function denoting an operation (e.g. ×, +).»
Feb 24 2016
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 24.02.2016 11:24, Ola Fosheim Grøstad wrote:
 On Tuesday, 23 February 2016 at 20:49:40 UTC, Timon Gehr wrote:
 On 23.02.2016 21:35, Ola Fosheim Grøstad wrote:
 I find it ironic that Walter objects to reusing operators such as "<<"
 while he is reusing "!" for templates
No reusing and no irony here. "!" for template instantiation is a binary usage.
Wrong. Unary, postfix, prefix, mixfix does not matter. It still affects usability. Definition for "operator": «a symbol or function denoting an operation (e.g. ×, +).»
I was responding to a very specific statement, namely the one I quoted, if that was unclear. It's obvious that Walter considers arity to be part of the identity of an operator. If you find pleasure in finding irony in misrepresented statements, feel free. I don't.
Feb 24 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 24 February 2016 at 21:12:23 UTC, Timon Gehr wrote:
 It's obvious that Walter considers arity to be part of the 
 identity of an operator. If you find pleasure in finding irony 
 in misrepresented statements, feel free. I don't.
There's nothing misrepresented in what I wrote. If you want arity to be part of the identity, you might as well including typing. That just a very convenient rewriting of reality, typical apologetic D-advocacy. The operator is the symbol and reusing it for something unrelated has a negative effect on usability. You guys need to stop complaining about the insignificant splinters of C++ and start worrying about the beams that are stumbling blocks for D. C++ is alive and kicking...
Feb 24 2016
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 24.02.2016 22:31, Ola Fosheim Grøstad wrote:
 That just a very convenient rewriting of reality,
The ultimate validity of the premise does not matter for what I objected to. You were trying to paint Walter's position internally inconsistent in a very specific way that just does not hold water.
Feb 24 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 24 February 2016 at 21:56:12 UTC, Timon Gehr wrote:
 The ultimate validity of the premise does not matter for what I 
 objected to. You were trying to paint Walter's position 
 internally inconsistent in a very specific way that just does 
 not hold water.
Sigh. I am not trying to paint anything, not even a bikeshed. I am merely observing the following: 1. I've never had any issues related to "<<" for iostream. 2. I am rather annoyed by the inconsistent use of symbols in D. 3. Objecting to "<<" for iostream while using symbols incosistently yourself IS ironic. What is and isn't ironic, isn't a matter of «validity of the premise». It is a matter of interpretation. Not your interpretation. Mine. Also, the usability issues concerning symbols isn't related to mathematical definitions, but is related to the mnemonics of the symbols, or the interpretation of them, by a human being. Not by a machine. As such a useful mnemonic for "<<" is that it is for moving stuff to the left. Which could work equally well for a stream as it does for bits. There is no apparent overlap between the mnemonics for "!" in the context of templates or bools. Same with "~", which in the context of C means "flip the bits", with the wave being a mnemonic for flipping. I find it ironic that iostream is more consistent with the mnemonics of the symbols than D is. Deal with it. Don't defend it. Fix it.
Feb 24 2016
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 24.02.2016 23:10, Ola Fosheim Grøstad wrote:
 On Wednesday, 24 February 2016 at 21:56:12 UTC, Timon Gehr wrote:
 The ultimate validity of the premise does not matter for what I
 objected to. You were trying to paint Walter's position internally
 inconsistent in a very specific way that just does not hold water.
Sigh. I am not trying to paint anything, not even a bikeshed. I am merely observing the following: 1. I've never had any issues related to "<<" for iostream. ...
Note that I am not the one complaining about overloaded tokens.
 2. I am rather annoyed by the inconsistent use of symbols in D.
 ...
It's not inconsistent. It's overloading at the lexical level that gets resolved at the level of the grammar.
 3. Objecting to "<<" for iostream while using symbols incosistently
 yourself IS ironic.


 What is and isn't ironic, isn't a matter of «validity of the premise».
You misunderstand what that part of the sentence refers to. (It's what I quoted.)
 It is a matter of interpretation. Not your interpretation. Mine.
 ...
You might want to keep those aspects to yourself or express their subjectivity more explicitly if you don't want them to be mistaken for a point being made that resembles points being made using the same wording.
 Also, the usability issues concerning symbols isn't related to
 mathematical definitions, but is related to the mnemonics of the
 symbols, or the interpretation of them, by a human being. Not by a machine.

 As such a useful mnemonic for "<<" is that it is for moving stuff to the
 left. Which could work equally well for a stream as it does for bits.

 There is no apparent overlap between the mnemonics for "!" in the
 context of templates or bools. Same with "~", which in the context of C
 means "flip the bits",
In the context of C, "*" means either "dereference" or "multiply". "&" means either "take address" or "bitwise and".
 with the wave being a mnemonic for flipping.
 ...
Uh...
 I find it ironic that iostream is more consistent with the mnemonics of
 the symbols than D is. Deal with it.  Don't defend it. Fix it.
I'm afraid I personally don't care too much about any of that. Also, I'm not defending anything. I was attacking annoying rhetoric. Not anymore though. I'm done here.
Feb 24 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 24 February 2016 at 22:55:11 UTC, Timon Gehr wrote:
 You misunderstand what that part of the sentence refers to. 
 (It's what I quoted.)
This is what you quoted: «I find it ironic that Walter objects to reusing operators such as "<<" while he is reusing "!" for templates»
 You might want to keep those aspects to yourself or express
You don't get to tell me what I want or do not want to express. You're an obnoxious kid. :-)
 their subjectivity more explicitly if you don't want them to be
"I find it ironic". What more do you need?
 In the context of C, "*" means either "dereference" or 
 "multiply". "&" means either "take address" or "bitwise and".
And D blindly copies those mistakes. How does C's mistakes have any relevance to this?
 Also, I'm not defending anything. I was attacking annoying 
 rhetoric.
I find it ironic that you keep trying to make your own subjectivity look objective when it is rather obvious that your are engaging in blatant advocacy which just sement the idea that the design rationale behind D2's syntax is sound. It isn't. It breaks with basic usability principles. The usability of D is not improving, and complaining about other languages' minor issues won't fix it. There is way too much resistance to fixing the language, both interface and semantics. That keeps D at a hobby level. Or to put it bluntly: C, C++ and Rust having crappy syntaxes does not make D look a whole lot better. In order to do better, you have to be better. C/C++ are bogged down with legacy. There is no reason for D to be. What keeps D from improving comes down to this: stubborn ignorance. Offensive, but true.
Feb 24 2016
parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/24/2016 9:43 PM, Ola Fosheim Grøstad wrote:
 You're an obnoxious kid. :-)
Such statements are not welcome here. Please stop.
Feb 24 2016
prev sibling next sibling parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Tuesday, 23 February 2016 at 20:35:16 UTC, Ola Fosheim Grøstad 
wrote:
 But in C/C++ "x->m" is a shorthand for "(*x).f".
I remember many compiling errors were I'd have to switch . with -> and vice versa... I don't really want to return to that, especially when you have two versions of compilers.
 C++ also have "and" and "or" as a shorthand for "&&" and "||", 
 btw. I think "and" and "or" often makes code look more 
 readable, yet I've never seen them used.
Considering it's just an #include forcing a replacement, it hides a little of what it's doing. Honestly && and || look fine to me. More confusing if they are 3 levels deep and lots of them, but 2-4 of them are easy to glance at and get the idea what's going on.
 Yes, I also like arrows for suggesting the direction when you 
 have pipelines.
But they only ever go one way... left to right.
 The primary issue I have with iostream is that floating point 
 formatting gets ugly. The "<<" works out ok for iostream in 
 practice, mostly because it is not common to do bit-shifts in 
 combination with IO.
I'd argue that, but I don't really have the experience to show an example. C and C++ were both very close to the hardware, every symbol and feature is almost a 1:1 representation of the machine code/intent, then compiled to work on that specific machine: + is add, - is sub, ~ is neg, etc etc. That's another reason -> was used because the indirection could make a noticeable difference in heavy code (especially if they were several levels deep).
 And I have to say that I find it ironic that Walter objects to 
 reusing operators such as "<<" while he is reusing "!" for 
 templates, which I find waaay more annoying than iostream.
So you're annoyed that Walter uses ! which is used 1/500th the time compared to << and >>, and by using ! he avoided the annoying <> which causes lots of slowdowns during compiling while doing templates. One of the best reasons ! works is it's an unary operation, compared to << >> < and >. He also reused ~ for appending (previously neg) also used about 1/500th of the time, but you aren't complaining about that (unless I just haven't noticed since I'm not watching the forums closely).
Feb 23 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Tuesday, 23 February 2016 at 20:54:25 UTC, Era Scarecrow wrote:
  Considering it's just an #include forcing a replacement, it 
 hides a little of what it's doing. Honestly && and || look fine
No, they are keywords. http://en.cppreference.com/w/cpp/keyword/and
 machine: + is add, - is sub, ~ is neg, etc etc. That's another 
 reason -> was used because the indirection could make a 
 noticeable difference in heavy code (especially if they were 
 several levels deep).
Huh? C is a minimalistic language, where even basic operations are just syntactical sugar. E.g. "a[2+3]" is just a short hand for "*(a+2+3)".
  So you're annoyed that Walter uses ! which is used 1/500th the 
 time compared to << and >>, and by using ! he avoided the 
 annoying <> which causes lots of slowdowns during compiling 
 while doing templates.
No way "!" is less used than "<<"... And "<...>" does not cause noticable slow downs when compiling.
 One of the best reasons ! works is it's an unary operation, 
 compared to << >> < and >. He also reused ~ for appending 
 (previously neg) also used about 1/500th of the time,
Another horrible idea.
 but you aren't complaining about that (unless I just haven't 
 noticed since I'm not watching the forums closely).
Oh yes, I have. :-)
Feb 23 2016
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 2/23/2016 12:35 PM, Ola Fosheim Grøstad wrote:
 And I have to say that I find it ironic that Walter objects to reusing
operators
 such as "<<" while he is reusing "!" for templates,
Hardly. ! is not an overloadable operator in D, and ! has no binary operator meaning other than for template argument lists. I.e. it is not "reuse" at all. Furthermore, iostreams' use of << is neither thread-safe nor exception-safe, though its designer could be forgiven because iostreams predates both concepts. The only interesting thing about iostreams is why it wasn't deprecated 20 years ago, despite being ugly, not thread-safe, not exception-safe, and slow.
Feb 23 2016
parent reply Suliman <evermind live.ru> writes:
On Wednesday, 24 February 2016 at 07:19:02 UTC, Walter Bright 
wrote:
 On 2/23/2016 12:35 PM, Ola Fosheim Grøstad wrote:
 And I have to say that I find it ironic that Walter objects to 
 reusing operators
 such as "<<" while he is reusing "!" for templates,
Hardly. ! is not an overloadable operator in D, and ! has no binary operator meaning other than for template argument lists. I.e. it is not "reuse" at all. Furthermore, iostreams' use of << is neither thread-safe nor exception-safe, though its designer could be forgiven because iostreams predates both concepts. The only interesting thing about iostreams is why it wasn't deprecated 20 years ago, despite being ugly, not thread-safe, not exception-safe, and slow.
Could you add to D operators like AND OR etc instead of && ||. Words are more readable.
Feb 23 2016
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/23/2016 11:23 PM, Suliman wrote:
 Could you add to D operators like AND OR etc instead of && ||. Words are more
 readable.
Those exist in C++ and I've never seen them used outside of a test suite. That's not encouraging.
Feb 23 2016
prev sibling parent reply wobbles <grogan.colin gmail.com> writes:
On Wednesday, 24 February 2016 at 07:23:03 UTC, Suliman wrote:
 On Wednesday, 24 February 2016 at 07:19:02 UTC, Walter Bright 
 wrote:
 On 2/23/2016 12:35 PM, Ola Fosheim Grøstad wrote:
 [...]
Hardly. ! is not an overloadable operator in D, and ! has no binary operator meaning other than for template argument lists. I.e. it is not "reuse" at all. Furthermore, iostreams' use of << is neither thread-safe nor exception-safe, though its designer could be forgiven because iostreams predates both concepts. The only interesting thing about iostreams is why it wasn't deprecated 20 years ago, despite being ugly, not thread-safe, not exception-safe, and slow.
Could you add to D operators like AND OR etc instead of && ||. Words are more readable.
It's a matter of taste I think. I find 'and's and 'or's less readable than && and ||. I suspect that's because I'm used to looking at them.
Feb 24 2016
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 24 February 2016 at 08:46:40 UTC, wobbles wrote:
 On Wednesday, 24 February 2016 at 07:23:03 UTC, Suliman wrote:
 On Wednesday, 24 February 2016 at 07:19:02 UTC, Walter Bright 
 wrote:
It's a matter of taste I think. I find 'and's and 'or's less readable than && and ||. I suspect that's because I'm used to looking at them.
Well, I use "&&" and not "and" in C++, although I think I ought to use "and" because long sequences of sigils is harder to separate. If anything the fact that C++ programmers don't use "and" and "or" shows how strong the effect of cultural influence is on "spelling". I am pretty sure that if "&&" had been introduced later than "and", then the roles had been switched. Interestingly Pony is enforcing parentheses on most operators, under the assumption that programmers often get precedence rules wrong. Which is good for correctness. They could probably loosen it up a bit, but it is better than what we see in the C-family of languages.
Feb 24 2016
prev sibling parent reply Dominikus Dittes Scherkl <Dominikus.Scherkl continental-corporation.com> writes:
On Tuesday, 23 February 2016 at 20:35:16 UTC, Ola Fosheim Grøstad 
wrote:
 The primary issue I have with iostream is that floating point 
 formatting gets ugly. The "<<" works out ok for iostream in 
 practice, mostly because it is not common to do bit-shifts in 
 combination with IO.
stdout << "double value is: " << i<<1; Oops. This happens, and you won't notice until someone complains about the wrong value in the output. in D neither ! nor ~ is "reused". They are both unary operators in C. D only defined new binary operators which use the same characters, but there is no way to confuse them. On the other side having two different "piplining" operators "." and "->" makes refactoring the code an ugly mess: If you decided to use a reference parameter instead of a pointer you have to replace all "->" by ".". But oops, there is still a pointer within the referenced struct? So, don't replace them all, but carefully revisit them to check where "." is necessary and where "->". I always hated that!
Feb 23 2016
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 24 February 2016 at 07:25:13 UTC, Dominikus Dittes 
Scherkl wrote:
 stdout << "double value is: " << i<<1;

 Oops.
error: invalid operands of types '_IO_FILE*' and 'const char [18]' to binary 'operator<<'
 This happens, and you won't notice until someone complains 
 about the wrong value in the output.
Only a neophyte would make such a mistake. Thanks to the messy precedence for operators in C you always have to be careful with parentheses.
 in D neither ! nor ~ is "reused". They are both unary operators 
 in C. D only defined new binary operators which use the same 
 characters, but there is no way to confuse them.
I am used to D-advocates blindly defending any position, but claiming that symbols aren't reused in D isn't a position I would expect anyone to defend. Unary or binary is not the issue. if(!a!(c,!d)(!e)){...} a~=3; b=~3;
 On the other side having two different "piplining" operators 
 "." and "->" makes refactoring the code an ugly mess: If you 
 decided to use a reference parameter instead of a pointer you 
 have to replace all "->" by ".". But oops, there is still a 
 pointer within the referenced struct?
In C++ I typically use "&" or "&&" references instead of pointers. In D's "Unique" you get weak duck-typing where you risk accessing a member of Unique instead of the object. However for C++ smart pointers you generally use "->" so you get strong typing.
Feb 24 2016
parent jmh530 <john.michael.hall gmail.com> writes:
On Wednesday, 24 February 2016 at 10:03:19 UTC, Ola Fosheim 
Grøstad wrote:
 if(!a!(c,!d)(!e)){...}
Working through this, !a, !d, and !e are unary operators a!(x)(y) is the only template Looks messy, but really isn't that hard to figure out. I don't think !d makes sense as a template argument (unary not something usually doesn't produce a type). If you want it even easier to understand, how about: alias acd = a!(c, d); if(!(acd(!e)))
 a~=3;
 b=~3;
I agree that this is confusing. Only thing I would recommend is formatting and maybe adding parenthesis. a ~= 3; b = (~3);
Feb 24 2016
prev sibling parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
On Sunday, 21 February 2016 at 10:16:19 UTC, Jonathan M Davis 
wrote:
 As for a pipe operator, I expect that it wouldn't really help 
 any. It would be a lot like . vs -> in that it's an unnecessary 
 complication, but it would actually probably be worse. If |
I am not sure I agree with this. "->" will make it *visible* what is going on, while "." can mean many things, and I would have to investigate what .something in part of a chain does. Right?
Mar 02 2016
parent reply Piotrek <starpit tlen.pl> writes:
On Wednesday, 2 March 2016 at 13:29:03 UTC, Dejan Lekic wrote:
 I am not sure I agree with this. "->" will make it *visible* 
 what is going on, while "." can mean many things, and I would 
 have to investigate what .something in part of a chain does. 
 Right?
Are you sure that "->" is obvious in C++? I ask because it can mean many things, not mentioning it can be overloaded! Piotrek
Mar 02 2016
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= writes:
On Wednesday, 2 March 2016 at 15:57:41 UTC, Piotrek wrote:
 Are you sure that "->" is obvious in C++? I ask because it can 
 mean many things, not mentioning it can be overloaded!
That's an odd statement. In C++ it is a member-overload that returns a pointer which is hardwired to be dereferenced by the compiler. No real relation... Anyway, trying to prevent library authors from providing the means to express an algebra is the antithesis of a programming language for generic programming. This is an area where D is fighting against itself and should either improve or focus less on generic programming. D2 is being held back by the high level legacy it inherits from D1.
Mar 02 2016
prev sibling next sibling parent deadalnix <deadalnix gmail.com> writes:
On Wednesday, 2 March 2016 at 15:57:41 UTC, Piotrek wrote:
 On Wednesday, 2 March 2016 at 13:29:03 UTC, Dejan Lekic wrote:
 I am not sure I agree with this. "->" will make it *visible* 
 what is going on, while "." can mean many things, and I would 
 have to investigate what .something in part of a chain does. 
 Right?
Are you sure that "->" is obvious in C++? I ask because it can mean many things, not mentioning it can be overloaded! Piotrek
Especially since its overloading rules are different from regular overload rules.
Mar 02 2016
prev sibling parent Dejan Lekic <dejan.lekic gmail.com> writes:
On Wednesday, 2 March 2016 at 15:57:41 UTC, Piotrek wrote:
 On Wednesday, 2 March 2016 at 13:29:03 UTC, Dejan Lekic wrote:
 I am not sure I agree with this. "->" will make it *visible* 
 what is going on, while "." can mean many things, and I would 
 have to investigate what .something in part of a chain does. 
 Right?
Are you sure that "->" is obvious in C++? I ask because it can mean many things, not mentioning it can be overloaded! Piotrek
Who is talking about C++?? `->` I was talking about is completely different thing from what `->` in C++. It would/should be semantically different from `.` in D and `->` in C++.
Mar 07 2016
prev sibling parent reply krzaq <dlangmailinglist krzaq.cc> writes:
On Tuesday, 16 February 2016 at 07:59:49 UTC, w0rp wrote:
 Personally, I find this proposal for C++ to be laughable. It's 
 like hitch hiking from New York to California, and only getting 
 as far as Texas and calling it good.

 The great thing about our UFCS is the left-to-right chaining of 
 algorithms.

 x.map!(...).filter!(...).reduce!(...)

 It beats the Hell out of...

 reduce!(...)(filter!(...)(map!(...)(x)))

 This proposal will encourage non member functions, which is 
 good, but will never reach the "aha" moment D had which gave us 
 UFCS chaining.
I agree completely. Form my point of view, UFCS is D's biggest advantage over C++ (beating CTFE and saner templates). It was the thing that I hoped for the most in C++17. Alas, we'll be forced to write onion code. This sucks. By the way, your example in C++ would be even worse: auto sum_of_filtered = x .map([&](auto&& val){ foo(val); }) .filter([](auto&& val){ return is_bar(val); }) .reduce(std::plus<>{}); vs auto sum_of_filtered = reduce(filter(map(x, [&](auto&& val){ foo(val); }) ,[](auto&& val){ return is_bar(val); }), std::plus<>{}); Try adding an additional pass there. Where do you put the comma and second/third argument? I have no idea how to indent that properly and creating a myriad of named temporary variables for no valid reason makes me hurt inside.
Feb 16 2016
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 16.02.2016 11:21, krzaq wrote:
 By the way, your example in C++ would be even worse:

 auto sum_of_filtered = x
      .map([&](auto&& val){ foo(val); })
      .filter([](auto&& val){ return is_bar(val); })
      .reduce(std::plus<>{});

 vs

 auto sum_of_filtered =
 reduce(filter(map(x, [&](auto&& val){ foo(val); }) ,[](auto&& val){
 return is_bar(val); }), std::plus<>{});
auto sum_of_filtered = x >>= map([&](auto&& val){ return foo(val); }) | filter([](auto&& val){ return is_bar(val); }) | reduce(std::plus<>{});
Feb 16 2016
parent krzaq <dlangmailinglist krzaq.cc> writes:
On Tuesday, 16 February 2016 at 11:08:28 UTC, Timon Gehr wrote:
 On 16.02.2016 11:21, krzaq wrote:
 By the way, your example in C++ would be even worse:

 auto sum_of_filtered = x
      .map([&](auto&& val){ foo(val); })
      .filter([](auto&& val){ return is_bar(val); })
      .reduce(std::plus<>{});

 vs

 auto sum_of_filtered =
 reduce(filter(map(x, [&](auto&& val){ foo(val); }) ,[](auto&& 
 val){
 return is_bar(val); }), std::plus<>{});
auto sum_of_filtered = x >>= map([&](auto&& val){ return foo(val); }) | filter([](auto&& val){ return is_bar(val); }) | reduce(std::plus<>{});
This will only work with stream-aware functions. That might've been your intention, but to me it's only the next best thing. Additionally, adding IDE code completion will be pretty difficult here.
Feb 16 2016
prev sibling parent reply bitwise <bitwise.pvt gmail.com> writes:
On Saturday, 13 February 2016 at 10:27:59 UTC, Daniel N wrote:
 "Abstract
 This is the proposed wording for a unified call syntax based on 
 the idea that f(x,y) can invoke a member function, x.f(y), if 
 there are no f(x,y). The inverse transformation, from x.f(y) to 
 f(x,y) is not proposed."

 They were considering 6 alternatives and chose the worst...
 https://isocpp.org/files/papers/P0251R0.pdf
Am I crazy, or is this paper proposing the exact opposite of what would be needed to do chaning of ranges or extension methods? I don't get how it would be useful at all to type f(x, y) and have the compiler call x.f(y) for me. Why would I ever not want to just use member invocation syntax? Bit
Feb 20 2016
next sibling parent Era Scarecrow <rtcvb32 yahoo.com> writes:
On Sunday, 21 February 2016 at 00:52:13 UTC, bitwise wrote:
 I don't get how it would be useful at all to type f(x, y) and 
 have the compiler call x.f(y) for me. Why would I ever not want 
 to just use member invocation syntax?
One reason could be connecting to OO based code that's written purely in C (but doesn't have the member invocation). I think a good portion of XWindows was written that way. Beyond that I'm not sure.
Feb 20 2016
prev sibling next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Sunday, 21 February 2016 at 00:52:13 UTC, bitwise wrote:
 Am I crazy, or is this paper proposing the exact opposite of 
 what would be needed to do chaning of ranges or extension 
 methods?
That is a good thing.
 I don't get how it would be useful at all to type f(x, y) and 
 have the compiler call x.f(y) for me. Why would I ever not want 
 to just use member invocation syntax?
Generic code cannot assume they exist. E.g. cbegin(x)
Feb 20 2016
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, 21 February 2016 at 00:52:13 UTC, bitwise wrote:
 On Saturday, 13 February 2016 at 10:27:59 UTC, Daniel N wrote:
 "Abstract
 This is the proposed wording for a unified call syntax based 
 on the idea that f(x,y) can invoke a member function, x.f(y), 
 if there are no f(x,y). The inverse transformation, from 
 x.f(y) to f(x,y) is not proposed."

 They were considering 6 alternatives and chose the worst...
 https://isocpp.org/files/papers/P0251R0.pdf
Am I crazy, or is this paper proposing the exact opposite of what would be needed to do chaning of ranges or extension methods? I don't get how it would be useful at all to type f(x, y) and have the compiler call x.f(y) for me. Why would I ever not want to just use member invocation syntax?
Because UFCS is not about chaining function calls. It's about being able to call a function without worrying about whether it's a free function or a member function. Without some form of UFCS, it really doesn't work well for generic code to be able to call a function when some types define the function and others work with a free function with the same name, because the syntax to call them is different, meaning that the same code won't work with both types. Regardless of whether UFCS is foo(x, y) or x.foo(y), it allows for a _universal_ way to call a function (hence the name Universal Function Call Syntax). That's the whole point. Much as many folks love how D's version of UFCS makes it really easy to chain function calls, it's really not the main goal of UFCS. It's just a nice side effect of how we've done it. C++ will still get all of the benefits for generic code the way that they're doing it. So, they'll get the intended benefit of UFCS. They just won't get the side benefits that many folks like about the syntax that D chose. - Jonathan M Davis
Feb 21 2016