February 14, 2017
On Tuesday, 14 February 2017 at 10:21:03 UTC, Johannes Pfau wrote:
> Am Mon, 13 Feb 2017 19:49:28 -0800
> schrieb Timothee Cour via Digitalmars-d <digitalmars-d@puremagic.com>:
>
>> What about allowing syntax sugar as an alternative to relying on the new `from/Module` inline import idiom:
>> 
>> ```
>> void fun(T)(std.stdio::File input, T value) if
>> (std.traits::isIntegral!T) {...}
>> ```
>
> If you use a single ':' instead you can argue it's simply a shortened, inline version of a selective import:
>
> import std.stdio : File;
> //still valid D
> import std.stdio:File;
> //expression instead of statement => remove ;
> import std.stdio:File
> //We're not importing a symbol, we're simply referring to it
> std.stdio:File
>
> -- Johannes

my_module:File

is it a label followed by File or File inside my_module?

February 14, 2017
On Tuesday, 14 February 2017 at 10:23:51 UTC, Daniel N wrote:
>>
>> -- Johannes
>
> my_module:File
>
> is it a label followed by File or File inside my_module?

This would be unambiguous AFAIK, since labels can't start with "import."

import.my_module:File


February 14, 2017
Dne 14.2.2017 v 11:21 Johannes Pfau via Digitalmars-d napsal(a):

> Am Mon, 13 Feb 2017 19:49:28 -0800
> schrieb Timothee Cour via Digitalmars-d <digitalmars-d@puremagic.com>:
>
>> What about allowing syntax sugar as an alternative to relying on the
>> new `from/Module` inline import idiom:
>>
>> ```
>> void fun(T)(std.stdio::File input, T value) if
>> (std.traits::isIntegral!T) {...}
>> ```
> If you use a single ':' instead you can argue it's simply a shortened,
> inline version of a selective import:
>
> import std.stdio : File;
> //still valid D
> import std.stdio:File;
> //expression instead of statement => remove ;
> import std.stdio:File
> //We're not importing a symbol, we're simply referring to it
> std.stdio:File
> -- Johannes
Exactly! I was going to write the same
February 14, 2017
On Tuesday, February 14, 2017 10:55:51 Jacob Carlborg via Digitalmars-d wrote:
> On 2017-02-14 04:49, Timothee Cour via Digitalmars-d wrote:
> > What about allowing syntax sugar as an alternative to relying on the new `from/Module` inline import idiom:
> >
> > ```
> > void fun(T)(std.stdio::File input, T value) if
> > (std.traits::isIntegral!T) {...}
> > ```
> >
> > instead of:
> >
> > ```
> > void fun(T)(Module!"std.stdio".File input, T value) if
> > (Module!"std.traits".isIntegral!T) {...}
> > ```
> >
> > Rationale:
> >
> > * this reads much better (less noise); same as `=>` syntax for lambdas
> >
> > * this is expected to be a very common pattern, so might as well make it as simple as possible
>
> Why? It looks awful. The signatures we already have in Phobos is quite ridiculous, this will not improve. Isn't this and the whole idea of DIP 1005 just a workaround for the compiler not lazily analyzing the symbols.

Mostly, but not just that. By having something like DIP 1005, all of the imports required for the function can be associated with the function. So, people reading the code then have an easier time figuring out where the symbols come from, and it could be that the compiler could take advantage of that somehow. It does seem though that the main motivator for DIP 1005 is the fact that we don't have lazy imports, and Walter has talked before about wanting to do fully lazy imports. So, I expect that we'll get them at some point, at which point, any performance improvements from DIP 1005 or the from template would likely become moot, and the only benefit left is essentially documentation.

Personally, I might use DIP 1005 in some cases if we end up with it, but I won't use from unless I'm forced to. As cool as it is that we can do it with the language as-is, it's far too verbose and far too ugly. As it is, I'm getting sick of doing local and selective imports all over the place like everyone seems to think is best practice. I understand why they're theoretically good, but it results in longer code, and it gets very tedious to have to try and maintain the list of symbols that are imported instead of just importing the modules you need at the top of the module and forgetting about it. Doing what DIP 1005 and from push for just takes that pain to another level. It might be worth it in code used by tons of people (like Phobos), but for most code, I'm increasingly of the opinion that it's not worth it. And having proper lazy imports would largely fix the compilation cost of simply importing modules. So, I'm very much in favor of getting lazy imports, and while I do see _some_ value in documenting where stuff comes from via something like DIP 1005, I seriosuly question that it's worth the extra pain. And when you have all of those function attributes to worry about on top of that... It's just getting to be too much.

- Jonathan M Davis

February 14, 2017
On Tuesday, 14 February 2017 at 09:55:51 UTC, Jacob Carlborg wrote:
> Why? It looks awful. The signatures we already have in Phobos is quite ridiculous, this will not improve. Isn't this and the whole idea of DIP 1005 just a workaround for the compiler not lazily analyzing the symbols.

This.

February 14, 2017
Am Tue, 14 Feb 2017 10:23:51 +0000
schrieb Daniel N <no@public.email>:

> On Tuesday, 14 February 2017 at 10:21:03 UTC, Johannes Pfau wrote:
> > Am Mon, 13 Feb 2017 19:49:28 -0800
> > schrieb Timothee Cour via Digitalmars-d
> > <digitalmars-d@puremagic.com>:
> > 
> >> What about allowing syntax sugar as an alternative to relying on the new `from/Module` inline import idiom:
> >> 
> >> ```
> >> void fun(T)(std.stdio::File input, T value) if
> >> (std.traits::isIntegral!T) {...}
> >> ```
> >
> > If you use a single ':' instead you can argue it's simply a shortened, inline version of a selective import:
> >
> > import std.stdio : File;
> > //still valid D
> > import std.stdio:File;
> > //expression instead of statement => remove ;
> > import std.stdio:File
> > //We're not importing a symbol, we're simply referring to it
> > std.stdio:File
> >
> > -- Johannes
> 
> my_module:File
> 
> is it a label followed by File or File inside my_module?
> 

This might be a problem. Labels can only occur in front of a statement though: https://dlang.org/spec/statement.html#LabeledStatement

So it boils down to:
ModuleFullyQualifiedName:ImportBind vs LabeledStatement


-- Johannes

February 14, 2017
On Tuesday, 14 February 2017 at 09:55:51 UTC, Jacob Carlborg wrote:
> On 2017-02-14 04:49, Timothee Cour via Digitalmars-d wrote:
>> What about allowing syntax sugar as an alternative to relying on the new
>> `from/Module` inline import idiom:
>>
>> ```
>> void fun(T)(std.stdio::File input, T value) if
>> (std.traits::isIntegral!T) {...}
>> ```
>>
>> instead of:
>>
>> ```
>> void fun(T)(Module!"std.stdio".File input, T value) if
>> (Module!"std.traits".isIntegral!T) {...}
>> ```
>>
>> Rationale:
>>
>> * this reads much better (less noise); same as `=>` syntax for lambdas
>>
>> * this is expected to be a very common pattern, so might as well make it
>> as simple as possible
>
> Why? It looks awful. The signatures we already have in Phobos is quite ridiculous, this will not improve. Isn't this and the whole idea of DIP 1005 just a workaround for the compiler not lazily analyzing the symbols.

This is what I had thought as well when Andrei first posted DIP1005, but he said that his main goal is actually making it so a declaration can carry all of its imports with it in a self-contained unit. When you look at it that way it makes a bit more sense as to why we might want constructs such as introduced by DIP1005 or this self-important lookup idiom.
February 14, 2017
On 02/14/2017 04:55 AM, Jacob Carlborg wrote:
> The signatures we already have in Phobos is quite ridiculous

How are they so, and what steps can we take to improve them. Could you please give a few examples on how to do things better? Thx! -- Andrei
February 14, 2017
On 2017-02-14 15:37, Andrei Alexandrescu wrote:

> How are they so,

Example [1]. That signature spans 8 lines, it took me 10 seconds to find the actual function name. Example [2], 5 lines. Adding attributes on top of that would increase the length of the signature even more. Fortunately templates will infer most attributes.

> and what steps can we take to improve them. Could you
> please give a few examples on how to do things better? Thx! -- Andrei

Well, I would prefer to have template constraints as its own entity in the language not not just a bunch of boolean conditions. This has been talked about before several times. Something like:

constraint Foo
{
    void foo();
}

void bar(T : Foo)(T t);

[1] https://github.com/dlang/phobos/blob/master/std/algorithm/mutation.d#L1682-L1689

[2] https://github.com/dlang/phobos/blob/master/std/algorithm/mutation.d#L2729-L2733

-- 
/Jacob Carlborg
February 14, 2017
On 02/14/2017 10:49 AM, Jacob Carlborg wrote:
> On 2017-02-14 15:37, Andrei Alexandrescu wrote:
>
>> How are they so,
>
> Example [1]. That signature spans 8 lines, it took me 10 seconds to find
> the actual function name.

Copying here to make things easier:

Range remove
(SwapStrategy s = SwapStrategy.stable, Range, Offset...)
(Range range, Offset offset)
if (s != SwapStrategy.stable
    && isBidirectionalRange!Range
    && hasLvalueElements!Range
    && hasLength!Range
    && Offset.length >= 1);

The function name is on the first line. I think 10 seconds would be an exaggeration of an admittedly real issue.

> Example [2], 5 lines.

Copying here as well (reflowed for email):

Tuple!(InputRange1, InputRange2)
swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
if (isInputRange!(InputRange1) && isInputRange!(InputRange2)
    && hasSwappableElements!(InputRange1)
    && hasSwappableElements!(InputRange2)
    && is(ElementType!(InputRange1) == ElementType!(InputRange2)));

One immediate matter here is redundant parens, of which elimination would lead to the marginally more palatable:

Tuple!(InputRange1, InputRange2)
swapRanges(InputRange1, InputRange2)(InputRange1 r1, InputRange2 r2)
if (isInputRange!InputRange1 && isInputRange!InputRange2
    && hasSwappableElements!InputRange1
    && hasSwappableElements!InputRange2
    && is(ElementType!InputRange1 == ElementType!InputRange2));

>> and what steps can we take to improve them. Could you
>> please give a few examples on how to do things better? Thx! -- Andrei
>
> Well, I would prefer to have template constraints as its own entity in
> the language not not just a bunch of boolean conditions. This has been
> talked about before several times. Something like:
>
> constraint Foo
> {
>     void foo();
> }
>
> void bar(T : Foo)(T t);

My recollection is past discussions got stalled because the approach is combinatorially bankrupt. How would one express the constraints of the functions above with simple named constraints? (Not rhetorical; please do provide an example if possible.) Before long there is an explosion in names ("BidirectionalWithLvalueElementsAndLength", ...). This is what has buried not one, but two concepts proposals for C++, leading to the current Concepts Lite proposal. I haven't followed that lately but I remember it combines an engineering effort to reduce the number of names introduced (for the standard library only, which is a limitation) with adding support to Boolean logic (surprise, surprise) to the feature (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4377.pdf), the most recent proposal, which was rejected for C++17. Over time, C++ concepts have moved from the broken combinatorially-bankrupt form slowly toward D's Boolean constraints (just with a gratuitously awkward notation). I presume they will be merged into the language when they'll have capabilities comparable to D's system.

The question is, given this experience, do we want to move the opposite direction?


Andrei