January 08
On 1/7/24 21:19, Walter Bright wrote:
> On 1/7/2024 11:52 AM, brianush1 wrote:
>> Not arsd.sqlite, nor any other library, defines their own interpolated strings. Importing a library does not and cannot change the behavior of interpolated strings, that is a misunderstanding. Library functions simple take in the interpolated string using a vararg template and do literally *whatever they want with it,* since they're given all the information about the interpolated string, including the evaluated expressions that were inside the string.
> 
> Thanks for the clarification. I had indeed misunderstood it.
> 
> So that means db.execi() is the template that adjusts how the call to sql is made. (I had assumed it was part of the sql api, rather than a wrapper.)
> 
> This makes it no different than DIP1027 in that regard.
> 
> It is not really necessary to have a marker to say if an argument is a literal or a variable. Consider this program:
> 
> ```
> import std.stdio;
> 
> void main()
> {
>      writeln("hello".stringof);
>      string foo = "betty";
>      writeln(foo.stringof);
> }
> ```
> 
> Which, when run, prints:
> 
> "hello"
> foo
> 
> and so a template, by using .stringof, can determine if a tuple element is a string literal or a variable.

Only if you pass the i-string as a template parameter (which might not even work because any non-symbol expression will need to be evaluated at compile time but maybe cannot). DIP1036 does not require that.

Also, what do you do if someone nests multiple i-strings? DIP1036 handles it. etc. The design is simple but it addresses many issues that authors of competing proposals did not even think about.
January 08
On 1/7/24 10:04, Walter Bright wrote:
> 
> It's true that in order for this to work,
> 
> ```
> db.execi(i"INSERT INTO sample VALUES ($(id), $(name))");
> ```
> would need to be written as:
> ```
> db.execi(xxx!(i"INSERT INTO sample VALUES ($(id), $(name))"));
> ```
> where `xxx` is the thoroughly unimaginative name of the transformer template.
> 
> Is adding the template call an undue burden?

Yes, among other reasons because it does not work.

This works with DIP1036:

```
int x=readln.strip.split.to!int;
db.execi(i"INSERT INTO sample VALUES ($(id), $(2*x))");
```

This cannot work:

```
int x=readln.strip.split.to!int;
db.execi(xxx!i"INSERT INTO sample VALUES ($(id), $(2*x))");
```


January 07
On 1/7/2024 3:27 PM, bomat wrote:
> I will continue with my D/vibe.d project because it is just a fun experiment that I do in my free time. If I get stuck at some point, fine, it still will have been a great learning experience.
> But would I stick with D if my business depended on it? Hell no. I'd probably use Go or maybe even C++ with wt or something like that. Something that I can be reasonably sure will still be maintained in 5 years from now.

D has been continuously improved and supported for over 20 years now.

January 08
On Sunday, 7 January 2024 at 21:16:46 UTC, H. S. Teoh wrote:
> On Sun, Jan 07, 2024 at 04:43:17PM +0000, Lance Bachmeier via Digitalmars-d wrote: [...]
>> I'd much rather Adam put his time into a fork, rather than the more common approach where he'd post here under various names, make ridiculous claims, and vandalize the discussions. If you're new, you may not have seen the many posts from someone that doesn't like private at the module level.
>
> Are you sure you have your facts straight? AFAIK the pseudonymous trolls who posted about private or this or that complaint were not Adam, they were some other disgruntled former D user who has since left.  AFAIK Adam has never engaged in such tactics and was in close contact with the core D team until the recent spat (which is the culmination of ongoing disagreements on governance that started more recently).

I'm saying it's good Adam isn't doing that, not that he is.

>> Whether there are useful insights from this or any other fork will depend on what they do with it. If there's too much incompatibility of code, due to breaking changes, it won't have much effect. There's already Nim, Rust, Go, Zig, etc., to compare with and the forks will in each case be just another language.
>
> Adam has stated (publicly, in the opendlang github discussions) that he does not plan to make major changes to the language that would massively break compatibility.  But of course, if this fork continues independently then over time things will diverge sooner or later.

I'm not sure what he has planned. I was just making a statement about forks in general - the more incompatibilities of a fork from the original, the less effect it has upstream. I think it's too early to speculate what will come of Adam's fork.
January 07
On 1/7/2024 3:45 PM, Timon Gehr wrote:
> Only if you pass the i-string as a template parameter (which might not even work because any non-symbol expression will need to be evaluated at compile time but maybe cannot).

Currently D internally supports non-trivial expressions as tuples. DIP1027 relies on that, as:

```
int i = 4;
writefln(i"hello $(3 + i)");
```

prints:

hello 7

But, if the tuple is created with:

```
template tuple(A ...) { alias tuple = A; }
```

then a non-trivial expression cannot be passed to it, as it will not work as an alias parameter. This is a general shortcoming in D, not a specific problem with DIP1027.

We've been moving towards:

```
auto tup = (1, 3 + i);
```
for a while now, which is why comma expressions have been deprecated.

Amusingly, istrings can be used to create non-trivial expression tuples with this:

```
int i = 4;
auto tup2 = i"$i $(3 + i)"[1..3];
writeln("a tuple: ", tup2);
```

which prints:

a tuple: 47

I can't recommend doing things that way, but it just illustrates istrings as being a building block rather than an end product.

As for detecting string literals, I have tried a few schemes to no avail. It may have to be added with a __traits, which is where we put such things.

Trying that with DIP1036 means there are several more entries added to the tuple, which would have to be filtered out.


> Also, what do you do if someone nests multiple i-strings? DIP1036 handles it. etc. The design is simple but it addresses many issues that authors of competing proposals did not even think about.

Nested istrings would do the expected - create a tuple within a tuple, which gets flattened out. You'd likely wind up with a compile time error that there are too many arguments for the format. Recall that the istring is simply converted to a tuple, after that, predictable tuple rules are followed.

However, the nested istring can always be inserted as an argument to the `text` function which will expand it into a single argument, and no tuple twubble.

In general, you and I agree that D should move towards much better tuple support. DIP1027 fits right in with that, as it does no magic. Better tuple support will fit right in in extending istring power, rather than making istring itself more powerful.
January 07
On 1/7/2024 3:50 PM, Timon Gehr wrote:
> This cannot work:
> 
> ```
> int x=readln.strip.split.to!int;
> db.execi(xxx!i"INSERT INTO sample VALUES ($(id), $(2*x))");
> ```

True, you got me there. It's the 2*x that is not turnable into an alias. I'm going to think about this a bit.


January 08

On Sunday, 7 January 2024 at 21:58:50 UTC, GrimMaple wrote:

>

There simply isn't a GC based language that can be as quick as C++

That's perhaps true of languages whose only memory-management method is GC-based. D isn't such a language. You can frequently avoid use of the GC in D because you have multiple memory-management techniques at your disposal.

I'm going to say something now that should be known by people who write code professionally, but is too often overlooked (I base this on many years of experience needing to convince people not to optimize prematurely and without having measured why their code doesn't perform as they would like). I'm not suggesting that you are guilty of this. I simply want it said explicitly.

The speed of the code generated by the language you are using is not necessarily the determining factor of the speed of your application. If your application is not cpu-limited and written in Python, re-writing it in C++ in pursuit of better performance is going to be a disappointment. If your application is cpu-limited but spends most of its time in some library, e.g.,sqlite, or in system-calls, re-writing it in C++ will only help in proportion to the time spent in your own code, which is small by assumption.

My point is that the performance vs. ease-of-coding tradeoff is not simple. It takes some smart engineering for a project to be near the sweet spot.

January 07
On 1/7/2024 6:30 PM, Walter Bright wrote:
> On 1/7/2024 3:50 PM, Timon Gehr wrote:
>> This cannot work:
>>
>> ```
>> int x=readln.strip.split.to!int;
>> db.execi(xxx!i"INSERT INTO sample VALUES ($(id), $(2*x))");
>> ```
> 
> True, you got me there. It's the 2*x that is not turnable into an alias. I'm going to think about this a bit.

I wonder if what we're missing are functions that operate on tuples and return tuples. We almost have them in the form of:

```
template tuple(A ...) { alias tuple = A; }
```

but the compiler wants A to only consist of symbols, types and expressions that can be computed at compile time. This is so the name mangling will work. But what if we don't bother doing name mangling for this kind of template?

January 07
On Mon, Jan 08, 2024 at 02:58:58AM +0000, Don Allen via Digitalmars-d wrote: [...]
> The speed of the code generated by the language you are using is not necessarily the determining factor of the speed of your application. If your application is not cpu-limited and written in Python, re-writing it in C++ in pursuit of better performance is going to be a disappointment. If your application *is* cpu-limited but spends most of its time in some library, e.g.,sqlite, or in system-calls, re-writing it in C++ will only help in proportion to the time spent in your own code, which is small by assumption.

I learned this the hard way over the years.  I used to be a self-proclaimed C/C++ expert, took pride in knowing obscure corners of C that very few others knew (I managed to answer correctly an obscure interview question that even the interviewer didn't know the answer to). I thought I knew it all about optimization, and that I could optimize just by looking at the code.

Boy was I wrong.

This one time I was having performance issues with my code, and I spent hours poring over every single line and optimizing it to next year and back.  The overall performance improvement was a disappointment. Finally, I conceded to using a profiler (before that I felt profilers were for wimps who didn't know how to program properly). The profiler instantly found the problem: a stray debug printf() that I forgot to remove after fixing a bug, that just happened to be sitting in the hot path.

That was just one of many, many such instances of hard reality smacking me upside the head.  After many years of such experiences, I began to realize just how wrong I am 90% of the time when it comes to performance.  The bottleneck is usually far away from where I assumed it'd be.  After learning this the hard way time and again, I learned one thing:

	Until you run a profiler on your program, you are most probably
	wrong about where the bottleneck is.

The corollary goes:

	If you're optimizing a piece of code before running a profiler
	on it, it's premature optimization and you're probably wasting
	your time.

The general theorem reads:

	Discussions about performance without hard numbers produced by
	actual profiler output are usually wrong.  Until you profile,
	it's all just guesswork and unfounded assumptions.

The practical takeaway is, whenever performance is an issue:

	Profile, profile, profile.

If you're not profiling and you talk about performance, I probably won't bother reading any further.  Or perhaps I would, but more for the entertainment value than any true technical merit.


> My point is that the performance vs. ease-of-coding tradeoff is not simple.  It takes some smart engineering for a project to be near the sweet spot.
[...]

Yep, optimization is an extremely complex problem that's very sensitive to fine details, and often, the exact use case or even exact data you're operating on.  Sweeping general statements about performance are rarely accurate, and not worth relying on unless there's hard data to back it up. And that's profiler data, not some made-up numbers made from some preconceived notion about optimization that's not based in reality.


T

-- 
Those who don't understand D are condemned to reinvent it, poorly. -- Daniel N
January 08
I kinda wish we had tuples that are not alias sequences right now.

1036e could be (at least in my opinion) better with them.

```
tuple(prefix, expression or positional, ...)
```

Removes the possibility of ref yes, but does introduce the possibility of f-string positional argument support and easily passing it around.

``i"prefix1${1}prefix2%{arg}"``

becomes

``tuple(PrefixType!("prefix1"), PositionType!1, PrefixType!("prefix2"), arg)``

```d
void writeln(Args...)(Args args) {
	static foreach(i, Arg; Args) {
		static if (is(Arg : typeof(tuple))) {
			// is tuple for arg i
		}
	}
}
```