December 07, 2018
On Friday, 7 December 2018 at 00:43:43 UTC, Mike Franklin wrote:
> Can that be extended somehow to pass around expressions too (i.e. expressions as rvalues)?

We kinda-sorta can, with `lazy void`. If we could get the code out of it as a string, that might be interesting. But I don't think it would hit the interp thing (whose library implementation is really just the mixin expression on the outside)

>     // It's already yelling at us with a ! operator.

Keep in mind that mixin templates currently do not actually need arguments listed.
December 07, 2018
On Thursday, 6 December 2018 at 23:02:43 UTC, Adam D. Ruppe wrote:
> On Thursday, 6 December 2018 at 22:54:54 UTC, o wrote:
>> import std.typecons: tuple;
>
> That's a library tuple, which is just syntax salt over a struct.
>
> When we say tuple here, we are actually referring to a compiler tuple, which is more like AliasSeq from std.meta - a magic type that represents an argument list.

Thanks for the clarification. Now this makes a lot more sense.
+1 for lowering to tuples/sequences. Disregard my previous messages about lowering to strings :-).
December 06, 2018
On Fri, Dec 07, 2018 at 12:43:43AM +0000, Mike Franklin via Digitalmars-d wrote: [...]
> As for myself, I don't see much value in forcing users to add `mixin`
> at the site of a mixin template instantiation, but there's a lot I
> don't see, so I may just be missing something.
> ```
> import std.stdio;
> 
> mixin template Foo(T)
> {
>     T x = 5;
> }
> 
> extern(C) void main()
> {
>     // Why do we need `mixin` here?
>     // Why can't we just write `Foo!int;`?
>     // It's already yelling at us with a ! operator.
>     mixin Foo!int;
>     writeln(x);
> }
> ```

Yes it's already yelling at us with a ! operator, but the difference is that Foo!Bar is generally read as a templated type of some sort in typical D code.  It's surprising behaviour to see Foo!Bar that not only has side-effects, but may access symbols in the current scope that aren't explicitly passed to it.  The 'mixin' is the cue that whatever's inside Foo may reach out and touch stuff in the surrounding code with its grubby hands, as opposed to, say, instantiating a template type, or calling a template function, both of which can only exert an effect within their own scope and/or arguments explicitly handed to them.

While I understand the cumbersomeness of having to type `mixin` everywhere string interpolation is used, part of me kinda wants to keep the `mixin` in the syntax, if for nothing else than to warn anyone reading the code that we're potentially touching stuff outside of what template functions can usually touch.

Which leads to the absolute minimal language change that would let us implement nice interpolated strings: mixin expressions. Writing:

	string name = ...;
	writeln(mixin interp!"My name is ${name}.");

is miles ahead of:

	string name = ...;
	mixin interp!"My name is ${name}.";
	writeln(interpResult);	// bad: `interpResult` is an implicit
				// symbol leaked out of interp's
				// implementation

Esp. if multiple interpolated arguments are being used:

	string name = ...;
	int age = ...;
	mixin interp!"My name is ${name}.";
	string s1 = interpResult;	// ouch
	mixin interp!"My age is ${age}.";
	string s2 = interpResult;	// double ouch
	writefln("%s %s", s1, s2);

Far too much boilerplate compared to:

	string name = ...;
	int age = ...;
	writefln("%s %s",
		 mixin interp!"My name is ${name}.",
		 mixin interp!"My age is ${age}.");

(I know, I know, bad example, since the whole point is not to use format strings.  But it was the quickest example that came to mind.)

And yes, `mixin interp!"..."` is horribly verbose. But ostensibly we could abbreviate it to something like `mixin i!"..."`.


On that note, though, a thought occurred to me: what if we implement interpolated strings using something (admittedly a major hack) like:

	mixin(interpolate!q{
		writeln("My name is ${name} and age is ${age}");
		writeln("How are you, ${guestName}?");
	});

where `interpolate` parses the passed-in code, expands any interpolated variables, and returns a code string that's mixed into the current context?  It will allow completely convenient syntax, since you can put multiple statements in the token string, even arbitrarily complex bits of code if you want. All you have to do is to wrap the whole thing inside the token string.

(I can already see y'all cringe at this. :-P  But for completeness' sake in the prospective DIP, we should address why such an approach is not desirable, since it's clearly *possible*, and does, ostensibly, solve the problem at hand.)


T

-- 
Let's eat some disquits while we format the biskettes.
December 07, 2018
On Friday, 7 December 2018 at 01:19:35 UTC, Adam D. Ruppe wrote:
> On Friday, 7 December 2018 at 00:43:43 UTC, Mike Franklin wrote:
>> Can that be extended somehow to pass around expressions too (i.e. expressions as rvalues)?
>
> We kinda-sorta can, with `lazy void`.

I'm not sure what you mean.  Please elaborate.

Steven gave this example[1] here:

> This doesn't work:
> 
> foo!(a + b);
> 
> But this does:
> 
> foo!(() => a + b);

What I'm thinking is if `foo` is declared as `foo(alias a)`, then `a` could either accept either a symbol (currently possible) or an expression (not currently possible; this is what I meant by "expressions as rvalues").  Depending on how the body of `foo` utilized `a` it could more or less do the equivalent of `foo!(() => a + b)`.

Mike

[1] - https://forum.dlang.org/post/puc2f3$27tr$1@digitalmars.com


December 07, 2018
On Thursday, 6 December 2018 at 00:10:56 UTC, o wrote:
> I really wish that D had string interpolation, and I can see that a ton of other people also do. String interpolation has been brought up before, but it has been ignored/put down every time. Jonathan Marler even created a Pull Request (https://github.com/dlang/dmd/pull/7988) to add this feature, but he ended up closing it because it was getting nowhere. The excuse that keeps being given for not adding this feature is something along the lines of "There are ways to work around this, so it is unnecessary to add it". If this is the case, then why do people keep on requesting it again and again? Here are just some cases of other people asking for string interpolation:
>
> [...]

https://github.com/dlang/dmd/pull/7988#issuecomment-434100869 was saddening to see.

On one hand people talk about D community not having enough man power + wanting to have a corporate back-up, etc. On the other hand... :(
December 07, 2018
On Friday, 7 December 2018 at 02:38:30 UTC, Mike Franklin wrote:
>> We kinda-sorta can, with `lazy void`.
>
> I'm not sure what you mean.  Please elaborate.

It is the runtime version of what Steven gave.

void foo(lazy int something) {
   import std.stdio;
   writeln(something);
}

void main() {
  int a = 1, b = 2;
  foo(a + b);
}


And you can `lazy void` too, which takes anything which has an effect (it is an error if it has no effect), but discards its return value. example here: https://dlang.org/spec/function.html#lazy-params


The compiler simply wraps the expression you pass to the argument in a delegate, and automatically calls any reference to it (so the ref of something above actually does something())

December 07, 2018
On Friday, 7 December 2018 at 02:47:01 UTC, Arun Chandrasekaran wrote:
> On one hand people talk about D community not having enough man power + wanting to have a corporate back-up, etc. On the other hand... :(

Yeah, D has plenty of workers. I rarely even bother trying to work with D's management though. My motivation was killed years ago.

I recently tried again though after the new PR manager actually pinged me! I fixed the PR.... and now it is sitting in silence again. Wolf, wolf, wolf, the boy cried.
December 06, 2018
On 12/6/18 7:43 PM, Mike Franklin wrote:
> On Thursday, 6 December 2018 at 22:04:13 UTC, Steven Schveighoffer wrote:
> 
>> It's really not what's enabled (clearly, things can still be used without string interpolation, and we can use mixins to simulate close to what we would want).
>>
>> It's how one writes and reads code. The efficiency and elegance is not to be ignored.
> 
> [..]
> 
> Of course, you are right, and that's what I was trying to say. "What language feature do we need, or limitation removed, that gets us what we want:  the ability to implement interpolated strings and potentially other features in the library without too much compromise on the efficiency, elegance, and expressiveness you would get if you implemented it in the language, and without turning D into a DSL".  That probably doesn't do it justice either, but I hope you get the idea and we're on more-or-less the same page.

I get the idea, but the answer is, nothing. We can implement it today (take a look at scriptlike).

As long as there is an insistence that 'if it's doable in the library, the elegance is not worth the effort,' any proposal will fail. We need to first convince those in charge think the feature should be added because of the *human* impact. That was the point of my longer answer.

> Jacob mentioned AST macros (I knew that was coming, and even had a note in my first draft say "Sorry, Jacob, except for AST macros", but I deleted it :D ).  But Jacob is on to something. We already pass around symbols with `alias`.  Can that be extended somehow to pass around expressions too (i.e. expressions as rvalues)?  That would probably help address the issue of printing assert expressions as well (https://github.com/dlang/dmd/pull/8517)

I think we can't exactly pass around expressions in the general case, because it's too fraught with ambiguity.

For example, if foo accepts an alias, then what is foo!(a + b)? Today, if a and b are compile-time known, then it's the sum of a and b. If a or b cannot be determined at compile time it's an error.

If foo!(a + b) all of a sudden compiled for runtime variables, but did something wildly different, we would probably have issues.

I think we would need a new type of alias. My hope was that we could let this remain without syntax, and just say it's only accessible if you use string interpolation. This makes the change simpler to implement, and narrowly focused.

However, if I had to give it a name (and syntax), I'd say it's a lazy alias.

> 
> As for myself, I don't see much value in forcing users to add `mixin` at the site of a mixin template instantiation, but there's a lot I don't see, so I may just be missing something.
> ```
> import std.stdio;
> 
> mixin template Foo(T)
> {
>      T x = 5;
> }
> 
> extern(C) void main()
> {
>      // Why do we need `mixin` here?
>      // Why can't we just write `Foo!int;`?
>      // It's already yelling at us with a ! operator.
>      mixin Foo!int;
>      writeln(x);
> }
> ```

I think the reason is that you are giving the template free access to ALL your scope. My expectation of the string interpolation mechanism is that it only gives access to the variables or expressions passed to it. I think it's probably a good thing to require mixin for a flag to look for, even if it's ugly.

vibe.d does string interpolation in it's diet templates, but the rub is that you have to pass in an alias to the variables you want to be visible in the interpolation. So it requires a very un-DRY solution, and also doesn't work with arbitrary expressions.

> Simen Kjærås mentioned a few things when we were discussing ways to implement properties in the library at https://forum.dlang.org/post/jqcqsriizuewdqotbnop@forum.dlang.org  There might be some feature to be added, or limitation removed, that will permit help both the string interpolation case and the properties case.
> 
> I know I'm just thinking out loud and not contributing much, but I can't help but feel that there's something common in all these ideas that just hasn't been identified yet.  And no, Jacob, not AST macros (Actually, that would probably do it, but I think we've already been there) :D

As I said, there's already possible libraries that allow what we want. It's the usage syntax that is the pain-point I would say.

-Steve
December 06, 2018
On Thu, Dec 06, 2018 at 10:29:11PM -0500, Steven Schveighoffer via Digitalmars-d wrote: [...]
> vibe.d does string interpolation in it's diet templates, but the rub is that you have to pass in an alias to the variables you want to be visible in the interpolation. So it requires a very un-DRY solution, and also doesn't work with arbitrary expressions.

I've discovered that since alias parameters accept module symbols, I can pass my module to a Diet template, and then the template has free access to everything in the module. :-D  E.g.,

	// mymodule.d
	int x;
	int y;
	...
	render!("mytemplate.dt", mymodule);

	// mytemplate.dt
	html
	    body
	        p x=#{mymodule.x} y=#{mymodule.y}

If your render!"" call is inside a class, you can also pass in `this`, then you can access all class members.


[...]
> As I said, there's already possible libraries that allow what we want. It's the usage syntax that is the pain-point I would say.
[...]

True. But we'll have to think of a convincing argument of why building the syntax into the language is a good thing -- good enough to pass W&A's scrutiny.  That's the difficult part.

There's also the matter of exactly what syntax we're going to use for interpolated strings. Since it's going to be baked into the language, any changes / tweaks will be a lot harder to make. So we have to get it (almost) perfect on first try (or at least, a perfect subset that can be extended later without breaking anything that depends on it), which is not easy to achieve. There will probably be bikeshedding over the finer details of syntax.


T

-- 
Тише едешь, дальше будешь.
December 06, 2018
On Fri, Dec 07, 2018 at 03:02:02AM +0000, Adam D. Ruppe via Digitalmars-d wrote:
> On Friday, 7 December 2018 at 02:47:01 UTC, Arun Chandrasekaran wrote:
> > On one hand people talk about D community not having enough man power + wanting to have a corporate back-up, etc. On the other hand... :(
> 
> Yeah, D has plenty of workers. I rarely even bother trying to work with D's management though. My motivation was killed years ago.
> 
> I recently tried again though after the new PR manager actually pinged me! I fixed the PR.... and now it is sitting in silence again. Wolf, wolf, wolf, the boy cried.

The thing is, the manpower we lack is more in the area of reviewing and merging PRs, not so much in coding up those PRs in the first place.  The scope of D is huge, and covers many different areas of expertise; reviewing PRs quite often requires expertise in a certain area in order to do it justice, but there are only a scant few who can do the job, usually just one person, who is also responsible for many other areas, besides non-D-related responsibilities such as a full-time job. Speaking as a Phobos committer, I simply don't have the expertise to have the confidence to review many PRs that involve areas I'm not familiar with, and my time is already too limited even in areas I *am* confident to review.  As a result, I refrain from reviewing for fear of making the wrong decision(s) -- or even if I do review the parts of the PR I'm confident enough to review, I would refrain from merging unless somebody else more competent reviews it.

Also, there's a lack of clear communication of expectations from W&A. Some years ago, when I and a few others were actively merging PRs, at one point Andrei stepped in and expressed unhappiness at the kind of changes that were being merged. He had good reasons for it, and in retrospect he did the right thing.  But OTOH he also did not give clear enough directions as what exactly *is* desired / undesired, so, lacking enough information to proceed, passivity set in, from the fear of getting vetoed again.  Their general reticence on many smaller issues, while understandable given how much is how their plate, nonetheless forms a very bad combination with wanting everything to be perfect -- it's not always clear what their idea of "perfect" is, and when nobody knows and W&A don't speak up, things just grind to a standstill.

The slow rate of adding new committers also does not help, given our already lacking manpower and the general busy-ness of existing committers. There are many more eager contributors submitting PRs than there are committers who are trusted enough to review and merge them, so we're bottlenecking in a bad way.

There's also too much of the perfect becoming the enemy of the good, which seems to be a common malady in D circles, and that doesn't help things either.

I think at some point, W&A are just going to have to loosen their rein on things, and appoint and trust more (many more) delegates to make decisions.  Keeping everything bottlenecking on just the two of them is not a viable long-term strategy.  While they have acknowledged in the past that they lack experience in management and are trying their best with what they have, this situation has been going on for years, and the improvements have been slow.  It's showing signs that this mode of management isn't working very well for an open source project, and it may be time to seriously reconsider how things are run, lest the technical excellence of D gets dragged under by ineffective management.


T

-- 
"A one-question geek test. If you get the joke, you're a geek: Seen on a California license plate on a VW Beetle: 'FEATURE'..." -- Joshua D. Wachs - Natural Intelligence, Inc.