www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP1027 + Design by Introspection

reply Daniel N <no public.email> writes:
DIP1027 + Design by Introspection

Since DIP1027 is simpler than DIP1036 I wanted to take a step 
back and see what could be done to fix DIP1027 to be even better 
than DIP1036.

1) q{} is designed for code generation it needs to be supported 
with Interpolation.
2) DbI

IMHO both DIP1027 and DIP1036 suffers when trying to support 
custom formatting...
which makes the syntax as hard to read as the original manual 
writefln format string.

My DIP1027+ proposal is based on UDA and can support any function 
with trivial syntax.
   printf(i"I ate $apples and $bananas totalling $(apples + 
bananas) fruit.");
writefln(i"I ate $apples and $bananas totalling $(apples + 
bananas) fruit.");

Key insight, the function specifies what format it expects.
printf(...)    formatting!printf_style
writefln(...)  formatting!writefln_style
This way it doesn't have to be repeated in user-facing code over 
and over.

Basically the compiler will invoke "printf_style!int" and the 
function will return "%d",
the compiler doesn't know anything about printf, it will just 
introspect/ask the function.
Feb 02 2021
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 2 February 2021 at 15:55:23 UTC, Daniel N wrote:
 Since DIP1027 is simpler than DIP1036
This is a myth, with the exception of the implicit to string conversion. DIP 1027 had to break up the string and reconstruct a new one while reordering the tuple. DIP 1036 is a direct syntax rewrite. It just splits the string on the ${ character into a tuple and puts a simple struct wrapper around the string parts so you can identify them. See for yourself how simple the diff is: https://github.com/dlang/dmd/compare/master...adamdruppe:string_interp The implicit to string part isn't implemented (gotta figure out how to express `alias toString this;` inside the compiler basically, it might be easy but I don't know how).
 Key insight, the function specifies what format it expects.
 printf(...)    formatting!printf_style
 writefln(...)  formatting!writefln_style
DIP 1036 can do this as it is already written! You don't need a magic UDA, you just overload the function on the interp type as a library author. Or you can simply call a function inside the interpolation thing if you want to do custom stuff as a user.
Feb 02 2021
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 2 February 2021 at 16:57:36 UTC, Adam D. Ruppe wrote:
 On Tuesday, 2 February 2021 at 15:55:23 UTC, Daniel N wrote:
 Since DIP1027 is simpler than DIP1036
This is a myth, with the exception of the implicit to string conversion. DIP 1027 had to break up the string and reconstruct a new one while reordering the tuple. DIP 1036 is a direct syntax rewrite. It just splits the string on the ${ character into a tuple and puts a simple struct wrapper around the string parts so you can identify them.
DIP 1027 is a single direct syntax rewrite with no library support required. DIP 1036 is two separate syntax rewrites, plus an algorithm for choosing between them, plus support code for the rewrites in druntime. DIP 1036 has plenty of advantages compared to DIP 1027, but trying to pretend it is a simpler proposal is just dishonest.
Feb 02 2021
parent reply Daniel N <no public.email> writes:
On Tuesday, 2 February 2021 at 17:04:47 UTC, Paul Backus wrote:
 DIP 1036 has plenty of advantages compared to DIP 1027, but 
 trying to pretend it is a simpler proposal is just dishonest.
I thought the only thing everyone could agree on was that DIP1027 is less complex, at least I could get the gist of it in an instant in contrast to DIP1036. My mistake, I guess it hasn't been established as a fact, I was not intentionally misleading, for me it was as obvious as "the sky is blue", but people would contest that also since it's not always blue, now is it?
Feb 02 2021
parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 2 February 2021 at 17:39:06 UTC, Daniel N wrote:
 On Tuesday, 2 February 2021 at 17:04:47 UTC, Paul Backus wrote:
 DIP 1036 has plenty of advantages compared to DIP 1027, but 
 trying to pretend it is a simpler proposal is just dishonest.
I thought the only thing everyone could agree on was that DIP1027 is less complex, at least I could get the gist of it in an instant in contrast to DIP1036.
Did you mean to reply to Adam instead of me? I agree with you--DIP 1027 is less complex than DIP 1036.
Feb 02 2021
parent Daniel N <no public.email> writes:
On Tuesday, 2 February 2021 at 17:56:32 UTC, Paul Backus wrote:
 On Tuesday, 2 February 2021 at 17:39:06 UTC, Daniel N wrote:
 On Tuesday, 2 February 2021 at 17:04:47 UTC, Paul Backus wrote:
 DIP 1036 has plenty of advantages compared to DIP 1027, but 
 trying to pretend it is a simpler proposal is just dishonest.
I thought the only thing everyone could agree on was that DIP1027 is less complex, at least I could get the gist of it in an instant in contrast to DIP1036.
Did you mean to reply to Adam instead of me? I agree with you--DIP 1027 is less complex than DIP 1036.
My bad again ;) Yes!
Feb 02 2021
prev sibling parent reply Daniel N <no public.email> writes:
On Tuesday, 2 February 2021 at 16:57:36 UTC, Adam D. Ruppe wrote:
 Key insight, the function specifies what format it expects.
 printf(...)    formatting!printf_style
 writefln(...)  formatting!writefln_style
DIP 1036 can do this as it is already written! You don't need a magic UDA, you just overload the function on the interp type as a library author. Or you can simply call a function inside the interpolation thing if you want to do custom stuff as a user.
In my opinion the user-facing interface of my proposal is cleaner as you don't have to introduce an interp template, you won't have to overload anything nor wrap anything.
Feb 02 2021
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 2 February 2021 at 17:29:53 UTC, Daniel N wrote:
 In my opinion the user-facing interface of my proposal is 
 cleaner as you don't have to introduce an interp template, you 
 won't have to overload anything nor wrap anything.
But you have to modify the source code in the library anyway. And then how do you add new styles? How does formatting!printf_style actually get applied?
Feb 02 2021
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/2/21 12:29 PM, Daniel N wrote:
 On Tuesday, 2 February 2021 at 16:57:36 UTC, Adam D. Ruppe wrote:
 Key insight, the function specifies what format it expects.
 printf(...)    formatting!printf_style
 writefln(...)  formatting!writefln_style
DIP 1036 can do this as it is already written! You don't need a magic UDA, you just overload the function on the interp type as a library author. Or you can simply call a function inside the interpolation thing if you want to do custom stuff as a user.
In my opinion the user-facing interface of my proposal is cleaner as you don't have to introduce an interp template, you won't have to overload anything nor wrap anything.
This is somewhat of a fallacy. You are overloading and wrapping (in a severely inflexible way). Just doing it with the compiler instead of an actual overload. Knowing how the compiler treats the rewrite is still a cognitive load on the user. And there are several issues: 1. It doesn't help when the function isn't "blueprint then data" style, which is costly compared to interleaved data, and only allows one interpolation string parameter. 2. It doesn't support "blueprint then data" implementations that require positional parameters (for example, Postgresql). And if you wanted something to support this, a. you'd have to rename it, as an overload would match the existing function, and b. you would still be able to call either function with either style (string + args or interpolation tuple). 3. It doesn't allow compile-time processing of the format string, nor really any useful compile-time introspection that isn't already available with the type being passed in the value tuple anyway. 4. There is no mechanism to overload "compiler-provided formats" with "user-provided formats". This means the resulting function must still guard against invalid input, instead of making it a compiler error (except, of course, with the magic help of the compiler specifically for printf). I want to expand a bit on point 1 too. Consider that DIP1036 is a straight rewrite of i"a${b}${c}d" as interp!"a", b, c, interp!"d". This is straightforward, intuitive, and can be explained easily. DIP1027 is a rewrite of i"a${b}${c}d" as "a%s%sd", b, c. This is not intuitive, nor cheap. I know it seems intuitive to C programmers, but for sure, blueprint+args is NOT intuitive to those not used to printf. Not only that but guess what functions like printf and writef do. They reinterpret the parameters using the blueprint to get them back into order. And this means iterating in parallel a PARSED version of the blueprint along with the parameters. Why would we want to do something that's harder to explain, harder to implement, and ironically round tripped from something parsed at compile-time to something that requires runtime parsing? I would note that DIP1027 would be a great CIP. D is not C. We have insanely good tools for this. Making it so you can't use introspection tools is not my idea of "better". -Steve
Feb 02 2021
parent Daniel N <no public.email> writes:
On Tuesday, 2 February 2021 at 18:47:48 UTC, Steven Schveighoffer 
wrote:
 I would note that DIP1027 would be a great CIP. D is not C. We 
 have insanely good tools for this. Making it so you can't use 
 introspection tools is not my idea of "better".

 -Steve
That was some good destructing, kudos! I still think UDA has merit, but I can't fix all your concerns without increasing complexity even beyond DIP1036. Will try from the other direction, to see if I can offer any ideas to simplify DIP1036 instead... /Daniel
Feb 03 2021
prev sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 2 February 2021 at 15:55:23 UTC, Daniel N wrote:
 DIP1027 + Design by Introspection

 Since DIP1027 is simpler than DIP1036 I wanted to take a step 
 back and see what could be done to fix DIP1027 to be even 
 better than DIP1036.

 1) q{} is designed for code generation it needs to be supported 
 with Interpolation.
 2) DbI

 IMHO both DIP1027 and DIP1036 suffers when trying to support 
 custom formatting...
 which makes the syntax as hard to read as the original manual 
 writefln format string.

 My DIP1027+ proposal is based on UDA and can support any 
 function with trivial syntax.
   printf(i"I ate $apples and $bananas totalling $(apples + 
 bananas) fruit.");
 writefln(i"I ate $apples and $bananas totalling $(apples + 
 bananas) fruit.");

 Key insight, the function specifies what format it expects.
 printf(...)    formatting!printf_style
 writefln(...)  formatting!writefln_style
 This way it doesn't have to be repeated in user-facing code 
 over and over.

 Basically the compiler will invoke "printf_style!int" and the 
 function will return "%d",
 the compiler doesn't know anything about printf, it will just 
 introspect/ask the function.
We don't need more built in attributes to an attribute filled language. -Alex
Feb 02 2021
parent Daniel N <no public.email> writes:
On Tuesday, 2 February 2021 at 18:36:30 UTC, 12345swordy wrote:
 We don't need more built in attributes to an attribute filled 
 language.

 -Alex
Sorry to inform you that this one kinda already exist. https://dlang.org/spec/pragma.html#printf Although, I prefer attributes over pragma, as it can be introspected. It's actually a fairly common solution, even gcc has format attribute: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html See "format (archetype, string-index, first-to-check)"
Feb 02 2021