February 24, 2020
On 2/24/20 5:11 PM, Walter Bright wrote:
> On 2/24/2020 1:45 PM, Steven Schveighoffer wrote:
>> Our proposal is even more restrictive, as the template and its API are actually defined by the language.
> 
> API is defined by the language, but not the behavior.

The language doesn't define my function's API, I do. I get to decide the types of my parameters, which ones are accepted, which ones aren't, what the names of my functions are, etc. Maybe you mean ABI?

> 
> 
>> No. It's overloading, not AST macros. How can an overload affect the AST other than to generate code specific to the type being accepted?
> 
> "generate code" is how.

This generates code (and AST):

int foo()
{
  return 1;
}

You can see it from the disassembly that a return statement is "generated". That's what I meant.

> 
> 
>> How is this an AST macro, but (string-literal, apples, bananas) not?
> 
> Because its behavior is defined by a template, not the language spec.

Not true. Both are defined by the language spec.

> 
>> That's it. The whole definition of the template and whatever is simply implementation details.
> 
> No, it isn't. It's leaving things up to templates like "formatString".

The result of formatString is defined by the spec. It doesn't matter how the template actually generates it. The fact that there's a template involved has no bearing on what the result should be (which will be 100% defined as I said).

> There are other instances of the compiler lowering things to templates, but the behavior is still defined by the language, not the template. The templates were not strictly necessary, they were just a convenience.

As is the case here.

> 
> The semantics of an interpolated string must be defined by the DIP, not deferred to some template. If the implementation of those defined language features is done by a template, that is an implementation choice, not part of the DIP or spec.

This is exactly how the proposal is defined. There is no wiggle room for the template (or whatever we decide) to do anything but follow the spec exactly. You will never get alternative behavior from that type.


> My inference of the discussion about this in the n.g. was the templates would be used so users could customize the behavior to be whatever they wanted.
> 

By accepting a different type from string. In other words, an overload.

This means you can have code that treats an interpolated string differently than a string. Overloads based on literal types are not a new feature.

You can have foo(double) and foo(float), and foo(1.0) will result in something different than foo(1.0f).

-Steve
February 24, 2020
On Monday, 24 February 2020 at 21:41:22 UTC, aliak wrote:
> Does that mean no betterC support if it's in druntime?

It would actually still work there because there is no actual code to link, just a compile-time definition to look up.

For example, the name `string` itself is a druntime definition, but it still works in betterC because it does not link anything at run time. This is very similar.

There is a known bug <https://issues.dlang.org/show_bug.cgi?id=19268> with betterC not allowing CTFE operations though, which imposes some unnecessary limitations, but we could and should fix that separately.

However, even with that bug, this proposal's i"" strings still partially work in betterC. And it will all work (except for the idup function, for obvious reasons) once that bug is fixed.
February 24, 2020
On 2/24/20 5:45 PM, Steven Schveighoffer wrote:
>> My inference of the discussion about this in the n.g. was the templates would be used so users could customize the behavior to be whatever they wanted.
>>
> 
> By accepting a different type from string. In other words, an overload.

I have a feeling from this comment that you are expecting that the compiler just literally lowers into the provided generated code, and leaves it up to the user to define the template. This is not the case.

The template will be defined in object.d, and the compiler will NOT COMPILE code that cannot find that template in the module object.d.

I would actually recommend that it lowers to:

.object._d_interpolated_string!(...), apples, bananas

To ensure that it cannot be intercepted.

-Steve


February 25, 2020
On Monday, 24 February 2020 at 22:11:08 UTC, Walter Bright wrote:
> The semantics of an interpolated string must be defined by the DIP, not deferred to some template. If the implementation of those defined language features is done by a template, that is an implementation choice, not part of the DIP or spec.
>

I don't understand this. The behavior of formatting strings is *currently* deferred to a template (std.format and co). This lets us do important decisions at compiletime, like writing the format string to a file or a string buffer piecewise without allocating memory. Why are you trying to get rid of this flexibility?

As I understand it, the point of a format string template is to keep exactly this kind of flexibility in exactly the same places it is currently available to users, while simultaneously improving syntax legibility. To emphasize this again: the @gc format string would have *reduced* flexibility for 90% of our usecases (templated nogc/lowgc log library calls). As proposed, I don't see why I would have ever used it.
February 24, 2020
On 2/24/2020 2:45 PM, Steven Schveighoffer wrote:
>> My inference of the discussion about this in the n.g. was the templates would be used so users could customize the behavior to be whatever they wanted.
> By accepting a different type from string. In other words, an overload.
> This means you can have code that treats an interpolated string differently than a string. Overloads based on literal types are not a new feature.

Were you proposing that an i"xxxx" be a different type? (DIP 1027 did not assign a type to it at all.) This would be radically different from DIP 1027, and a large increase in complexity (adding any new basic types is a big deal and a very intrusive change, and is tough to justify).

This is different enough from DIP 1027 that it would merit a separate DIP.

DIPs for the core language specify only behaviors, not implementations. Implementation possibilities can be included in an advisory manner only. Note that nowhere in the (massive and complicated) C++ core language specification is there any description of how the compiler should be implemented. Writing that an implementation must refer to specific templates implies that the behavior is customizable by the user via modifying those templates.
February 24, 2020
On 2/24/2020 8:24 PM, FeepingCreature wrote:
> The behavior of formatting strings is *currently* deferred to a template (std.format and co). This lets us do important decisions at compiletime, like writing the format string to a file or a string buffer piecewise without allocating memory. Why are you trying to get rid of this flexibility?

std.format is a library function, with its behaviors entirely defined by the library. It is not a core language feature.

There's nothing stopping writing a CTFE-able function for doing formatting. It doesn't need to be built in to the compiler.


> As I understand it, the point of a format string template is to keep exactly this kind of flexibility in exactly the same places it is currently available to users, while simultaneously improving syntax legibility. To emphasize this again: the @gc format string would have *reduced* flexibility for 90% of our usecases (templated nogc/lowgc log library calls). As proposed, I don't see why I would have ever used it.

Steven's proposal is radically different from #DIP1027. It should be separately proposed as a coherent DIP, not in bits and pieces over several n.g. postings.

All DIP1027 did was turn an istring into a tuple. That's it. The user can then do whatever they want with the tuple, including overloading a custom function based on the tuple arguments. DIP1027 did not actually do ANY formatting at all.
February 25, 2020
On Tuesday, 25 February 2020 at 07:07:50 UTC, Walter Bright wrote:
> All DIP1027 did was turn an istring into a tuple. That's it. The user can then do whatever they want with the tuple, including overloading a custom function based on the tuple arguments. DIP1027 did not actually do ANY formatting at all.

This may have already been answered in the other threads, but I was just wondering if anyone managed to propose a way to avoid this scenario with DIP1027?

void f(string s, int i = 0);
f(i"hello $a"); // silent unwanted bahviour.

?
February 25, 2020
On Tuesday, 25 February 2020 at 09:36:25 UTC, aliak wrote:
> This may have already been answered in the other threads, but I was just wondering if anyone managed to propose a way to avoid this scenario with DIP1027?

Yes, that is the key impetus of our amendment, which I also wrote up on a gist weeks ago.... and it is now on github too! https://github.com/dlang/DIPs/pull/186

By putting a new type around the generated format string, the f(i"") is a type mismatch error, so the user can decide what they want to do (I propose having the compiler suggest you call `.idup` on it to copy it into an ordinary GC string for new users to quickly get going with it.)

That's all our amendment fundamentally does.

Walter's: i"test $foo" -> "test %s", foo
Our's:    i"test $foo" -> wrapper!("test ", thing(null)), foo

The `thing` there represents the interpolated item and user-defined format string. Since there isn't one, it is passed null.

The `wrapper` there is a new type.


Both `thing` and `wrapper` are defined by the language and their actual implementations live in druntime

struct thing { string specifier; }
struct wrapper(format_string_pieces...) {}


From the language perspective, the rest is the same was Walter's proposal. Just with that wrapper type:

foo(string, int) // type error, cannot convert wrapper to string

to protect from that.
February 25, 2020
On Tuesday, 25 February 2020 at 13:04:41 UTC, Adam D. Ruppe wrote:
> On Tuesday, 25 February 2020 at 09:36:25 UTC, aliak wrote:
>> [...]
>
> Yes, that is the key impetus of our amendment, which I also wrote up on a gist weeks ago.... and it is now on github too! https://github.com/dlang/DIPs/pull/186
>
> [...]

I should’ve been more specific 😬 I was wondering if the same could be achieved without a introducing a new aggregate type!
February 25, 2020
On Tuesday, 25 February 2020 at 13:39:40 UTC, Aliak wrote:
> On Tuesday, 25 February 2020 at 13:04:41 UTC, Adam D. Ruppe wrote:
>> On Tuesday, 25 February 2020 at 09:36:25 UTC, aliak wrote:
>>> [...]
>>
>> Yes, that is the key impetus of our amendment, which I also wrote up on a gist weeks ago.... and it is now on github too! https://github.com/dlang/DIPs/pull/186
>>
>> [...]
>
> I should’ve been more specific 😬 I was wondering if the same could be achieved without a introducing a new aggregate type!

In my opinion the only really viable solutions are either to lower to a function call to format (or similar) such that typeof(i"") == string or a new type such as Adam describes so that functions can add overloads for it (and specialized compiler errors for common misuse cases).

Anything else and you risk users running into inexplicable errors because their string isn't a string.