Jump to page: 1 2 3
Thread overview
Inline imports redivivus
Mar 07, 2022
Per Nordlöw
Mar 07, 2022
Ali Çehreli
Mar 08, 2022
Paul Backus
Mar 08, 2022
Ali Çehreli
Mar 09, 2022
H. S. Teoh
Mar 09, 2022
Ali Çehreli
Mar 11, 2022
Zach Tollen
Mar 11, 2022
Ali Çehreli
Mar 12, 2022
Zach Tollen
Mar 12, 2022
Zach Tollen
Mar 12, 2022
Daniel N
Mar 12, 2022
Zach Tollen
Mar 13, 2022
Dom DiSc
Mar 13, 2022
Dom DiSc
Mar 13, 2022
zjh
Mar 13, 2022
Adam D Ruppe
Mar 13, 2022
Tejas
Mar 15, 2022
bauss
Mar 15, 2022
Andrea Fontana
Mar 15, 2022
bauss
Mar 16, 2022
Zach Tollen
March 07, 2022

https://forum.dlang.org/post/sdehom$10fi$1@digitalmars.com

On Friday, 23 July 2021 at 13:55:34 UTC, Andrei Alexandrescu wrote:

>

If it works well in practice, a future language proposal could take
_import!"std.datetime".SysTime to the simpler and better
import(std.datetime).SysTime.

Yes, please!

March 07, 2022
On 3/7/22 02:27, Per Nordlöw wrote:
> https://forum.dlang.org/post/sdehom$10fi$1@digitalmars.com
>
> On Friday, 23 July 2021 at 13:55:34 UTC, Andrei Alexandrescu wrote:
>
>> If it works well in practice, a future language proposal could take
>> `_import!"std.datetime".SysTime` to the simpler and better
>> `import(std.datetime).SysTime`.
>
> Yes, please!

This seems to be yet another example of the need for template string arguments typed as symbols in the source code.

- Flag!"foo" could become Flag(foo) (or more consistently Flag!foo).

- bitfields could become bitfields!(int, x, 8) instead of bitfields!(int, "x", 8)[*]

Andrei mentioned a couple of times that this is what was discussed as "new alias" in the past where the template allows the use of an "unknown" (or "new") symbol at call site. I see a strong similarity here to the existing opDispatch() that makes compile-time strings from "unknown" symbols at call site.

Ali

[*] I think it would be interesting to come up with a language solution that would e.g. enable combining each three consecutive arguments of bitfields. It is a code smell that everybody knows that the three separate arguments go together but we don't use a language construct for that. We already have the following method in the current language but it is obviously redundant and perhaps that's why the current design of bitfields does not use it:

  bitfields!(Bit(int, x, 8),       // Better but redundant
             Bit(int, y, 8));

A solution that would allow the following would be interesting:

  bitfields!(int x : 8,
             int y : 8);

So, we somehow specify at template definition that two (or three?) parameters (e.g. int and x) can be specified without a comma and perhaps anything after ':' are UDAs of that parameter?

March 08, 2022
On Monday, 7 March 2022 at 18:45:54 UTC, Ali Çehreli wrote:
> A solution that would allow the following would be interesting:
>
>   bitfields!(int x : 8,
>              int y : 8);
>
> So, we somehow specify at template definition that two (or three?) parameters (e.g. int and x) can be specified without a comma and perhaps anything after ':' are UDAs of that parameter?

There's always strings:

    bitfields!("int x : 8",
               "int y : 8");
March 08, 2022
On 3/8/22 14:28, Paul Backus wrote:

> There's always strings:

And they are the eyesore! :)

>      bitfields!("int x : 8",
>                 "int y : 8");

But you give me the idea that if we allow "this template parameter is a string" and don't require strings at the use site, then it would work for the above case as well. Basically, the string is contains my domain specific language as you show and I can do anything I want with it.

Brain storming with a 'new string' syntax:

template bitfields(new string args...) {
  // ...
}

  bitfields!(int x : 8,
             int y : 8);

And the template instance sees two strings: "int x : 8" and "int y : 8" and has fun parsing them at compile time. Again, this feels natural to me because it is related to opDispatch.

Of course there are syntax issues: Nothing that takes part in a parameter list can be a part of the string. I think they are just ',' to allow multiple 'new string' parameters and ')' to allow closing the parameter list. When needed, they could be written with backslashes as \, and \).

Wow! I've just written a DIP! :P

Ali

March 08, 2022
On Tue, Mar 08, 2022 at 03:25:49PM -0800, Ali Çehreli via Digitalmars-d wrote:
> On 3/8/22 14:28, Paul Backus wrote:
> 
> > There's always strings:
> 
> And they are the eyesore! :)
> 
> >      bitfields!("int x : 8",
> >                 "int y : 8");
> 
> But you give me the idea that if we allow "this template parameter is a string" and don't require strings at the use site, then it would work for the above case as well. Basically, the string is contains my domain specific language as you show and I can do anything I want with it.
[...]

Token strings are your friend:

	bitfields!q{ int x:8; int y:8; };

Or, if you like struct-like syntax:

	bitfields!q{
		int x:8;
		int y:8;
	};


T

-- 
Questions are the beginning of intelligence, but the fear of God is the beginning of wisdom.
March 08, 2022
On 3/8/22 17:15, H. S. Teoh wrote:

> Token strings are your friend:

I know but they are still strings.

  Flag!"foo" a;  // Meh
  Flag!`foo` b;  // Meh
  Flag!q{foo} c; // No comment... D'oh! :)
  Flag!foo d;    // Unavailable

This is a minor thing only Ali dislikes... :/

Ali

March 11, 2022

On Monday, 7 March 2022 at 10:27:08 UTC, Per Nordlöw wrote:

>

https://forum.dlang.org/post/sdehom$10fi$1@digitalmars.com

On Friday, 23 July 2021 at 13:55:34 UTC, Andrei Alexandrescu wrote:

>

If it works well in practice, a future language proposal could take
_import!"std.datetime".SysTime to the simpler and better
import(std.datetime).SysTime.

Yes, please!

The reason I wanted to revive this redivivus — so to say — is because I believe the following syntax is near-optimal for the task at hand:

import.std.datetime:SysTime

From my perspective there is no need to rely on advanced template features since inline imports are so basic that they should be adopted as a language feature instead.

The above syntax is excellent because:

  • It is grammatically unambiguous
  • It requires no parentheses or other enclosing marks
  • It resembles selective imports

That is exactly what it is: a use-once, selective import. You use it as a drop-in replacement for the identifier you want to import.

In reviewing the historical proposals even as far back as DIP1005 [1], it seems that the syntax above simply wasn't stumbled upon. Therefore I wanted it to be evaluated. "Destroy!"

To give a little more food for thought, in addition to the above syntax, I wanted to introduce a stunning syntax sugar, which uses $ instead of import . as a special token to activate the sequence:

$std.datetime:SysTime

This is the tersest fully qualified inline import possible. I suppose it is strange on the eyes. But don't implement it unless you want people to use it, because people can hardly resist a concise syntax like this!

Anyway, those are my proposals. Here are some previous proposals and why I have problems with them:

imported!"std.datetime".SysTime // - already implemented in object.d [2]
                                // - best you can do with existing language
                                // - can't use keyword `import`
                                // - requires `""` and `!`

import(std.datetime).SysTime    // parens unnecessary
(import std.datetime).SysTime   // ditto
std.datetime::SysTime           // grammatically ambiguous (module name unclear)

::std.datetime:SysTime          // if we put the `::` first it becomes viable
                                // it's a different version of the `$`

[1] https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1005.md#syntactic-alternatives

[2] https://github.com/dlang/druntime/pull/1756/files

March 11, 2022
On 3/10/22 22:48, Zach Tollen wrote:

> ::std.datetime:SysTime          // if we put the `::` first it becomes
> viable
>                                  // it's a different version of the `$`
>

Perhaps a second meaning for ..? And is : really necessary? So, would the following work?

  ..std.datetime.Systime

Now it seems to have a different meaning from "importing" though. In this case it feels like we are "using" Systime from that module. And the rationale for .. can be:

- Single dot already means "this module".
- Two dots may mean "outside of this module".

Going off topic and without knowing whether this topic has already been brought up, should inline imports automatically be made available to the callers of functions? Arbitrarily using the $ syntax:

module my.module;

void foo($bar:SomeSymbol a) {
}

Since 'foo' is public to the users of my.module, should we expect the users be able to call 'foo' without importing SomeSymbol separately themselves? And the next question may be what if SomeSymbol is accessible to my.module but not to my users (e.g. if it's 'package'). So, if it should automatically be imported for the users, should SomeSymbol automatically be raised to 'public' status for the users of 'foo'?

Ali

March 12, 2022

Thanks for your reply!

On Friday, 11 March 2022 at 13:01:43 UTC, Ali Çehreli wrote:

>

On 3/10/22 22:48, Zach Tollen wrote:

>

::std.datetime:SysTime // if we put the :: first
it becomes
viable
// it's a different version
of the $

Perhaps a second meaning for ..? And is : really necessary? So, would the following work?

..std.datetime.Systime

If you used .. here you would always have to add whitespace in an ordinary call chain, to avoid ambiguous lexing, so it's not good:

{
   x = normal.call.chain;
   x = dotdot.call. ..modname:chain; // space necessary to avoid lexing as `...`
}

As far as not wanting to use : the issue is also ambiguity. In DIP1005, written a few years ago by Andrei Alexandrescu, this exact question was addressed [1]. Quote:

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

"Such an option has an ambiguity problem shown by Timon Gehr: is import.std.range.isInputRange looking up symbol isInputRange in module/package std.range, or the symbol range.isInputRange (e.g. a struct member) in module/package std?"

>
  • Single dot already means "this module".
  • Two dots may mean "outside of this module".

If we can find a starting token (other than $) which allows the construct to seem familiar and which has no other problems, I'm all for it. :: has been suggested. I believe also : would work:

auto x = :std.datetime:Systime;

Technically, : would not cause grammatical ambiguity. But I don't think it's visually distinct enough, and the error messages you get if you don't type it correctly would be confused with the compiler's other error messages for : syntaxes.

At minimum, $ as in $fully.qualified:symbol announces its presence boldly, as if to challenge the language designer to come up with a better use of the $ token. :-)

>

Going off topic and without knowing whether this topic has already been brought up, should inline imports automatically be made available to the callers of functions? Arbitrarily using the $ syntax:

module my.module;

void foo($bar:SomeSymbol a) {
}

Since 'foo' is public to the users of my.module, should we expect the users be able to call 'foo' without importing SomeSymbol separately themselves?

I would say no. As a one-use import, it doesn't spread its import anywhere but to itself. But the caller can just call using foo($bar:SomeSymbol(value)) if they don't feel like importing the module either.

>

And the next question may be what if SomeSymbol is accessible to my.module but not to my users (e.g. if it's 'package'). So, if it should automatically be imported for the users, should SomeSymbol automatically be raised to 'public' status for the users of 'foo'?

Again, no. If a function parameter requires a privately defined structure, then that function is not meant to be called by things which don't have access to that structure.

Inline imports are semantically no different from symbols which had their modules imported separately. I'm pretty sure issues of privacy won't be affected by this.

  • Zach

[1] https://github.com/dlang/DIPs/blob/master/DIPs/other/DIP1005.md#syntactic-alternatives

March 12, 2022

On Friday, 11 March 2022 at 13:01:43 UTC, Ali Çehreli wrote:

>

Perhaps a second meaning for ..? And is : really necessary?

The character | might work too. It looks better if we close it with the same character.

   x = |std.datetime|SysTime;

I actually like this one a lot. There is some potential lexical ambiguity with | and || as binary operators. However, those operators are typically separated with whitespace in ordinary code, so I don't think it will ever be a problem. (The second | in |std.datetime|SysTime can be parsed as a part of |modname|symbol, so apart from typos, there's no syntactical problem.)

The worst you would suffer would be the visual confusion of something like this:

if (|std.something|condition(sdfd) || |some.other.inlinemodule|Test
      || |othermod.imp|mycondition) {
   myFlags = |std.something|Flagset | |std.otherthing|Flags;
}

This would be the extreme case I think. Syntax highlighting could help.

I think this is better than $std.datetime:SysTime.

« First   ‹ Prev
1 2 3