January 08, 2019
On Tuesday, 8 January 2019 at 10:54:24 UTC, Martin Tschierschke wrote:
> I realized that UFCS would work only if the alias is defined outside of main();
>
> Is this a bug or a feature? Don't know if this can be solved.

It is by design - UFCS only considered for global symbols. The idea is to simplify the reasoning process for finding .members by eliminating local scopes from the search (supposed to make ide stuff easier, etc)

Whether this is good design or not is left up to the reader.
January 08, 2019
On Tuesday, 8 January 2019 at 13:40:51 UTC, Adam D. Ruppe wrote:
[...]
> It is by design - UFCS only considered for global symbols. The idea is to simplify the reasoning process for finding .members by eliminating local scopes from the search (supposed to make ide stuff easier, etc)
>
> Whether this is good design or not is left up to the reader.

So, as a result I can conclude, that real local imports don't work togethter with UFCS, and this is disabling any chaining.

January 08, 2019
On Tue, Jan 08, 2019 at 02:13:21PM +0000, Martin Tschierschke via Digitalmars-d wrote:
> On Tuesday, 8 January 2019 at 13:40:51 UTC, Adam D. Ruppe wrote: [...]
> > It is by design - UFCS only considered for global symbols. The idea is to simplify the reasoning process for finding .members by eliminating local scopes from the search (supposed to make ide stuff easier, etc)
> > 
> > Whether this is good design or not is left up to the reader.
> 
> So, as a result I can conclude, that real local imports don't work togethter with UFCS, and this is disabling any chaining.

Not true. This works:

	void main() {
		// N.B.: local imports
		import std.array;
		import std.algorithm;
		import std.conv;
		import std.stdio;

		// N.B.: UFCS chaining
		"abcdef".map!(e => cast(int) (e - 'a'))
		        .filter!(e => e < 4)
			.map!(e => cast(dchar) (e + 'm'))
			.to!string
			.writeln;
	}

To state more accurately what Adam said, UFCS is considered for *module-level* symbols. Meaning, the requirement is applied at the site of definition (it has to be at the top *level* in the module where it's defined) rather than the site of import (which can be in a local *scope*).


T

-- 
What is Matter, what is Mind? Never Mind, it doesn't Matter.
January 08, 2019
On Tuesday, 8 January 2019 at 13:39:48 UTC, JN wrote:
> On Monday, 7 January 2019 at 21:50:20 UTC, Andrei Alexandrescu wrote:
>> This is pretty awesome.
>>
>> Since the implementation would (initially at least) be private, the presence of "from" in documentation would be awkward. So I suggest the glorious hack:
>
> I am probably in minority here, or I am misunderstand the purpose of this feature, but wouldn't such stuff be better put somewhere around the compiler/frontend rather than in the library with compile-time magic?

FYI: at the end of last year Eyal (Weka) and Andrei (and me a little bit) have been discussing lazy importing (full import) of symbols by the compiler. We hope to have a student work on this.
Indeed I agree with you: the compiler could do (some of) this stuff, and because the rewards seem large it makes sense to indeed have the compiler do it.

-Johan

January 08, 2019
On Tuesday, 8 January 2019 at 14:28:47 UTC, H. S. Teoh wrote:
> On Tue, Jan 08, 2019 at 02:13:21PM +0000, Martin Tschierschke via Digitalmars-d wrote:
>> [...]
>
> Not true. This works:
>
> 	void main() {
> 		// N.B.: local imports
> 		import std.array;
> 		import std.algorithm;
> 		import std.conv;
> 		import std.stdio;
>
> 		// N.B.: UFCS chaining
> 		"abcdef".map!(e => cast(int) (e - 'a'))
> 		        .filter!(e => e < 4)
> 			.map!(e => cast(dchar) (e + 'm'))
> 			.to!string
> 			.writeln;
> 	}
>
> To state more accurately what Adam said, UFCS is considered for *module-level* symbols. Meaning, the requirement is applied at the site of definition (it has to be at the top *level* in the module where it's defined) rather than the site of import (which can be in a local *scope*).
>
>
> T
OK. Thank you!

With "real local import" I was referring to the "new import idiom" in this thread, provided by  localimport.dub.pm

mt.

January 08, 2019
On Tue, Jan 08, 2019 at 03:18:03PM +0000, Martin Tschierschke via Digitalmars-d wrote: [...]
> With "real local import" I was referring to the "new import idiom" in this thread, provided by  localimport.dub.pm
[...]

The intent of that import idiom is an import whose scope is limited to the expression it's in. It's a way of pulling in a specific symbol without "polluting" the surrounding scope. E.g. currently, if you have a module-scope declaration that requires an imported symbol, you have no choice but to import the symbol into the containing scope:

	// This import line is required otherwise the sig constraint
	// won't work.
	import std.range.primitives : isInputRange;
	auto myRangeFunc(R)(R range) if (isInputRange!R) { ... }

If this is the only function in a module of say 100 functions that requires std.range.primitives, it seems wasteful to import it into the entire module's scope.  With the new import idiom, we can do this:

	// N.B.: no more imports in module scope!
	auto myRangeFunc(R)(R range) if (from.std.range.isInputRange!R)
	{ ... }

Which also makes the declaration carry it's own import dependencies, so when you decide to refactor and move this function into another module, you'll never have to worry about also moving/copying the global import statement.

This is the primary use case of this idiom.

If you actually need the import symbols into the containing scope, just use the built-in import statement instead! :-D

	auto myRangeFunc(R)(R range) if (from.std.range.isInputRange!R)
	{
		// We need std.uni in this function, so just pull it
		// into the function scope. No need to pull out the
		// expression-local import warhead!
		import std.uni : isWhite;

		while (!range.empty && isWhite(range.front))
			range.popFront;
		...
		// more uses of isWhite here
		...
	}


T

-- 
LINUX = Lousy Interface for Nefarious Unix Xenophobes.
January 08, 2019
On Monday, 7 January 2019 at 21:50:20 UTC, Andrei Alexandrescu wrote:
> the presence of "from" in documentation would be awkward. So I suggest the glorious hack:
>
> alias std = from.std;

Apart from compiler overhead, this seems to make `static import` redundant.
January 08, 2019
On Tuesday, January 8, 2019 7:40:47 AM MST Johan Engelen via Digitalmars-d wrote:
> On Tuesday, 8 January 2019 at 13:39:48 UTC, JN wrote:
> > On Monday, 7 January 2019 at 21:50:20 UTC, Andrei Alexandrescu
> >
> > wrote:
> >> This is pretty awesome.
> >>
> >> Since the implementation would (initially at least) be private, the presence of "from" in documentation would be
> >
> >> awkward. So I suggest the glorious hack:
> > I am probably in minority here, or I am misunderstand the purpose of this feature, but wouldn't such stuff be better put somewhere around the compiler/frontend rather than in the library with compile-time magic?
>
> FYI: at the end of last year Eyal (Weka) and Andrei (and me a
> little bit) have been discussing lazy importing (full import) of
> symbols by the compiler. We hope to have a student work on this.
> Indeed I agree with you: the compiler could do (some of) this
> stuff, and because the rewards seem large it makes sense to
> indeed have the compiler do it.

Yeah, Walter has expressed interest in having lazy imports in the past (e.g. he talked about it when Liran was complaining about importing issues at dconf a few years ago). So, if it were implemented, I wouldn't expect it to have much trouble getting merged. Personally, I've argued every time this sort of solution has come up that it's incredibly ugly and tedious and that we should just do lazy imports if possible, because they would cleanly fix the compilation times without requiring such verbose workarounds. But of course, someone has to actually do the work of implementing lazy imports.

- Jonathan M Davis



January 09, 2019
On Tuesday, 8 January 2019 at 14:40:47 UTC, Johan Engelen wrote:
> On Tuesday, 8 January 2019 at 13:39:48 UTC, JN wrote:
>> On Monday, 7 January 2019 at 21:50:20 UTC, Andrei Alexandrescu wrote:
>>> This is pretty awesome.
>>>
>>> Since the implementation would (initially at least) be private, the presence of "from" in documentation would be awkward. So I suggest the glorious hack:
>>
>> I am probably in minority here, or I am misunderstand the purpose of this feature, but wouldn't such stuff be better put somewhere around the compiler/frontend rather than in the library with compile-time magic?
>
> FYI: at the end of last year Eyal (Weka) and Andrei (and me a little bit) have been discussing lazy importing (full import) of symbols by the compiler. We hope to have a student work on this.
> Indeed I agree with you: the compiler could do (some of) this stuff, and because the rewards seem large it makes sense to indeed have the compiler do it.
>
> -Johan

Make sure whoever works on it is aware of this:

https://github.com/marler8997/dlangfeatures#lazy-imports

To summarize, there's no way to make normal imports lazy (i.e. "import foo;"). However we can make the following lazy by default:

1. static imports (static import std.typecons;)
2. selective imports (import std.typecons: isBigEndian;)
3. aliased imports (import t = std.typecons;)

I had a partial implementation for lazy imports, but Walter never reviewed my other pull requests so I never pushed it.

January 09, 2019
On Wednesday, 9 January 2019 at 22:39:58 UTC, Jonathan Marler wrote:
> Make sure whoever works on it is aware of this:
>
> https://github.com/marler8997/dlangfeatures#lazy-imports
>
> To summarize, there's no way to make normal imports lazy (i.e. "import foo;"). However we can make the following lazy by default:
>
> 1. static imports (static import std.typecons;)
> 2. selective imports (import std.typecons: isBigEndian;)
> 3. aliased imports (import t = std.typecons;)
>
> I had a partial implementation for lazy imports, but Walter never reviewed my other pull requests so I never pushed it.

Maybe I'm missing something, but wouldn't it be possible to lazy import `import foo;` if the compiler checks lazily if a symbol isn't found in the current scope and only then tries to find it in one of the imports? Or would that be ineffective?

Example:
----
import foo; // contains bar2

void bar1() { }

bar1(); // in current scope
bar2(); // not found, we have to search in the imports
----