December 14, 2016
On Wednesday, 14 December 2016 at 17:28:57 UTC, Andrei Alexandrescu wrote:
> On 12/14/2016 12:07 PM, David Gileadi wrote:
>> The above rule doesn't cover non-template function declarations like the
>> `process` example in the DIP, however. Are they an important enough use
>> case to justify new syntax?
>
> I suspect 90% of all uses will be straight definitions of template functions or template structs/classes. So by that estimate we should be in good shape.
>
> However, looking inside the definition in order to look up names in its declarations breaks the rule of least astonishment. Making the import part of the syntactical unit of the declaration seems to be the path of least resistance.

It also doesn't work with function prototypes. With the proposed syntax, you can do

    int foo(SysTime st) import(std.datetime);

but if the compiler has to look into the function body to get at the import, then a prototype like this would be out of luck.

- Jonathan M Davis
December 14, 2016
On Wednesday, 14 December 2016 at 19:39:55 UTC, Andrei Alexandrescu wrote:
> On 12/14/2016 02:04 PM, Meta wrote:
>> On Wednesday, 14 December 2016 at 17:32:10 UTC, H. S. Teoh wrote:
>>> What about:
>>>
>>>     /* Showing full declaration just for context */
>>>     bool myFunc(R1, R2)(R1 r1, R2 r2)
>>>     import {
>>>         std.range : isInputRange,
>>>         std.traits : isNum = isNumeric
>>>     }
>>>     if (isInputRange!R1 && isInputRange!R2 &&
>>>         isNum!(ElementType!R1))
>>>     in { assert(someCondition!R1); }
>>>     out(result) { assert(result == expectedResult(...)); }
>>>     body
>>>     {
>>>         ...
>>>     }
>>>

as ketmar said, would the import block have any restrictions what code could be used inside, would this work?

T1 fun(T1, T2)(T1 t1, T2 t2)
import
{
    version(A) { someMod: T1, T2; }
    else { someOtherMod: T1, T2; }

    // static if or any other code?
}
{
    T1 ret = t1 + t2;
    return ret;
}

December 14, 2016
Made a pass through the document integrating a lot of feedback and fleshing the proposal better:

https://github.com/andralex/DIPs/blob/155ff59984b26749af7830aeb172d3af2dae8cd7/DIPs/DIP1005.md

https://github.com/dlang/DIPs/pull/51/files


Andrei

December 14, 2016
On 12/14/2016 04:47 PM, ArturG wrote:
> On Wednesday, 14 December 2016 at 19:39:55 UTC, Andrei Alexandrescu wrote:
>> On 12/14/2016 02:04 PM, Meta wrote:
>>> On Wednesday, 14 December 2016 at 17:32:10 UTC, H. S. Teoh wrote:
>>>> What about:
>>>>
>>>>     /* Showing full declaration just for context */
>>>>     bool myFunc(R1, R2)(R1 r1, R2 r2)
>>>>     import {
>>>>         std.range : isInputRange,
>>>>         std.traits : isNum = isNumeric
>>>>     }
>>>>     if (isInputRange!R1 && isInputRange!R2 &&
>>>>         isNum!(ElementType!R1))
>>>>     in { assert(someCondition!R1); }
>>>>     out(result) { assert(result == expectedResult(...)); }
>>>>     body
>>>>     {
>>>>         ...
>>>>     }
>>>>
>
> as ketmar said, would the import block have any restrictions what code
> could be used inside, would this work?
>
> T1 fun(T1, T2)(T1 t1, T2 t2)
> import
> {
>     version(A) { someMod: T1, T2; }
>     else { someOtherMod: T1, T2; }
>
>     // static if or any other code?
> }
> {
>     T1 ret = t1 + t2;
>     return ret;
> }

The acceptability of the proposal decays exponentially with its deviation from existing import syntax. -- Andrei

December 14, 2016
On Wed, Dec 14, 2016 at 04:08:56PM -0500, Andrei Alexandrescu via Digitalmars-d wrote:
> On 12/14/2016 03:33 PM, H. S. Teoh via Digitalmars-d wrote:
> > That's easy to fix:
> > 
> > 	import { a : b, c;  d: e, f; }
> 
> The cost being adding new syntax. -- Andrei

Aren't we already adding new syntax?

On thinking about this again, though, isn't the whole point of this DIP to add a way of attaching imports X, Y, Z to some declaration such that the imports are in effect for the scope of the declaration?  The specific syntax is really secondary.  I think we should rather be more concerned about the semantics of it, such as:

(1) The scope of the imports: I assume the import would be in effect until the end of the function body, correct? Or does it only last until the beginning of the function body?

   (a) Are DCD-imported symbols accessible in in- and out-contracts?

   (b) Are DCD imports permitted in the definition of inner functions?
   What is their effect, if allowed? Will symbols thus imported be
   restricted to the body of the inner function, or will it be visible
   throughout the outer function body?

(2) How overloads are handled:

   (a) If the current module declares symbol X, and a DCD import pulls
   in another module that declares X, which X will it resolve to when
   the declaration references X?  Are there cases of possible symbol
   hijacking here?  What if the function body also declares a local
   symbol X?

   (b) If there are multiple DCD imports that declare symbol X, how
   would overload resolution work?

   (c) How are parameter symbols figured into overload resolution? E.g.,
   if the DCD import pulls in module M that declares a module global
   xyz, and one of the function parameter names is also xyz.

   (d) Will symbols in a DCD imported module that aren't specifically
   imported shadow module globals, parameters, or local variables?
   E.g., you import my.module : X, but my.module also declares Y, and
   there's a {module global (in the current module), parameter, local
   variable} called Y.  How would overload resolution work in this case?

(4) Are DCD imports restricted to function declarations, or template declarations, or all declarations in general?

   (a) I.e., is it possible to declare a module global of type X, where
   X is defined by another module pulled in via a DCD import?

   (b) What about the other eponymous template shorthands, like `enum
   E(X) = ...`: will it be possible to attach DCD imports to that? E.g.,
   if we want to say isInputRange!X in the enum definition.

   (c) Is it possible to attach DCD imports to delegate / lambda
   definitions? If so, what is their scope / interaction with the
   containing scope?

(5) Is it possible to attach DCD imports to individual parameters? E.g.:

	auto myFunc(import.std.stdio.File f) { ... }

	or:

	auto myFunc(scope void delegate(import.std.stdio.File f) dg)
	{ ... }

   Or do such imports have to be attached to the top-level declaration?


T

-- 
Computerese Irregular Verb Conjugation: I have preferences.  You have biases.  He/She has prejudices. -- Gene Wirchenko
December 14, 2016
On Wednesday, 14 December 2016 at 22:55:26 UTC, Andrei Alexandrescu wrote:
> Made a pass through the document integrating a lot of feedback and fleshing the proposal better:
>
> https://github.com/andralex/DIPs/blob/155ff59984b26749af7830aeb172d3af2dae8cd7/DIPs/DIP1005.md
>
> https://github.com/dlang/DIPs/pull/51/files
>
>
> Andrei

I'd also mention that the advantage of this feature is for the human reader (and not just ddoc generators) as you can instantly tell where all the symbols are located which a function uses. It could save a lot of time for the reader when analyzing a function.

For example, if we have a function like the following:

ubyte[] readSomeBytes ( )
{
    return read(1024);
}

It's a non-trivial exercise for the reader to understand where the `read` symbol is coming from. It usually involves looking up the import list at the top of the module which is typically very long and contains unrelated imports as the DIP mentions.

Sometimes you can use a symbol lookup shortcut in your editor, but with a name like `read` you'll likely get a dozen modules listed in the pop-up and you still couldn't immediately tell which one of the symbols this `read` call refers to. Someone will mention IDEs, but remember when you're looking at the code in another environment (say reviewing code on Github) you may not have quick point & click functionality to find the symbol declaration. That's another win for this DIP.
December 15, 2016
On 15.12.2016 00:17, Andrej Mitrovic wrote:
>
> ubyte[] readSomeBytes ( )
> {
>     return read(1024);
> }
>
> It's a non-trivial exercise for the reader to understand where the
> `read` symbol is coming from.

pragma(msg,fullyQualifiedName!read);
December 14, 2016
On Wednesday, 14 December 2016 at 22:56:54 UTC, Andrei Alexandrescu wrote:
>
> The acceptability of the proposal decays exponentially with its deviation from existing import syntax. -- Andrei

sorry, i missed the import keyword :/

T1 fun(T1, T2)(T1 t1, T2 t2)
import
{
     version(A)
     { import someMod: T1, T2; }
     else
     { import someOtherMod: T1, T2;}

     import std.stdio;

// this import block would support only import statemens, version and static if etc...

}
{
     t2.writeln;  // use symbols imported by the import block
     T1 ret = t1 + t2;
     return ret;
}
December 14, 2016
On 12/14/16 6:46 PM, arturg wrote:
> On Wednesday, 14 December 2016 at 22:56:54 UTC, Andrei Alexandrescu wrote:
>>
>> The acceptability of the proposal decays exponentially with its
>> deviation from existing import syntax. -- Andrei
>
> sorry, i missed the import keyword :/
>
> T1 fun(T1, T2)(T1 t1, T2 t2)
> import
> {
>      version(A)
>      { import someMod: T1, T2; }
>      else
>      { import someOtherMod: T1, T2;}
>
>      import std.stdio;
>
> // this import block would support only import statemens, version and
> static if etc...
>
> }

I wrote the proposal and I have difficulty understanding what's meant here. Imagine us inflicting this upon our users. -- Andrei

December 15, 2016
On Wednesday, 14 December 2016 at 22:55:26 UTC, Andrei Alexandrescu wrote:
> Made a pass through the document integrating a lot of feedback and fleshing the proposal better:
>
> https://github.com/andralex/DIPs/blob/155ff59984b26749af7830aeb172d3af2dae8cd7/DIPs/DIP1005.md
>
> https://github.com/dlang/DIPs/pull/51/files
>
>
> Andrei

For the "with" keyword, why is the import statement kept? Seems unnecessary to keep it.

void process(File input) import std.stdio;
struct Buffered(Range) if (isInputRange!Range)
with (std.range)
{
    ...
}