January 11, 2018
On Thu, Jan 11, 2018 at 04:38:57PM -0500, Steven Schveighoffer via Digitalmars-d-announce wrote:
> On 1/11/18 4:12 PM, kdevel wrote:
> > On Thursday, 11 January 2018 at 20:40:01 UTC, Dmitry Olshansky wrote:
> > > What did you expect?
> > 
> > To be honest: A compile time error. Modern C compilers can check such format strings. Example: GCC 6:
> 
> But dmd isn't a C compiler, nor does it have to worry about the problems C has (namely, untyped varargs). To dmd, printf is just another function, there's nothing special about it.
[...]

Yeah, checking C-style printf formats isn't dmd's problem.

The Phobos equivalent of printf, however, *does* support compile-time format checking in the latest version:

	writefln!"%s %d %d"("abc", 1); // "Orphan format specifier: %d"
	writefln!"%s %d"("abc", 1, 2); // "Orphan format arguments: args[2..3]"
	writefln!"%s %d"(1, "abc");    // "Incorrect format specifier for range: %d"
	writefln!"%f"(1);              // "incompatible format character for integral argument: %f"

Best of all, this is all done via CTFE in the library code, no hard-coding in the compiler necessary.  You can implement your own compile-time checker for your own DSLs in the same way, without needing to hack the compiler.


T

-- 
MSDOS = MicroSoft's Denial Of Service
January 11, 2018
On 2018-01-11 15:34:04 +0000, Seb said:

>> Side-Note: I'm always missing the betterC information or is the philosophy to just try it out?
> 
> We have now this page:
> 
> https://dlang.org/spec/betterc.html

Hi, thanks. Should have been more precise: An informaiton for every lib if it is compatible with betterC.

IMO betterC is the strategic trojan horse to get D into the broader masses.

> Well, betterC it's still a WIP feature and its feature subset is improved from release to release.
> In doubt you can always use run.dlang.io to quickly try out things.

That's great, thanks for the hint.

-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

January 11, 2018
On 2018-01-11 18:15:23 +0000, rumbu said:

> On Thursday, 11 January 2018 at 11:19:41 UTC, Robert M. Münch wrote:
>> 
>> Great stuff! Will this work in betterC mode?
> 
> It will not work without some refactory. Most of phobos/druntime dependencies are minimal an can be rewritten - in fact there are only 9 dependencies: bsr, bsf, addu, subu, adds, subs from druntime and isNaN, isinfinity, signbit from std.math.
> 
> The rest of the dependencies are simply traits that must work by default under betterC.

Ok, that doesn't sound impossible.

> Once dependencies are solved, another problem will be the exception mechanism. 90% of arithmetic operations are meant to throw exceptions, but this can be overridden by the alternate exception handling - raising and setting flags.

Yes, makes sense.

> BUT - a very big but - the most important issue is the formatting thing.
> ...
> a printf equivalent for decimal types is rewritten from scratch or -
> decimal values must be converted to binary float before printing them -
> but this will negate the main purpose of the decimal type - precision.

Well, I think even using a decimal128 for some calculations to have higher precision intermediate results and only converting them to float for UI interaction would make a lot of sense.

At least in our use-case, that would be quite interesting.

Looking forward to see some benchmarks.


-- 
Robert M. Münch
http://www.saphirion.com
smarter | better | faster

January 11, 2018
On Thursday, 11 January 2018 at 21:24:30 UTC, kdevel wrote:
> On Thursday, 11 January 2018 at 20:44:13 UTC, kdevel wrote:
>> On Thursday, 11 January 2018 at 20:35:03 UTC, kdevel wrote:
>>>              <--- loop output missing
>
> loop.d
> ```
> import std.stdio;
> import decimal;
>
> void loopme(T) ()
> {
>    "---".writeln;
>    T e = T(1000);
>    while (e > T(1e-6)) {
>       e.writeln;
>       e /= 10;
>    }
> }
>
> void main ()
> {
>    loopme!float;
>    loopme!decimal32;
> }
> ```
>
> This prints
>
>    ---
>    1000
>    100
>    10
>    1
>    0.1
>    0.01
>    0.001
>    0.0001
>    1e-05
>    ---
>    1000
>    100
>    10
>    1
>    0.1
>    0.0100000    <--
>    0.00100000   <--
>    0.000100000  <--
>    1.00000e-05  <--
>
> Why are there trailing zeroes?


As I said, the %g specifier (used by default in writeln) makes me cry. Anyway, I made some modifications, now it prints correctly (in fact using floats just proves the need of decimals on my system):

--
1000
100
10
1
0.1
0.01
0.00099999
0.000099999
1e-05
---
1000
100
10
1
0.1
0.01
0.001
0.0001
1e-05

Regarding printf, I cannot help, this is a C function, has nothing to do with D formatting.

January 11, 2018
On Thursday, 11 January 2018 at 22:36:40 UTC, rumbu wrote:
> 1000
> 100
> 10
> 1
> 0.1
> 0.01
> 0.001
> 0.0001
> 1e-05
>
> Regarding printf, I cannot help, this is a C function, has nothing to do with D formatting.

Sure. What about the failed comparison:

gt.d
```
import std.stdio;
import decimal;

void loopme(T) ()
{
   "---".writeln;
   T e = 10;
   while (e > 1e-6) {
      e /= 10;
      writeln (e, ' ', e > 1e-6);
   }
}

void main ()
{
   loopme!decimal32;
   loopme!decimal64;
   loopme!decimal128;
}
```

This gives here:

   ---
   1 true
   0.1 false
   ---
   1 true
   0.1 false
   ---
   1 true
   0.1 true
   0.0100000 true
   0.00100000 true
   0.000100000 true
   1.00000e-05 true
   1.00000e-06 true
   1.00000e-07 false
January 12, 2018
On Thursday, 11 January 2018 at 23:57:29 UTC, kdevel wrote:
What about the failed comparison:
>
> gt.d
> ```
> import std.stdio;
> import decimal;
>
> void loopme(T) ()
> {
>    "---".writeln;
>    T e = 10;
>    while (e > 1e-6) {
>       e /= 10;
>       writeln (e, ' ', e > 1e-6);
>    }
> }
>
> void main ()
> {
>    loopme!decimal32;
>    loopme!decimal64;
>    loopme!decimal128;
> }
> ```
>
> This gives here:
>
>    ---
>    1 true
>    0.1 false
>    ---
>    1 true
>    0.1 false
>    ---
>    1 true
>    0.1 true
>    0.0100000 true
>    0.00100000 true
>    0.000100000 true
>    1.00000e-05 true
>    1.00000e-06 true
>    1.00000e-07 false

This is not failed comparison. 1e-6 cannnot be represented exactly as binary floating point, it is in fact 0.00000099999999999999995481 as double which happens to be less than 1e-6.

decimal32 and decimal64 are rounding up the value, decimal128 has enough precision (34 digits) to render exactly the value above.

writefln(" 7 digits: %#.7f", 1e-6);
writefln("15 digits: %#.15f", 1e-6);
writefln("34 digits: %#.34f", 1e-6);

-----

 7 digits: 0.0000010
15 digits: 0.000001000000000
34 digits: 0.0000009999999999999999548100000000





January 12, 2018
> On Thursday, 11 January 2018 at 23:57:29 UTC, kdevel wrote:
> What about the failed comparison:
>>
....

You are right in fact, there is also a failed comparison. Now corrected.




January 12, 2018
On Friday, 12 January 2018 at 05:18:15 UTC, rumbu wrote:
>> On Thursday, 11 January 2018 at 23:57:29 UTC, kdevel wrote:
>> What about the failed comparison:
>>>
> ....
>
> You are right in fact, there is also a failed comparison. Now corrected.

Works. Thanks for the changes!
January 12, 2018
On Monday, 8 January 2018 at 22:16:25 UTC, rumbu wrote:
> - all std.math functions implemented (even logarithms and trigonometry);

nosine.d
```
import std.stdio;
// import std.math;
import decimal;

void nosine (T) ()
{
   T d = T(1.1);
   writeln (sin(d));
}

void main ()
{
   nosine!decimal32;
   nosine!decimal64;
   nosine!decimal128;
}
```

$ dmd nosine.d decimal.git/libdecimal.a
decimal/package.d(10505): Error: undefined identifier decimalCapAngle
decimal/package.d(5364): Error: template instance decimal.decimalSin!(Decimal!32) error instantiating
nosine.d(8):        instantiated from here: sin!(Decimal!32)
nosine.d(13):        instantiated from here: nosine!(Decimal!32)
decimal/package.d(10505): Error: undefined identifier decimalCapAngle
decimal/package.d(5364): Error: template instance decimal.decimalSin!(Decimal!64) error instantiating
nosine.d(8):        instantiated from here: sin!(Decimal!64)
nosine.d(14):        instantiated from here: nosine!(Decimal!64)
decimal/package.d(10505): Error: undefined identifier decimalCapAngle
decimal/package.d(5364): Error: template instance decimal.decimalSin!(Decimal!128) error instantiating
nosine.d(8):        instantiated from here: sin!(Decimal!128)
nosine.d(15):        instantiated from here: nosine!(Decimal!128)

January 12, 2018
On Thursday, 11 January 2018 at 22:07:42 UTC, H. S. Teoh wrote:
> On Thu, Jan 11, 2018 at 04:38:57PM -0500, Steven Schveighoffer via Digitalmars-d-announce wrote:
>> On 1/11/18 4:12 PM, kdevel wrote:
>> > On Thursday, 11 January 2018 at 20:40:01 UTC, Dmitry Olshansky wrote:
>> > > What did you expect?
>> > 
>> > To be honest: A compile time error. Modern C compilers can check such format strings. Example: GCC 6:
>> 
>> But dmd isn't a C compiler, nor does it have to worry about the problems C has (namely, untyped varargs). To dmd, printf is just another function, there's nothing special about it.
> [...]
>
> Yeah, checking C-style printf formats isn't dmd's problem.
>
> The Phobos equivalent of printf, however, *does* support compile-time format checking in the latest version:
>
> 	writefln!"%s %d %d"("abc", 1); // "Orphan format specifier: %d"
> 	writefln!"%s %d"("abc", 1, 2); // "Orphan format arguments: args[2..3]"
> 	writefln!"%s %d"(1, "abc");    // "Incorrect format specifier for range: %d"
> 	writefln!"%f"(1);              // "incompatible format character for integral argument: %f"
>
> Best of all, this is all done via CTFE in the library code, no hard-coding in the compiler necessary.  You can implement your own compile-time checker for your own DSLs in the same way, without needing to hack the compiler.

Interesting, guess this was added last April with dmd 2.074?

https://dlang.org/changelog/2.074.0.html#std-format-formattedWrite

You or someone should write up a blog post about this, with both this example and expanding on how D enables this kind of functionality in general.