December 17, 2019
On Tuesday, 17 December 2019 at 17:13:50 UTC, Patrick Schluter wrote:
> Which was my point. An interpolated string cannot be stored in a simple string as some people requested in the thread before (not you). It is only feasible if the istring is evaluated at runtime with an interpreter who knows the current values of the variables used. Interpreted languages like python, perl, javascript etc. might get away with it but compiled languages have to transform it in its code representation.

These languages also don't store "interpolated strings" in
variables; they store strings in variables, and any string
interpolation happens at the literal.

Crystal (compiled language with a real type system, etc.):

  apple = 0
  my_is = "apple=#{apple}"
  apple = 36
  puts my_is

Ruby (interpreted scripting language):

  apple = 0
  my_is = "apple=#{apple}"
  apple = 36
  puts my_is

Both output "apple=0". I can't recall a case where you'd get
"apple=36". You'd have to deliberately delay evaluation of the
literal.

But I don't think anyone's asked for any other behavior than
this. What's wanted is for

  int apple;
  string my_is = i"apple=$apple";
  apple = 36;
  writeln(my_is);

to output "apple=36" rather than result in a compile-time
error because i"..." doesn't evaluate to a string.

December 17, 2019
On Tuesday, 17 December 2019 at 17:31:05 UTC, Steven Schveighoffer wrote:
> On 12/17/19 12:19 PM, ag0aep6g wrote:
>> On 17.12.19 18:12, Steven Schveighoffer wrote:
>
>>> Is there a way that this could work? I mean, aside from storing lambdas for everything?
>> 
>> alias as = AliasSeq!("%s apples and %s bananas", apples, bananas);
>
> :facepalm:
>
> Thanks!
>
> That is pretty cool. Coupled with a logging function:
>
>
>     import std.experimental.logger;
>     int apples = 5;
>     int bananas = 6;
>     //equivalent to: alias msg = i"$apples apples and $bananas bananas";
>     alias msg = AliasSeq!("%s apples and %s bananas", apples, bananas);
>     logf(msg);
>     ++apples;
>     ++bananas;
>     logf(msg);
>
> This works pretty well, shows the filename/line numbers, and reevaluates the log message each time.
>
> Another cool use case.
>
> -Steve

This got me excited, but unfortunately it doesn't work with expressions (for obvious reasons):

// Error: variable apples cannot be read at compile time
alias msg = AliasSeq!("%s apples and %s bananas makes %s fruit", apples, bananas, apples + bananas);

December 17, 2019
On 12/17/19 1:17 PM, Meta wrote:
> On Tuesday, 17 December 2019 at 17:31:05 UTC, Steven Schveighoffer wrote:
>> This works pretty well, shows the filename/line numbers, and reevaluates the log message each time.
>>
>> Another cool use case.
>>
> This got me excited, but unfortunately it doesn't work with expressions (for obvious reasons):
> 
> // Error: variable apples cannot be read at compile time
> alias msg = AliasSeq!("%s apples and %s bananas makes %s fruit", apples, bananas, apples + bananas);
> 

Right, the alias has to be a symbol or a constant. Though you could technically put in a lambda. I don't know if the log/writef would support that.

This doesn't mean it's not useful if it can only be a symbol, I predict even without string interpolation, my printf debugging that I generally use is going to be enhanced with this idea.

-Steve
December 17, 2019
On Monday, 16 December 2019 at 21:42:32 UTC, Walter Bright wrote:
> On 12/16/2019 6:00 AM, Nick Treleaven wrote:
>> Interpolated strings could implicitly convert to strings, which is the most common use case in typical D code. That would not bloat code that doesn't need it, as Adam has shown by using an import inside a template.
>> 
>> Interpolated strings should not be designed with low-level concerns as the priority motivator at the cost of high level usability and safety.
>> 
>> D is supposed to be a type safe language, even std.format.format is not fully type safe because using string for a format string allows runtime errors.
>> 
>> Any good D interpolation proposal would support compile time checked format strings, even when runtime arguments are passed. D is supposed to be the best language for compile time stuff!
>
> Having it go directly to a string has multiple problems:

I said implicitly convert. If it lowers to a templated struct, it can still be used without converting to string - see below.

> 1. Those who want the tuple in order to do something else with it will be unhappy and out of luck.

struct FormatSeq(S...)
{
    /// the sequence for e.g. printf
    S expand;

    alias get this;

    @property string get()() // template, doesn't link Phobos unless needed
    {
        import std.format;
        return format(expand);
    }
}

unittest
{
    int i = 5;
    string s = "hi";
    //auto fs = i"$i, $s";
    auto fs = FormatSeq!(string, int, string)("%s, %s", i, s); //lowering
    import std.stdio;
    writefln(fs.expand); // works as format string
    string s2 = fs; // works as string implicitly too
    s2.writeln;
}

> 2. It will not work with betterC.
> 3. It will allocate GC memory.
> 4. It will be substantially slower because of the extra intermediate buffer.

None of these points are true, just use `.expand` and avoid the alias this.

> 5. I don't think it'll work with Steven Schweighoffer's SQL examples.

The above get method would do the wrong thing, yes. Perhaps if the format string is a struct template value parameter, the code can detect that custom specifiers have been used and statically disable the get method.

> 6. It will require the core language to depend on a rather large and complex Phobos routine.

Only if the alias this is actually used - it's a template. The precedent for lowering to Phobos is the ^^ operator which IIRC lowers to std.math.pow.

> 7. It will not be any more typesafe than it would be generating a tuple.

The common case for creating a string is seamless and can't be done wrong when using alias this, which is also the easiest way to use it. printf could be wrapped with a method, and the format string could be checked at compile-time when it's a literal.

> 8. The number of times I've wanted a formatted string as the end result, as opposed to wanting formatted insertion into something else, is about 1 in 100, if that.

So just put .expand after the interpolated string. For *every* programming language I'm aware of, interpolated strings implicitly convert to a string.

If it really is as commonly needed as you think, you can add wrapper methods to the struct so you even avoid importing core.stdc or std.stdio.
December 17, 2019
On Tuesday, 17 December 2019 at 18:17:30 UTC, Meta wrote:
> This got me excited, but unfortunately it doesn't work with expressions (for obvious reasons):
>
> // Error: variable apples cannot be read at compile time
> alias msg = AliasSeq!("%s apples and %s bananas makes %s fruit", apples, bananas, apples + bananas);

tuple of lazy args should work probably (i.e. pass through vararg function that has all args marked as lazy.

Best regards,
Alexandru.
December 17, 2019
On Tuesday, 17 December 2019 at 17:31:20 UTC, mipri wrote:
> What's wanted is for
>
>   int apple;
>   string my_is = i"apple=$apple";
>   apple = 36;
>   writeln(my_is);
>
> to output "apple=36"

Of course this should read "apple=0".

This is a mistake I wouldn't've made with a logical
programming language :(
December 17, 2019
On Monday, 16 December 2019 at 11:18:33 UTC, Patrick Schluter wrote:
> On Monday, 16 December 2019 at 11:08:00 UTC, Patrick Schluter wrote:
>> On Monday, 16 December 2019 at 10:48:51 UTC, aliak wrote:
>>
>>> Resolving interpolation at compile time is imho incompatible
>> with handling them as regular strings.
>
> Maybe I'm wrong here, I haven't thought it through, but in first approach I think that's an essential point. As the string contains code, if evaluated at CT, the string must be split somehow in literal parts and code parts. Allowing the i-string to be handled as regular string implies that the splitting happens sometime between when it is declared and after it is used, which can happen after runtime.
>
> import fn;
>
> int b = 20;
>
> string inter = i"$(a+b)";
>
> foreach(a; 1..10)
>   fn(inter);
>
> ---
> module fn;
>
> void fn(string s)
> {
>   writefln(s);
> }
>
> How would that work?
>
> In python or javascript there's no issue, a is a runtime symbol.
>
>>
>> The question is then do we want CT or RT interpolated strings. RT interpolated strings can still be provided by a library.

Well there is a issue in javascript, interpolated string are evaluated once met in code by interpreter and are not somehow delayed at later stage as in your example.

Here is a test case:
```
var c = 40
var s = `${a + b} ${c}`

var a = 10
var b = 20
console.log(s)
```

The result is:
Nan 40

Best regards,
Alexandru
December 17, 2019
On Tuesday, 17 December 2019 at 10:14:35 UTC, Patrick Schluter wrote:
> On Tuesday, 17 December 2019 at 09:20:06 UTC, Jacob Carlborg wrote:
>>[...]
> Yes, and that was the point of the exercice. Transforming the interpolated "string" into a string evaluates the values of the variables at the moment of that transformation. From then on, there is no interpolation possible as it a simple string.
> I suppose that what aliak leant in his comments was that the string then could still be used for interpolation.
>
> [...]

I'm pretty sure I said that I expect interpolated strings to be assignable to strings and that this DIP doesn't enable that. And people will need to understand tuples to understand what's happening. I'm not sure how you interpreted all the rest?
December 17, 2019
On 12/11/19 4:52 AM, Mike Parker wrote:
> This is the feedback thread for the first round of Community Review for DIP 1027, "String Interpolation":
> 
> https://github.com/dlang/DIPs/blob/148001a963f5d6e090bb6beef5caf9854372d0bc/DIPs/DIP1027.md 
> 
> 
> All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on December 25, or when I make a post declaring it complete.
> 
> At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round of Community Review. Otherwise, it will be queued for the Final Review and Formal Assessment.
> 
> Anyone intending to post feedback in this thread is expected to be familiar with the reviewer guidelines:
> 
> https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md
> 
> *Please stay on topic!*
> 
> Thanks in advance to all who participate.

BTW, people have been talking about usage like:

auto str = i"I have $apples apples".format;

And it got me thinking, does this actually work? I mean, can multiple parameters be used for UFCS?

Answer: yes.

auto str = AliasSeq!("I have %s apples", apples).format; // OK

pretty cool. I had no idea.

-Steve
December 18, 2019
On Wednesday, 18 December 2019 at 01:20:33 UTC, Steven Schveighoffer wrote:
> On 12/11/19 4:52 AM, Mike Parker wrote:
>> [...]
>
> BTW, people have been talking about usage like:
>
> auto str = i"I have $apples apples".format;
>
> And it got me thinking, does this actually work? I mean, can multiple parameters be used for UFCS?
>
> Answer: yes.
>
> auto str = AliasSeq!("I have %s apples", apples).format; // OK
>
> pretty cool. I had no idea.

Huh. I wrote my example without UFCS precisely because I didn't know if that would work. Nice!


> -Steve