September 10, 2022
On 10.09.22 19:43, Walter Bright wrote:
> On 9/10/2022 9:18 AM, Timon Gehr wrote:
>> o!422 is such a hack,
> 
> How so?
> ...

422 is a decimal literal. E.g., there is type deduction logic in the compiler:

```d
import std.conv: o=octal;

void main(){
    auto x0=o!1000000000;
    static assert(is(typeof(x0)==int));
    auto x1=o!10000000000;
    static assert(is(typeof(x1)==long));
}
```

It was never meant to be interpreted as octal, and it shows.

>> and it does not even (always) work.
> 
> You're referring to when it has too many digits, it has to be done as:
> 
>    o!"442"
> ...

Sure, for example. Pure, unadulterated incidental complexity. Now every D programmer has to know multiple details about this nonsense. No simplification was achieved.

I was objecting to the argument where you used the hack to claim it's not much more ugly. However, this hack should not exist and not be used.

> It would be interesting to see a proposal to improve this sort of thing.
> ...

Build it into the lexer using the canonical syntax.

>> Binary literals are e.g., a GNU C extension and they are in C++14, so clearly people see an use for them.
> 
> I implemented them back in the 80s as an extension, and nobody commented on them. I never found a use.

Obviously you have been using them on a daily basis and are just lying to us so you can simplify the lexer. /s

(Actually, I can see no upside whatsoever. I imagine the lexer will just get a bit bigger, because it still has to give a nice error message saying to use the Phobos template instead.)

> As for seeing a use, seeing a use for them and actually using them are different things.
> ...

People have been telling you they are actually using them. I think you should consider updating your wrong belief that nobody is actually using them. It seems quite rude to tell people that they are not actually using features that they themselves can see they are obviously using.

> D originally was embeddable in html. The compiler was able to extract it from html files. I saw a use for it, but never found one. It was dropped. Nobody commented on that, either.
> 
> 
>>> Let's simplify D.
>> I really don't understand why you seem to think removing simple and convenient lexer features that behave exactly as expected in favor of overengineered Phobos templates that have weird corner cases and are orders of magnitude slower to compile is a meaningful simplification of D. It utterly makes no sense to me.
> 
> The idea is to have a simple core language, and have a way that users can add features via the library.

You consistently argue against things like AST macros. I don't think you can have it both ways. There's value in the language providing obvious features as built-ins with standardized syntax. The features are the language and clean syntax is one of the things that people consistently bring up when they have to explain why they are using D. This becomes harder to uphold when you turn obvious code into logically inconsistent line noise for purely ideological reasons.

> For example, user-defined literals are a valuable feature. C++ added specific syntax for them. D has user-defined literals as fallout from the template syntax.
> ...

D has templates with string arguments. I am pretty sure that even if C++ had templates with string arguments, they still would have added user-defined literals.

> User-defined literals in D are indeed an order of magnitude slower than builtin ones. But that only matters if one is using a lot of them. Like having files filled with them. How often does that happen?
> ...

It adds up. It opens the language up to ridicule. The cost/benefit analysis for removing this feature seems widely off.

> The Phobos implementation of octal is indeed overengineered, as I mentioned in another post here. Phobos in general has been overengineered, but that's not a fault of the language. I suppose I should submit a PR to fix the octal template implementation.
> ...

I don't think there's a very good implementation of the idea.

> 
>  > Let's simplify D in a way that actually positively impacts the user experience,
>  > for example by getting rid of weird corner cases and arbitrary limitations. Of
>  > course, that requires actual design work and sometimes even nontrivial compiler
>  > improvements, which is a bit harder than just deleting a few lines of code in
>  > the lexer and then adding ten times that amount to Phobos.
> 
> We do this all the time.

Which is good.


Which situation is the simplest one?

a)

0x... for hexadecimal
0o... for octal
0b... for binary


b)

0x... for hexadecimal
std.conv.octal!"..." for octal
0b"..." for binary


c)

0x... for hexadecimal
std.conv.octal!"..." for octal
std.conv.binary!"..." for binary
September 10, 2022
On Saturday, 10 September 2022 at 21:57:51 UTC, Timon Gehr wrote:
> On 10.09.22 19:43, Walter Bright wrote:

> Which situation is the simplest one?
>
> a)
>
> 0x... for hexadecimal
> 0o... for octal
> 0b... for binary


Surely it's (a), and it's consistent!


The other options ... even looking at them let me feel want to vomit, so I have to delete from the quotes.

September 10, 2022
On Saturday, 10 September 2022 at 21:57:51 UTC, Timon Gehr wrote:
>
> D has templates with string arguments. I am pretty sure that even if C++ had templates with string arguments, they still would have added user-defined literals.

C++ has user defined literals since C++11. Typically something that ends with "_myliteral", for example 300_km. Both string and value literals are supported.
September 10, 2022

On Friday, 9 September 2022 at 16:55:18 UTC, Puneet Goel wrote:

>

Please reconsider binary literal deprecation.

Just to add a data point to the discussion, I have run a search over one of my D projects and got 151 hits in 15 files for \b0b, so I use them quite a lot.

September 11, 2022
On Saturday, 10 September 2022 at 21:57:51 UTC, Timon Gehr wrote:
> 422 is a decimal literal. E.g., there is type deduction logic in the compiler:

Well, that was a requirement for Phobos inclusion (and one that caused considerable complexity increase). The idea was to replicate the behavior of the original literal. Though I will grant the requirement that if the literal has a L on the end that it always comes out typed as long is what causes the effect you pointed out, since the compiler will treat that 10000000000 and 10000000000L, and 10L too all the same way, so the template can't tell the difference.

Still, consider this massively simplified implementation:

enum o(ulong a) = to!int(to!string(a), 8);

That's consistently going to give you an int, even if the compiler made the input a long. But it no longer will give a long if you use the L suffix. (and yes i know it throws if the octal is legit more than 31 bits too, so you realistically might need a static if branch in there to allow that to be long in those cases. Or you could simply make it always return ulong and let VRP take care of things:

enum o(ulong a) = to!ulong(to!string(a), 8);

int x1=o!10000000000; // perfectly fine

but then `auto` will always give you ulong. so there is no perfect answer. only the string one can really match the suffix rules etc. or, of course, a built in literal. which is the correct answer. But I personally never liked the string version.

BTW there's also an argument to be made that the whole `enum` aspect is a bit hacky - you can also use a standard function and let the ordinary constant folder and dead code elimination give you the very same result too.)



like i get your point and you can call it a hack if you want

but i consider it pure genius

just like its brilliant inventor

it just isn't meant for this fallen world in which we live
September 10, 2022
On Sat, Sep 10, 2022 at 11:57:51PM +0200, Timon Gehr via Digitalmars-d wrote: [...]
> Which situation is the simplest one?
> 
> a)
> 
> 0x... for hexadecimal
> 0o... for octal
> 0b... for binary
> 
> 
> b)
> 
> 0x... for hexadecimal
> std.conv.octal!"..." for octal
> 0b"..." for binary
> 
> 
> c)
> 
> 0x... for hexadecimal
> std.conv.octal!"..." for octal
> std.conv.binary!"..." for binary

There's also:

d)

std.conv.hex!"..." for hexadecimal
std.conv.octal!"..." for hexadecimal
std.conv.binary!"..." for hexadecimal

Which, judging by the way things are going, is where we're headed.  The logical conclusion of which is:

e)

std.conv.hex!"..." for hexadecimal
std.conv.octal!"..." for hexadecimal
std.conv.binary!"..." for hexadecimal
std.conv.decimal!"..." for decimal - because the language becomes *much*
	simpler when it doesn't natively support any integer literals at
	all.

:-P


T

-- 
Being able to learn is a great learning; being able to unlearn is a greater learning.
September 11, 2022
 On Saturday, 10 September 2022 at 18:32:26 UTC, Walter Bright wrote:
> I understand. I suppose it's like learning to touch-type. Takes some effort at first, but a lifetime of payoff. There's no way to avoid working with binary data without getting comfortable with hex.

Might not be generally applicable, but “binary data” and “data represented by binary digits” aren’t practically the same thing to me. Like: Do the individual digits of a number impose a special meaning? Or are they just a vehicle to represent the number?

If the individual binary digits have a meaning (and the number they form is only their storage, think: container), viewing them by their number in a consolidating representation imposes extra work to derive the individual digits. Because it’s the digits that matter, the number itself has no meaning. Even if they’re technically the same.

The opposite would be the case with 8bit RGB color channels:
The digits impose no meaning by themselves. It’s the whole number that represents the brightness of the channel. Whether the any digit is 0,1,2,3,… is useless information on its own. It only serves a purpose when one has the whole number available. The digits are are only a tool to visualize the number here.

…unless we consolidate multiple channels into one number:
e.g. `#B03931` (= 0xB0_39_31)
While the number itself still represents a specific color (mixed from the three channels R/G/B), the meaning is implied by looking at the digits representing (the brightness of) the individual channels. Once one converts said number (the “color code”) to decimal (→ 11548977) that meaning is lost.

Another example:
If someone told me that DDRB (Data Direction Register B) of my ATmega 328p were 144, I’d know nothing while technically I’ve been told everything. I first have to separate said number to binary digits; then I will find out what I could have been told in the first place: PINB4 (digit 4) and PINB7 (digit 7) are set to 1 (“input”).
Hex form 0x90 might make the separation process easier, but it’s still a number representing a certain state, not the state data itself. Binary form however matches perfectly the actual state data.

Why this differentiation matters:
In case we get one digit wrong, how much a “whole number” is off, depends on the position of the digit in the number; e.g.

• if we’re talking about a color channel then 255 (xFF) vs 55 (x37) will make a whole lot of a difference, while 255 (xFF) vs 250 (xFA) might be barely visible in real life. Nevertheless, the “whole” color channel (it’s an atomic thing from this point of view) is wrong. There’s practically no specific sub-portion that is wrong (we’re only making up one by partitioning the number into digits).

• If a digit of the data direction register in my microcontroller is wrong, only one pin will malfunction (further impact depending on the application’s circuit; not the best example obviously). In other words, only a part of the whole thing is wrong.

• If one channel of our RGB color lamp is off by whatever value, at first glance the whole color might look wrong (because colors mix in our eyes/brains), but in fact it’s only one LED/bulb of the three that is actually wrong.

Don’t get me wrong, please. Of course, there is a difference between binary digits vs decimal digits vs hexadecimal digits. But again, isolated digits have no actual standalone meaning for things like brightness of a single color channels. On the other hand: if we consolidate the binary digits of a register of our microcontroller to dec or hex, even a single digit being off by a little will now also make a huge impact (on up to 4 pins!).
In the end it comes down to “atomic” unit we’re looking at. Like I wrote, if any of the (irrelevant) digits of the value of our color channel is wrong, the whole channel is wrong.

> (In 8th grade I took a 2 week summer school course in touch typing. The typewriters were mechanical monsters, you really had to hammer the keys to get it to work, but that helped build the muscle memory. Having a lifetime of payoff from that was soooo worth the few hours.)

Touch-type is useful to me, too :)
Learning to mentally translate hex to binary patterns isn’t, to be honest (at least yet; removing binary literals from D would introduce a potential use case).

If I were asked, hex numbers are only possibly nice for the first 4 bits; beyond these I have to keep track of the position as well. There we go: On the screen I could at least use a pointer pencil (if wanted). In my mind there is no such option.

Most of the time, when I’m working with binary data, individual binary digits (“bits”) of bytes don’t matter. Binary representation serves no purpose there. If it weren’t for control characters etc., ISO-8859-15 visualization would work for me as well…

Memorizing the 16 pattern HEX->BIN table doesn’t really help me with binary data retrieved from /dev/urandom or when mysql-native (MySQL/MariaDB client library) decides to return BINARY columns typed as strings. (In case someone wondered what binary data I mostly work with, ignoring media files.)

But if someone types "DDRB |= 144;" when programming my microcontroller, I’ll nervously get my calculator out ;)
September 11, 2022

On Saturday, 10 September 2022 at 05:40:49 UTC, Walter Bright wrote:

>

On 9/9/2022 7:45 PM, Nicholas Wilson wrote:

>

If you think binary literals are user unfriendly you're using them wrong.

Do you use them? :-)

Just searched my projects - I am in a few places, and I'm glad they're there. For goodness sake, please do not remove binary literals...

September 11, 2022
On Saturday, 10 September 2022 at 18:14:38 UTC, Walter Bright wrote:

>
> and you'll be doing a couple hundred of those at least. Wouldn't this be more appealing:
>
> "
>    .XXX.
>    X...X
>    XXXXX
>    X...X
>    X...X
> "

It probably would, but that's not our use case.

>
> ? Then write a trivial parser, and use CTFE to generate the binary data for the table. Of course, such a parser could be used over and over for other projects.

As I said, we could do it differently, but binary literals + comments are just optimal for our use case. There are other cases where we use them (in the definition of a binary protocol and in a few other places). We could but don't want to write a parser, translate into hex, etc. Replacing the literals with templates would be acceptable but annoying.
September 11, 2022
On Saturday, 10 September 2022 at 19:05:38 UTC, Don Allen wrote:
>
> I couldn't agree more with this. I've made it clear that I've done some very successful work with D and have been very pleased with the outcome. But this work involved porting C code I wrote 10 years ago that had become ugly (or maybe it always was) and difficult to maintain. The D version is a big improvement.

Removing the binary literals does not mean reduction in complexity, neither in the compiler, nor in the user code.