digitalmars.D - Is this correct?
- Jonathan Marler (16/16) Feb 06 2020 The named arguments DIP got to question what this example would
- Adam D. Ruppe (9/10) Feb 06 2020 Yes. (at least for those of us intimately familiar with the spec,
- Steven Schveighoffer (22/43) Feb 06 2020 Yes. Overloads sets are delineated by scope, from inner to outer. All
- Timon Gehr (11/32) Feb 06 2020 Yes. The justification for this is that otherwise foolib could silently
- Petar Kirov [ZombineDev] (42/58) Feb 06 2020 It's surprising, but it has to do with how overload sets are
- Walter Bright (2/3) Feb 06 2020 To everyone who replied: All great answers!
The named arguments DIP got to question what this example would
do:
--- foolib.d
import std.stdio;
void foo(string s) { writefln("foo string"); }
--- main.d
import std.stdio;
import foolib;
void foo(const(char)[] s) { writefln("foo const"); }
void main()
{
foo("hello");
}
This prints "foo const". And if you move the function overload
from foolib.d to main.d, it will print "foo string". Is this the
expected behavior?
Feb 06 2020
On Thursday, 6 February 2020 at 23:05:19 UTC, Jonathan Marler wrote:Is this the expected behavior?Yes. (at least for those of us intimately familiar with the spec, lol, it is a faq among others) This is the anti-hijacking rule described here: https://dlang.org/articles/hijack.html Local functions are NOT overloaded against functions from a different namespace. If you want that, you must explicitly opt in by doing `alias foo = other.module.foo`
Feb 06 2020
On 2/6/20 6:05 PM, Jonathan Marler wrote:
The named arguments DIP got to question what this example would do:
--- foolib.d
import std.stdio;
void foo(string s) { writefln("foo string"); }
--- main.d
import std.stdio;
import foolib;
void foo(const(char)[] s) { writefln("foo const"); }
void main()
{
foo("hello");
}
This prints "foo const". And if you move the function overload from
foolib.d to main.d, it will print "foo string". Is this the expected
behavior?
Yes. Overloads sets are delineated by scope, from inner to outer. All
imported modules count as a further outer scope. See information here:
https://dlang.org/spec/function.html#overload-sets
In order to bring imported symbols into your overload set, you need to
alias them. Also you could selectively import the symbol to get it into
the module's namespace.
--- main.d
import std.stdio;
import foolib;
alias foo = foolib.foo; // this or import foolib: foo;
void foo(const(char)[] s) { writefln("foo const"); }
void main()
{
foo("hello");
}
---
prints foo string
As a demonstration to realize it stops at your module's scope, change
the local foo to accept an int (and don't alias in the external foo),
and you will get an error even though foolib.foo could accept the parameter.
-Steve
Feb 06 2020
On 07.02.20 00:05, Jonathan Marler wrote:
The named arguments DIP got to question what this example would do:
--- foolib.d
import std.stdio;
void foo(string s) { writefln("foo string"); }
--- main.d
import std.stdio;
import foolib;
void foo(const(char)[] s) { writefln("foo const"); }
void main()
{
foo("hello");
}
This prints "foo const". And if you move the function overload from
foolib.d to main.d, it will print "foo string". Is this the expected
behavior?
Yes. The justification for this is that otherwise foolib could silently
hijack your main.d by introducing a new function "foo". If you want to
overload against the library function, you can use an alias:
import std.stdio;
import foolib;
alias foo=foolib.foo;
void foo(const(char)[] s) { writefln("foo const"); }
void main(){
foo("hello"); // foo string
}
Feb 06 2020
On Thursday, 6 February 2020 at 23:05:19 UTC, Jonathan Marler
wrote:
The named arguments DIP got to question what this example would
do:
--- foolib.d
import std.stdio;
void foo(string s) { writefln("foo string"); }
--- main.d
import std.stdio;
import foolib;
void foo(const(char)[] s) { writefln("foo const"); }
void main()
{
foo("hello");
}
This prints "foo const". And if you move the function overload
from foolib.d to main.d, it will print "foo string". Is this
the expected behavior?
It's surprising, but it has to do with how overload sets are
created.
You can get the "foo string" by using a selective import:
--- foolib.d
import std.stdio;
void foo(string s) { writefln("foo string"); }
--- main.d
import std.stdio;
import foolib : foo;
void foo(const(char)[] s) { writefln("foo const"); }
void main()
{
foo("hello");
}
Which is essentially equivalent to a private alias:
--- foolib.d
import std.stdio;
void foo(string s) { writefln("foo string"); }
--- main.d
import std.stdio;
import foolib;
private alias foo = foolib.foo;
void foo(const(char)[] s) { writefln("foo const"); }
void main()
{
foo("hello");
}
The idea is that local symbols must take precedence
(anti-hijacking principle - adding imports should not change the
meaning of your code).
Overloading works when all symbols are declared in the same
scope. For example, if both overloads of foo were in foolib, then
they would naturally overload (with both normal or selective
imports).
Adding an alias is essentially creating a symbol in the local
scope - a "symlink" to another symbol.
So overload a symbol A in scope S1 with symbol B in S2, you need
to add 'alias A = S2.B' in scope S1.
Cheers,
Petar
Feb 06 2020
On 2/6/2020 3:05 PM, Jonathan Marler wrote:The named arguments DIP got to question what this example would do:To everyone who replied: All great answers!
Feb 06 2020









Adam D. Ruppe <destructionator gmail.com> 