February 26, 2020
On Wednesday, 26 February 2020 at 09:45:55 UTC, Walter Bright wrote:
>> void f(string s, int i = 0);
>> f(i"hello $a"); // silent unwanted bahviour.
>> 
>> ?
>
> It is lowered to:
>
>   f("hello %s", a);
>
> as designed. I don't know what's unwanted about it.

void print_many(string msg, int cnt = 1) {
    foreach(i; 0 .. cnt) writeln(msg);
}

int apple_cnt = 4;
print_many(i"I have $apple_cnt apples.");

expected: I have 4 apples.
real (unwanted) output:
I have 4 apples.
I have 4 apples.
I have 4 apples.
I have 4 apples.
February 26, 2020
On 2/26/2020 2:02 AM, Juraj Mojzis wrote:
> void print_many(string msg, int cnt = 1) {
>      foreach(i; 0 .. cnt) writeln(msg);
> }
> 
> int apple_cnt = 4;
> print_many(i"I have $apple_cnt apples.");
> 
> expected: I have 4 apples.

Doing what you want would require a runtime GC allocated string.
February 26, 2020
On 2/24/2020 4:07 PM, Steven Schveighoffer wrote:
> To ensure that it cannot be intercepted.

See my reply to H.S. Teoh which addresses this.
February 26, 2020
On Wednesday, 26 February 2020 at 09:45:55 UTC, Walter Bright wrote:
> On 2/25/2020 1:36 AM, 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?
>> 
>> void f(string s, int i = 0);
>> f(i"hello $a"); // silent unwanted bahviour.
>> 
>> ?
>
> It is lowered to:
>
>   f("hello %s", a);
>
> as designed. I don't know what's unwanted about it.

It's unwanted because the lowering calls a function that was not intended with values that were unintended. You can take this article: https://dlang.org/articles/hijack.html and replace it with that lowering behaviour, and have the exact same story.

Also unwanted because of what string interpolation means (ref wikipedia and all other languages).

February 26, 2020
On Wednesday, 26 February 2020 at 10:02:15 UTC, Juraj Mojzis wrote:
> On Wednesday, 26 February 2020 at 09:45:55 UTC, Walter Bright wrote:
>
> void print_many(string msg, int cnt = 1) {
>     foreach(i; 0 .. cnt) writeln(msg);
> }
>
> int apple_cnt = 4;
> print_many(i"I have $apple_cnt apples.");
>
> expected: I have 4 apples.
> real (unwanted) output:
> I have 4 apples.
> I have 4 apples.
> I have 4 apples.
> I have 4 apples.

Sorry, I made a mistake in my last reply.
This is the (unwanted) output:

I have %s apples.
I have %s apples.
I have %s apples.
I have %s apples.
February 26, 2020
On Tuesday, 25 February 2020 at 16:04:59 UTC, Arine wrote:
> ``How to distinguish a different type? Use a different type. No, is there another simpler way to do that instead?``
>
> Is this really the line of thinking going on here? It seems Walter has these arbitrary rules he's following which led up to the impractical and buggy solution that was DIP1027. Rules aren't meant to be followed blindly.

Calm down. I didn't ask how to distinguish a type. I asked how to prevent a behaviour. There's a slight difference. If you misunderstood that then maybe I just didn't communicate that properly.
February 26, 2020
On Wednesday, 26 February 2020 at 09:45:55 UTC, Walter Bright wrote:
> On 2/25/2020 1:36 AM, 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?
>> 
>> void f(string s, int i = 0);
>> f(i"hello $a"); // silent unwanted bahviour.
>> 
>> ?
>
> It is lowered to:
>
>   f("hello %s", a);
>
> as designed. I don't know what's unwanted about it.

In all other languages with string interpolation that I'm familiar with, `a` is not passed to the `i` parameter.

---
C#

Code:

    public class Program
    {
        public static void f(string s, int i = 21)
        {
            System.Console.WriteLine($"s='{s}' | i='{i}'");
        }

        public static void Main()
        {
            int a = 42;
            f($"hello {a}");
        }
    }

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/ZigzagStickyHardware
---

JavaScript

Code:
    function f(s, i = 21) {
      console.log(`s='${s}' | i='${i}'`);
    }

    const a = 42;
    f(`hello ${a}`);

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/TechnologicalJointDisassembler

---

Python

Code:
    def f(s, i = 21):
        print(f"s='{s}' | i='{i}'")

    a = 42;
    f(f"hello {a}");

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/CrookedOutlandishInstructions

---

Ruby:

Code:
    def f(s, i = 21)
      puts "s='#{s}' | i='#{i}'"
    end

    a = 42;
    f("hello #{a}")

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/MidnightblueProudAgent

---

Kotlin

Code:
    fun f(s: String, i: Int = 21) {
        println("s='$s' | i='$i'");
    }

    val a = 42;
    f("hello $a");

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/ImpartialPepperyProducts

---

Dart

Code:
    void f(String s, [int i = 21]) {
      print("s='${s}' | i='${i}'");
    }

    void main() {
      const a = 42;
      f("hello ${a}");
    }

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/AwareSqueakyProlog

---

Swift

Code:
    func f(_ s: String, _ i: Int = 21) {
      print("s='\(s)' | i='\(i)'");
    }


    let a = 42
    f("hello \(a)")

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/MulticoloredCulturedRule

---

Julia:

Code:
    function f(s, i = 21)
      print("s='$s' | i='$i'")
    end

    a = 42
    f("hello $a")

Output:
    s='hello 42' | i='21'

Try it online: https://repl.it/repls/StupidAcidicDatabases

---

And so on...
February 26, 2020
On Wednesday, 26 February 2020 at 11:13:12 UTC, Petar Kirov [ZombineDev] wrote:
> On Wednesday, 26 February 2020 at 09:45:55 UTC, Walter Bright wrote:
>> It is lowered to:
>>
>>   f("hello %s", a);
>>
>> as designed. I don't know what's unwanted about it.
>
> In all other languages with string interpolation that I'm familiar with, `a` is not passed to the `i` parameter.
>
> ---
> [snip]

To be fair, none of those languages care about an extra string allocation.

But to be fair again, Adam/Steven's proposal can avoid the memory allocation while also not passing i implicitly, at the cost of not matching to the string type.

But to be thrice fair, Adam/Steven's proposal would work with the minor extension `f(i"hello $a".format)`/`f(i"hello $a".to!string)`, in keeping with the trend of GC use requiring explicit opt-in.
February 26, 2020
On Wednesday, 26 February 2020 at 12:18:07 UTC, FeepingCreature wrote:
> But to be thrice fair, Adam/Steven's proposal would work with the minor extension `f(i"hello $a".format)`/`f(i"hello $a".to!string)`, in keeping with the trend of GC use requiring explicit opt-in.

Actually, thanks to the new type, the sample code in my dip offers an `idup` overload that works really easily for the users.


void foo(string s) {}

const(char)[] a;

foo(a); // doesn't work, but you can .idup it

foo(i"..."); // doesn't work, but you can .idup it too!

foo(i"...".idup); // indicates you are OK with the GC copy by asking for one


so still really easy to use while being in line with D's existing features. No GC if you don't want it, easy GC if you do.
February 26, 2020
On 2/26/20 4:57 AM, Walter Bright wrote:
> On 2/25/2020 9:44 AM, H. S. Teoh wrote:
>> On Mon, Feb 24, 2020 at 10:54:34PM -0800, Walter Bright via Digitalmars-d-announce wrote:
>> [...]
>>> Writing that an implementation must refer to specific templates
>>> implies that the behavior is customizable by the user via modifying
>>> those templates.
>>
>> I think this is where the misunderstanding is. The proposed template is
>> defined by druntime, and is NOT customizable by the user.
> 
> Requiring the compiler to use a specific template that is not specified by the user has no place in a language specification (and therefore no place in a proposed language change).

We can do it without specifying that it's a template or the name of that template.

But this statement still belies your misunderstanding. D is full of compiler-defined types that are implemented via templates in the library "not specified by the user".

> The specification does NOT specify how it should be implemented.

No but logic does. It will have to be implemented this way, but we can certainly word the spec to "leave it up to the compiler/runtime implementation" to satisfy the requirements.

-Steve