www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - best way to handle UFCS with ambiguous names: using

reply Timothee Cour <thelastmammoth gmail.com> writes:
UFCS chains are problematic when a symbol is ambiguous (eg after import
std.stdio:write;import std.file:write);

I previously suggested to add the syntax
'arg1.(std.file.write)(arg2)'
(see 'support UFCS with fully qualified function names (was in
"digitalmars.D.learn")'  to avoid breaking UFCS chains.

Others have suggested using renamed local imports:
import std.file:write2=write;
'arg1.write2(arg2)'

This issue keeps coming up, eg '
http://forum.dlang.org/post/mailman.980.1370764406.13711.digitalmars-d puremagic.com',
prompting some to prefer symbols with unique, redundant names eg
std.compress.lzw.lzwCompress instead of std.compress.lzw.compress.

However I found a much better way:

*import std. typetuple:Alias;*
*'arg1.Alias!(std.file.write).arg2'*

Interestingly, I haven't found this pattern in phobos.

advantage:

* UFCS chain not broken; no loss of efficiency
* library solution, already works, no need to add new syntax
* avoids the renamed local imports, which I argue is a bad idea (makes it
harder to search for usages of a function, ie 'grep' won't work)
* systematic way to handle the such cases, whereas renamed local imports
require to 'guess' a good name, eg import std.file:write2=write;
* renamed local imports require 1 import declaration syntax per ambiguous
UFCS function (eg import std.file:write2=write needed even if import
std.file is already there), whereas a single import std.typetuple
declaration handles all ambiguous cases).

Bigger example:
----
void main(){
import std.typetuple;

import std.stdio;
import std.file;
import std.range;
import std.algorithm;

"hello2".Alias!(std.stdio.write);
3.iota.map!(a=>a*a).Alias!(std.algorithm.reduce!"a+b").Alias!(std.stdio.writeln);
}
----
Jun 09 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 10 June 2013 at 02:02:09 UTC, Timothee Cour wrote:
 UFCS chains are problematic when a symbol is ambiguous (eg 
 after import
 std.stdio:write;import std.file:write);

 I previously suggested to add the syntax
 'arg1.(std.file.write)(arg2)'
 (see 'support UFCS with fully qualified function names (was in
 "digitalmars.D.learn")'  to avoid breaking UFCS chains.
We should allow this anyway, simply to deal with static imports.
Jun 10 2013
parent reply "timotheecour" <timothee.cour2 gmail.com> writes:
On Monday, 10 June 2013 at 08:13:42 UTC, John Colvin wrote:
 On Monday, 10 June 2013 at 02:02:09 UTC, Timothee Cour wrote:
 UFCS chains are problematic when a symbol is ambiguous (eg 
 after import
 std.stdio:write;import std.file:write);

 I previously suggested to add the syntax
 'arg1.(std.file.write)(arg2)'
 (see 'support UFCS with fully qualified function names (was in
 "digitalmars.D.learn")'  to avoid breaking UFCS chains.
We should allow this anyway, simply to deal with static imports.
What do you mean? Are you arguing in favor of arg1.(std.file.write)(arg2) ? It seems people didn't like that first proposal. In any case, I'm arguing that Alias as I've suggested is always better than renamed import.
Jun 11 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 11 June 2013 at 18:47:08 UTC, timotheecour wrote:
 On Monday, 10 June 2013 at 08:13:42 UTC, John Colvin wrote:
 On Monday, 10 June 2013 at 02:02:09 UTC, Timothee Cour wrote:
 UFCS chains are problematic when a symbol is ambiguous (eg 
 after import
 std.stdio:write;import std.file:write);

 I previously suggested to add the syntax
 'arg1.(std.file.write)(arg2)'
 (see 'support UFCS with fully qualified function names (was in
 "digitalmars.D.learn")'  to avoid breaking UFCS chains.
We should allow this anyway, simply to deal with static imports.
What do you mean? Are you arguing in favor of arg1.(std.file.write)(arg2) ? It seems people didn't like that first proposal.
Having thought about it it's probably not a good idea.
Jun 11 2013
prev sibling next sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
I think selective, renamed imports are much better.

On Monday, 10 June 2013 at 02:02:09 UTC, Timothee Cour wrote:
 * library solution, already works, no need to add new syntax
 * avoids the renamed local imports, which I argue is a bad idea 
 (makes it
 harder to search for usages of a function, ie 'grep' won't work)
The search will yield the site of renaming, where the alias can be found and included in the search. It's not overly troublesome. Most good renames might include the original name as part of the alias anyway, in which case all you might need is case-insensitive search.
 * systematic way to handle the such cases, whereas renamed 
 local imports
 require to 'guess' a good name, eg import std.file:write2=write;
Do you "guess" identifier names when you introduce other symbols, too?
 * renamed local imports require 1 import declaration syntax per 
 ambiguous
 UFCS function (eg import std.file:write2=write needed even if 
 import
 std.file is already there), whereas a single import 
 std.typetuple
 declaration handles all ambiguous cases).
Conflicts are very rare and the rename can be included at function scope which is often going to be feasible. Also, a separate import statement is not necessary in cases where selective imports are already used.
Jun 11 2013
prev sibling parent "ixid" <nuaccount gmail.com> writes:
On Monday, 10 June 2013 at 02:02:09 UTC, Timothee Cour wrote:
 UFCS chains are problematic when a symbol is ambiguous (eg 
 after import
 std.stdio:write;import std.file:write);

 I previously suggested to add the syntax
 'arg1.(std.file.write)(arg2)'
 (see 'support UFCS with fully qualified function names (was in
 "digitalmars.D.learn")'  to avoid breaking UFCS chains.

 Others have suggested using renamed local imports:
 import std.file:write2=write;
 'arg1.write2(arg2)'

 This issue keeps coming up, eg '
 http://forum.dlang.org/post/mailman.980.1370764406.13711.digitalmars-d puremagic.com',
 prompting some to prefer symbols with unique, redundant names eg
 std.compress.lzw.lzwCompress instead of 
 std.compress.lzw.compress.

 However I found a much better way:

 *import std. typetuple:Alias;*
 *'arg1.Alias!(std.file.write).arg2'*

 Interestingly, I haven't found this pattern in phobos.

 advantage:

 * UFCS chain not broken; no loss of efficiency
 * library solution, already works, no need to add new syntax
 * avoids the renamed local imports, which I argue is a bad idea 
 (makes it
 harder to search for usages of a function, ie 'grep' won't work)
 * systematic way to handle the such cases, whereas renamed 
 local imports
 require to 'guess' a good name, eg import std.file:write2=write;
 * renamed local imports require 1 import declaration syntax per 
 ambiguous
 UFCS function (eg import std.file:write2=write needed even if 
 import
 std.file is already there), whereas a single import 
 std.typetuple
 declaration handles all ambiguous cases).

 Bigger example:
 ----
 void main(){
 import std.typetuple;

 import std.stdio;
 import std.file;
 import std.range;
 import std.algorithm;

 "hello2".Alias!(std.stdio.write);
 3.iota.map!(a=>a*a).Alias!(std.algorithm.reduce!"a+b").Alias!(std.stdio.writeln);
 }
 ----
It seems like a goofy choice to have two extremely common library functions share the same name.
Jun 11 2013