Power operator and replacement for E exponent notation

31 views
Skip to first unread message

James Harris

unread,
Nov 8, 2021, 2:46:37 PM11/8/21
to
Here's something a bit lighter than what we are discussing in other
threads - a nice, friendly syntax issue. :-)



Exponent notation
-----------------

For decades programming languages have used an 'E notation' to indicate
"times 10 to the power of" as in

1e3 1 times 10 to the power of 3
4.5e-2 4.5 times 10 to the power of -2

I think it goes back as far as Fortran and maybe even further into early
assembly languages but is it the best way?

I came up with (not implemented yet) something else. IMO it's better but
see what you think. I would express the above two numbers as

10^3 10 to the power of 3
4.5x10^-2 4.5 times 10 to the power of -2

(Yes, that's a lower-case x,)

Two advantages (AISI):

1. It looks closer to what a mathematician would write.

2. It includes the base so bases other than 10 would be possible, if
required, but the presence of the base is no impediment as even if it's
always 10 it helps make the number look more natural.




Power operator
--------------

The reason for bringing this up now is that in another thread we got on
to discussing a power operator. I was using ** such that "A squared"
would be

A ** 2

However, I am not sure that looks very consistent with the above
notation so I currently have "A squared" as

A ^ 2

That said, I am not going to use x as a multiplication sign so it's not
fully compatible.

What do you think would be best as a power operator? Or should power be
calculated by a function as in C?




Spaced out
----------

One thing I should mention that may be a bit controversial is that in
keeping with other operators space matters.

10^3

is a literal integer meaning 1000 whereas

10 ^ 3

is an expression which would evaluate to 1000. Space must be on both
sides of ^ or neither. Both of

10^ 3
10 ^3

would be invalid.




That's it. Two (or is it three?) issues. Feel free to comment on or
criticise any of them. I can take it!


--
James Harris

Bart

unread,
Nov 8, 2021, 3:04:22 PM11/8/21
to
On 08/11/2021 19:46, James Harris wrote:

> What do you think would be best as a power operator? Or should power be
> calculated by a function as in C?

Don't copy C.

It's pow() function works for one type at a time. You will need multiple
versions for different types, just like you have to with abs: abs()
labs(), llabs(), fabs(), fabs(). There are no versions of pow() for ints
that I'm aware of.

If you like 'pow', just use that with function-like syntax, but make it
overloaded like '+' and '*'.

For a symbolic operator, either ** or ^ is fine.

Dmitry A. Kazakov

unread,
Nov 8, 2021, 3:26:39 PM11/8/21
to
On 2021-11-08 20:46, James Harris wrote:

> For decades programming languages have used an 'E notation' to indicate
> "times 10 to the power of" as in
>
>   1e3      1 times 10 to the power of 3
>   4.5e-2   4.5 times 10 to the power of -2
>
> I think it goes back as far as Fortran and maybe even further into early
> assembly languages but is it the best way?

FORTRAN-IV did not have the first. Ada 83 had both.

> I came up with (not implemented yet) something else. IMO it's better but
> see what you think. I would express the above two numbers as
>
>   10^3         10 to the power of 3
>   4.5x10^-2    4.5 times 10 to the power of -2
>
> (Yes, that's a lower-case x,)

You can use the Unicode symbol ⋅ instead (U+22C5). There exists ⨯
(U+2A2F) too, but that is vector product.

> Two advantages (AISI):
>
> 1. It looks closer to what a mathematician would write.

In this case you must orient rather on physicists and chemists.

> 2. It includes the base so bases other than 10 would be possible, if
> required, but the presence of the base is no impediment as even if it's
> always 10 it helps make the number look more natural.

Just apply the base to the exponent as Ada does:

2#111#e7

means 5 * 2**7. That is why it is E and not 10 in Ada.

> One thing I should mention that may be a bit controversial is that in
> keeping with other operators space matters.
>
>   10^3
>
> is a literal integer meaning 1000 whereas
>
>   10 ^ 3

That would be an argument against using ^ for both. Note that the same
issue apply to unary - and +. This the reason why

+10

is not a literal in Ada, it is an expression.

Note also how this is connected to the approach to the types of the
literals. You need silly rules like below:

> is an expression which would evaluate to 1000. Space must be on both
> sides of ^ or neither. Both of
>
>   10^ 3
>   10 ^3
>
> would be invalid.

because you could not consistently fold constant expressions making all
cases equal. Ada has no such problem, e.g.

-32768

is perfectly OK for a 16-bit 2's complement integer regardless the fact
that the literal 32768 is out of the range.

Exponentiation would have the same problem as -, though much more
rarely, of course.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

James Harris

unread,
Nov 8, 2021, 3:52:03 PM11/8/21
to
On 08/11/2021 20:26, Dmitry A. Kazakov wrote:
> On 2021-11-08 20:46, James Harris wrote:

...

>>    10^3         10 to the power of 3
>>    4.5x10^-2    4.5 times 10 to the power of -2
>>
>> (Yes, that's a lower-case x,)
>
> You can use the Unicode symbol ⋅ instead (U+22C5). There exists ⨯
> (U+2A2F) too, but that is vector product.

Too much like APL!

>
>> Two advantages (AISI):
>>
>> 1. It looks closer to what a mathematician would write.
>
> In this case you must orient rather on physicists and chemists.

LOL! Why is that?

>
>> 2. It includes the base so bases other than 10 would be possible, if
>> required, but the presence of the base is no impediment as even if
>> it's always 10 it helps make the number look more natural.
>
> Just apply the base to the exponent as Ada does:
>
>    2#111#e7
>
> means 5 * 2**7. That is why it is E and not 10 in Ada.

I avoided mentioning numbers with different bases because it was too
much to show at once. Besides, it looked potentially confusing to have a
number base and an exponent base. But since you bring it up my notation
for that binary number is

2'111'x2^7


>
>> One thing I should mention that may be a bit controversial is that in
>> keeping with other operators space matters.
>>
>>    10^3
>>
>> is a literal integer meaning 1000 whereas
>>
>>    10 ^ 3
>
> That would be an argument against using ^ for both.

Opinion noted. It sounds as though you see no problem with having

10^3
10 ** 3

and that may make life simpler in some ways.


> Note that the same
> issue apply to unary - and +. This the reason why
>
>   +10
>
> is not a literal in Ada, it is an expression.

What's the problem?

FWIW I wanted to be able to write explicitly unsigned integer literals
and so use + as follows.

10 weak signed integer of value 10
-10 weak signed integer of value -10
+10 weak unsigned integer (of value 10)

>
> Note also how this is connected to the approach to the types of the
> literals. You need silly rules like below:
>
>> is an expression which would evaluate to 1000. Space must be on both
>> sides of ^ or neither. Both of
>>
>>    10^ 3
>>    10 ^3
>>
>> would be invalid.
>
> because you could not consistently fold constant expressions making all
> cases equal. Ada has no such problem, e.g.
>
>    -32768
>
> is perfectly OK for a 16-bit 2's complement integer regardless the fact
> that the literal 32768 is out of the range.
>
> Exponentiation would have the same problem as -, though much more
> rarely, of course.
>

Again, that sounds interesting but it appears to defy logic. What does
it mean?


--
James Harris

David Brown

unread,
Nov 8, 2021, 4:25:05 PM11/8/21
to
On 08/11/2021 21:04, Bart wrote:
> On 08/11/2021 19:46, James Harris wrote:
>
>> What do you think would be best as a power operator? Or should power
>> be calculated by a function as in C?
>
> Don't copy C.

I too think an operator would be nice.

>
> It's pow() function works for one type at a time. You will need multiple
> versions for different types, just like you have to with abs: abs()
> labs(), llabs(), fabs(), fabs().

Or if you live in this century, you use <tgmath.h> and it's all just
fabs(), pow(), etc., for any floating point types.

> There are no versions of pow() for ints
> that I'm aware of.

Not in the standard library, no. It has always struck me as an odd
omission (though I don't believe I have needed integer powers in my own
code, except for powers of 2).

>
> If you like 'pow', just use that with function-like syntax, but make it
> overloaded like '+' and '*'.

Yes, as it is in C (and C++). But go the whole way and cover integer
types as well as floating point types.

>
> For a symbolic operator, either ** or ^ is fine.
>

I think ** is the more common choice, especially if the language also
wants an operator for xor.

Bart

unread,
Nov 8, 2021, 4:27:29 PM11/8/21
to
On 08/11/2021 20:52, James Harris wrote:
> On 08/11/2021 20:26, Dmitry A. Kazakov wrote:

>> Just apply the base to the exponent as Ada does:
>>
>>     2#111#e7
>>
>> means 5 * 2**7. That is why it is E and not 10 in Ada.
>
> I avoided mentioning numbers with different bases because it was too
> much to show at once. Besides, it looked potentially confusing to have a
> number base and an exponent base. But since you bring it up my notation
> for that binary number is
>
>   2'111'x2^7

What /is/ the number? Is it 7 * 2**7 or 5 x 2**7? Having two 7s is
confusing!

Assuming it is the former, then the number is 896. (BTW my Casio uses ^
for 'to the power of'.)

I would write that entirely in base 2 as the single literal:

2x111e111

This yields 896.0, a float. But I can emulate your example:

2x111*2**7

in this case yielding an integer 896

Once again, don't copy C in this regard, where this:

0x100p10

is the literal 262144.0. This was a surprise to my, since when I write:

0x100p10

I get:

4722366482869645200000.0

Note that my literal is 100% hex, so 0x100p10 means:

256 * 16 ** 16

In C, 0x100p10 means:

256 * 2 * 10

So it's using 3 different bases: hex for the 0x100 part, base 2 (what
you raise to the power), and base 10 for the exponent!


David Brown

unread,
Nov 8, 2021, 4:37:21 PM11/8/21
to
On 08/11/2021 21:26, Dmitry A. Kazakov wrote:

> Just apply the base to the exponent as Ada does:
>
>    2#111#e7
>
> means 5 * 2**7. That is why it is E and not 10 in Ada.
>
(Surely you mean 7 * 2**7 ?)

Ada's system for non-decimal numbers has always struck me as flexible,
but possibly the ugliest and most difficult to read and write method I
have ever seen.

How often does anyone need a base other than 2, 10, or 16 ? If you are
into computer palaeontology, perhaps you also want octal - but that's
stretching things (I believe most cases of C octal constants, such as
0123, are mistakes - the programmer probably mean 123).

I have a hard time seeing how it would be possible to get something more
convenient and unambiguous than 123.6e5, 0xbeef, 0b1101. Other bases
don't turn up in real code, nor do floating point in anything other than
decimal. You'll want a digit separator, however - underscore is
probably the best choice.

(I'm omitting C's octals and hexadecimal floating point notations, and I
don't think the type suffixes are a good solution.)


Dmitry A. Kazakov

unread,
Nov 8, 2021, 4:39:50 PM11/8/21
to
On 2021-11-08 21:52, James Harris wrote:
> On 08/11/2021 20:26, Dmitry A. Kazakov wrote:
>> On 2021-11-08 20:46, James Harris wrote:

>> In this case you must orient rather on physicists and chemists.
>
> LOL! Why is that?

Who else would ever use such numbers? (:-)

>>> 2. It includes the base so bases other than 10 would be possible, if
>>> required, but the presence of the base is no impediment as even if
>>> it's always 10 it helps make the number look more natural.
>>
>> Just apply the base to the exponent as Ada does:
>>
>>     2#111#e7
>>
>> means 5 * 2**7. That is why it is E and not 10 in Ada.
>
> I avoided mentioning numbers with different bases because it was too
> much to show at once. Besides, it looked potentially confusing to have a
> number base and an exponent base. But since you bring it up my notation
> for that binary number is
>
>   2'111'x2^7

The point is that it does not make much sense to have the exponent
different from the base. The numeric model suggests that the exponent
shifts the mantissa by digits:

2#111#e2 = 2#11100#e0

>> Note that the same issue apply to unary - and +. This the reason why
>>
>>    +10

>> is not a literal in Ada, it is an expression.
>
> What's the problem?

You stated it yourself, the problem is with the blanks inside the literals:

+ // Children, let me tell you a wonderful story
//
// ...
//
// And they lived happily ever after.
10

> FWIW I wanted to be able to write explicitly unsigned integer literals
> and so use + as follows.
>
>   10   weak signed integer of value 10
>   -10  weak signed integer of value -10
>   +10  weak unsigned integer (of value 10)

A normal reader would expect +10 be signed because you specified that
damned sign!

But how would you explain a non-medicated person why

a-10

must be illegal?

> Again, that sounds interesting but it appears to defy logic. What does
> it mean?

It is quite logical to me that

-32768

and

- 32768

mean exactly same and the second would not suddenly overflow.

Bart

unread,
Nov 8, 2021, 4:56:47 PM11/8/21
to
On 08/11/2021 21:25, David Brown wrote:
> On 08/11/2021 21:04, Bart wrote:
>> On 08/11/2021 19:46, James Harris wrote:
>>
>>> What do you think would be best as a power operator? Or should power
>>> be calculated by a function as in C?
>>
>> Don't copy C.
>
> I too think an operator would be nice.
>
>>
>> It's pow() function works for one type at a time. You will need multiple
>> versions for different types, just like you have to with abs: abs()
>> labs(), llabs(), fabs(), fabs().
>
> Or if you live in this century, you use <tgmath.h> and it's all just
> fabs(), pow(), etc., for any floating point types.

If it's only for floats, how many are there? There's only float and
double unless you're interested in complex.

tgmath.h is anyway not universal. tcc doesn't have it. MSVC warns its
version is not compatible with C99 (possibly due to not have _Generic).
(You have to use ctgmath.h, for C++.)

So it's still messy, and not an approach to be copied.

Dmitry A. Kazakov

unread,
Nov 8, 2021, 4:57:06 PM11/8/21
to
On 2021-11-08 22:27, Bart wrote:
> On 08/11/2021 20:52, James Harris wrote:
>> On 08/11/2021 20:26, Dmitry A. Kazakov wrote:
>
>>> Just apply the base to the exponent as Ada does:
>>>
>>>     2#111#e7
>>>
>>> means 5 * 2**7. That is why it is E and not 10 in Ada.
>>
>> I avoided mentioning numbers with different bases because it was too
>> much to show at once. Besides, it looked potentially confusing to have
>> a number base and an exponent base. But since you bring it up my
>> notation for that binary number is
>>
>>    2'111'x2^7
>
> What /is/ the number? Is it 7 * 2**7 or 5 x 2**7? Having two 7s is
> confusing!

7 * 2**7. 5 was a typo error.

Dmitry A. Kazakov

unread,
Nov 8, 2021, 5:18:35 PM11/8/21
to
On 2021-11-08 22:37, David Brown wrote:
> On 08/11/2021 21:26, Dmitry A. Kazakov wrote:
>
>> Just apply the base to the exponent as Ada does:
>>
>>    2#111#e7
>>
>> means 5 * 2**7. That is why it is E and not 10 in Ada.
>>
> (Surely you mean 7 * 2**7 ?)

Yes.

> Ada's system for non-decimal numbers has always struck me as flexible,
> but possibly the ugliest and most difficult to read and write method I
> have ever seen.
>
> How often does anyone need a base other than 2, 10, or 16 ? If you are
> into computer palaeontology, perhaps you also want octal - but that's
> stretching things (I believe most cases of C octal constants, such as
> 0123, are mistakes - the programmer probably mean 123).
>
> I have a hard time seeing how it would be possible to get something more
> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101.

And how would by do:

16#0.FF03_8A90_FE1E#E-5

p instead of E looks totally out of place.

> Other bases
> don't turn up in real code, nor do floating point in anything other than
> decimal.

Maybe, but it is simpler to have them for the regularity sake.

> You'll want a digit separator, however - underscore is
> probably the best choice.

Yes, like in Ada.

> (I'm omitting C's octals and hexadecimal floating point notations, and I
> don't think the type suffixes are a good solution.)

A Unicode alternative would be using the mathematical notation for the base:

1101₂

Exponents would be superscript as James suggested:

0.FF03_8A90_FE1E₁ ₆16⁵

Not very readable in a fixed font.

P.S. I actually used such stuff in the UI, e.g. to annotate axes in
graphs and for measurement units. You really want to see m/s² rather
than m/(s^2) or whatever.

David Brown

unread,
Nov 8, 2021, 5:43:31 PM11/8/21
to
On 08/11/2021 22:56, Bart wrote:
> On 08/11/2021 21:25, David Brown wrote:
>> On 08/11/2021 21:04, Bart wrote:
>>> On 08/11/2021 19:46, James Harris wrote:
>>>
>>>> What do you think would be best as a power operator? Or should power
>>>> be calculated by a function as in C?
>>>
>>> Don't copy C.
>>
>> I too think an operator would be nice.
>>
>>>
>>> It's pow() function works for one type at a time. You will need multiple
>>> versions for different types, just like you have to with abs: abs()
>>> labs(), llabs(), fabs(), fabs().
>>
>> Or if you live in this century, you use <tgmath.h> and it's all just
>> fabs(), pow(), etc., for any floating point types.
>
> If it's only for floats, how many are there? There's only float and
> double unless you're interested in complex.

float, double, long double, float _Complex, double _Complex, long double
_Complex. The complex types are there, whether you are interested in
them or not.

(I prefer C++'s handling of complex numbers - it makes more sense to
have them as library classes than built-in language types.)

>
> tgmath.h is anyway not universal. tcc doesn't have it. MSVC warns its
> version is not compatible with C99 (possibly due to not have _Generic).
> (You have to use ctgmath.h, for C++.)

I have little interest in half-baked sort-of-C compilers. MSVC has
traditionally had terrible C support - perhaps because they want users
to think C is bad and choose lock-in C# instead. I have heard that the
more recent versions of MSVC are better, but have not tried them myself.

tcc is a toy - or, at best, a niche tool aimed at minimal size rather
than properly supporting C standards. tgmath.h is part of C99 - a
standard that is two decades old, and which has been superseded twice!
A toolchain that doesn't support it can't call itself C.

(<tgmath.h> precedes _Generic by over a decade. One of the motivations
for _Generic was to allow a <tgmath.h> implementation without needing
compiler extensions, but compilers had <tgmath.h> long before _Generic.)

And no, you don't need to use <ctgmath.h> in C++. In every C++
toolchain known to man, you can use <tgmath.h>. You can alternatively
use <ctgmath> - there is no ".h" in the C++ standard headers.

However, the normal C++ method is to include <cmath> and use overloaded
std::pow - the powf and powl (and similarly for fabs and all the others)
are only included for convenience of compatibility.

>
> So it's still messy, and not an approach to be copied.
>

Don't copy the implementation details from C - copy the user-level
usage. Have "pow" (and "abs", and the rest) as functions that can take
any arithmetic type and adapt to that type. It doesn't matter if this
is done by _Generic, compiler extensions, overloaded functions, function
templates, or whatever. (It should not, however, be done with built-in
functions or operators - these are library functions in any
well-designed language.)

David Brown

unread,
Nov 8, 2021, 5:56:35 PM11/8/21
to
On 08/11/2021 23:18, Dmitry A. Kazakov wrote:
> On 2021-11-08 22:37, David Brown wrote:
>> On 08/11/2021 21:26, Dmitry A. Kazakov wrote:
>>
>>> Just apply the base to the exponent as Ada does:
>>>
>>>     2#111#e7
>>>
>>> means 5 * 2**7. That is why it is E and not 10 in Ada.
>>>
>> (Surely you mean 7 * 2**7 ?)
>
> Yes.
>
>> Ada's system for non-decimal numbers has always struck me as flexible,
>> but possibly the ugliest and most difficult to read and write method I
>> have ever seen.
>>
>> How often does anyone need a base other than 2, 10, or 16 ?  If you are
>> into computer palaeontology, perhaps you also want octal - but that's
>> stretching things (I believe most cases of C octal constants, such as
>> 0123, are mistakes - the programmer probably mean 123).
>>
>> I have a hard time seeing how it would be possible to get something more
>> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101.
>
> And how would by do:
>
>    16#0.FF03_8A90_FE1E#E-5
>
> p instead of E looks totally out of place.

When would you ever need it? Who has /ever/ had need of writing a
hexadecimal fraction?

In C, you could have

(double) 0xff03'8a90'fe1e / 0x1'0000'0000'0000 / 0x10'0000

Yes, I'd write such a monstrosity using a normal hexadecimal number that
is then scaled. How I would write the scaling - dividing by separate
hex numbers, or by a (1ul << (48 + 20)), or something else, would depend
on the context. And I can't imagine any context where such a thing
would exist.


>
>> Other bases
>> don't turn up in real code, nor do floating point in anything other than
>> decimal.
>
> Maybe, but it is simpler to have them for the regularity sake.
>

Not if it means the common cases of binary and hex integers are so
hideous to work with. Have an extra mess to allow base 13 floating
point if you want, but don't drag binary and hex into it.

>> You'll want a digit separator, however - underscore is
>> probably the best choice.
>
> Yes, like in Ada.

Yes, I know. C++ could not use underscore, since that had another
meaning, so they picked ' (as used in a few countries). C is following
in the up-coming C23 standard.

>
>> (I'm omitting C's octals and hexadecimal floating point notations, and I
>> don't think the type suffixes are a good solution.)
>
> A Unicode alternative would be using the mathematical notation for the
> base:
>
>    1101₂

That would work, except that almost no one could type it. (Even on
*nix, few people have a compose key enabled, and few of them know that ₂
is compose + underscore + 2.)

>
> Exponents would be superscript as James suggested:
>
>    0.FF03_8A90_FE1E₁ ₆16⁵
>
> Not very readable in a fixed font.

Or writeable.

>
> P.S. I actually used such stuff in the UI, e.g. to annotate axes in
> graphs and for measurement units. You really want to see m/s² rather
> than m/(s^2) or whatever.
>

Unicode can be fine for text strings - I agree that ms⁻² or m/s² is
nice. But it is not a good choice for key parts of a language.

Bart

unread,
Nov 8, 2021, 6:52:38 PM11/8/21
to
On 08/11/2021 22:43, David Brown wrote:

> templates, or whatever. (It should not, however, be done with built-in
> functions or operators - these are library functions in any
> well-designed language.)

Why?

+ and * aren't usually library functions, what's special about **?

These operations are fundamental. My Casio calculator has dedicated
buttons for Abs, **, sqrt, square, log, sin and so on.

And what would you be missing out on if they /were/ built-in?

Anyone can add versions implemented via user-functions if they really
want; vice-versa is a little harder.


Dmitry A. Kazakov

unread,
Nov 9, 2021, 2:47:41 AM11/9/21
to
On 2021-11-08 23:56, David Brown wrote:
> On 08/11/2021 23:18, Dmitry A. Kazakov wrote:
>> On 2021-11-08 22:37, David Brown wrote:
>>> On 08/11/2021 21:26, Dmitry A. Kazakov wrote:
>>>
>>>> Just apply the base to the exponent as Ada does:
>>>>
>>>>     2#111#e7
>>>>
>>>> means 5 * 2**7. That is why it is E and not 10 in Ada.
>>>>
>>> (Surely you mean 7 * 2**7 ?)
>>
>> Yes.
>>
>>> Ada's system for non-decimal numbers has always struck me as flexible,
>>> but possibly the ugliest and most difficult to read and write method I
>>> have ever seen.
>>>
>>> How often does anyone need a base other than 2, 10, or 16 ?  If you are
>>> into computer palaeontology, perhaps you also want octal - but that's
>>> stretching things (I believe most cases of C octal constants, such as
>>> 0123, are mistakes - the programmer probably mean 123).
>>>
>>> I have a hard time seeing how it would be possible to get something more
>>> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101.
>>
>> And how would by do:
>>
>>    16#0.FF03_8A90_FE1E#E-5
>>
>> p instead of E looks totally out of place.
>
> When would you ever need it? Who has /ever/ had need of writing a
> hexadecimal fraction?

Rarely. One case I had was tabulating floating-point constants that need
to be exact. IEEE 754 would be binary, but I remember, some
floating-point formats used hexadecimal mantissa.

>>> Other bases
>>> don't turn up in real code, nor do floating point in anything other than
>>> decimal.
>>
>> Maybe, but it is simpler to have them for the regularity sake.
>
> Not if it means the common cases of binary and hex integers are so
> hideous to work with. Have an extra mess to allow base 13 floating
> point if you want, but don't drag binary and hex into it.

The beauty is in the eye of beholder. I find 0xFE hideous and illogical.

>> A Unicode alternative would be using the mathematical notation for the
>> base:
>>
>>    1101₂
>
> That would work, except that almost no one could type it. (Even on
> *nix, few people have a compose key enabled, and few of them know that ₂
> is compose + underscore + 2.)

Yes. I never managed to learn that trick. I open some Unicode HTTP page
or Windows Character Map and copy paste from there.

> Unicode can be fine for text strings - I agree that ms⁻² or m/s² is
> nice. But it is not a good choice for key parts of a language.

Yes. I am against Unicode in the programming language even in the string
literals.

James Harris

unread,
Nov 9, 2021, 3:15:01 AM11/9/21
to
On 08/11/2021 21:39, Dmitry A. Kazakov wrote:
> On 2021-11-08 21:52, James Harris wrote:

>>> In this case you must orient rather on physicists and chemists.
>>
>> LOL! Why is that?
>
> Who else would ever use such numbers? (:-)

:-)

...

> But how would you explain a non-medicated person why
>
>    a-10
>
> must be illegal?

If it's meant to be the name of an identifier it would presumably be
undeclared so the compiler would report it as such.

If, on the other hand, it's meant to be a subtraction but lacks required
whitespace the compiler could still report it. In fact, it would be easy
enough for the compiler to provide apropos hints to people coming from
other languages.


>
>> Again, that sounds interesting but it appears to defy logic. What does
>> it mean?
>
> It is quite logical to me that
>
>    -32768
>
> and
>
>    - 32768
>
> mean exactly same and the second would not suddenly overflow.
>

Didn't you say they were int 16s in which such a number would be invalid?


--
James Harris

James Harris

unread,
Nov 9, 2021, 3:23:16 AM11/9/21
to
On 08/11/2021 22:18, Dmitry A. Kazakov wrote:
> On 2021-11-08 22:37, David Brown wrote:

...

>> I have a hard time seeing how it would be possible to get something more
>> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101.
>
> And how would by do:
>
>    16#0.FF03_8A90_FE1E#E-5

FWIW my version of that would be similar:

16'0.FF03_8A90_FE1E'x16^-5

...

> A Unicode alternative would be using the mathematical notation for the
> base:
>
>    1101₂
>
> Exponents would be superscript as James suggested:
>
>    0.FF03_8A90_FE1E₁ ₆16⁵

I suggested an 'up arrow' but not a literal superscript. IMO all code
should be in universal old ASCII.


--
James Harris

Dmitry A. Kazakov

unread,
Nov 9, 2021, 4:00:14 AM11/9/21
to
On 2021-11-09 09:14, James Harris wrote:
> On 08/11/2021 21:39, Dmitry A. Kazakov wrote:
>> On 2021-11-08 21:52, James Harris wrote:
>
>> But how would you explain a non-medicated person why
>>
>>     a-10
>>
>> must be illegal?
>
> If it's meant to be the name of an identifier it would presumably be
> undeclared so the compiler would report it as such.
>
> If, on the other hand, it's meant to be a subtraction but lacks required
> whitespace the compiler could still report it. In fact, it would be easy
> enough for the compiler to provide apropos hints to people coming from
> other languages.

What kind of hints? I see two compelling alternatives:

1. Sorry guys, I could not do it right.

2. Piss off, moron!

(:-))

>>> Again, that sounds interesting but it appears to defy logic. What
>>> does it mean?
>>
>> It is quite logical to me that
>>
>>     -32768
>>
>> and
>>
>>     - 32768
>>
>> mean exactly same and the second would not suddenly overflow.
>
> Didn't you say they were int 16s in which such a number would be invalid?

But it would be valid, that is the whole point!

James Harris

unread,
Nov 9, 2021, 4:05:10 AM11/9/21
to
On 08/11/2021 21:37, David Brown wrote:
> On 08/11/2021 21:26, Dmitry A. Kazakov wrote:

...

> How often does anyone need a base other than 2, 10, or 16 ?

You mean you don't write out many gene sequences? ;-)

> If you are
> into computer palaeontology, perhaps you also want octal - but that's
> stretching things (I believe most cases of C octal constants, such as
> 0123, are mistakes - the programmer probably mean 123).

That problem wasn't in BCPL which allowed, AIUI, any of

#O100
#o100
#100

but the problem was introduced in B which had the rule: "An octal
constant is the same as a decimal constant except that it begins with a
zero".

It's curious as to how popular octal was back then that languages made
it the easiest to type.

>
> I have a hard time seeing how it would be possible to get something more
> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101.

If you are talking about C having those I am surprised to see the 0b
notation. When was it introduced?

It took me a long time and many iterations to come up with a good
notation for numbers in bases other than decimal (a case of lots of work
to make something that looks simple) but I am pleased with the result.
Your two non-decimals would be

0xbeef --> 16'beef'
0b1101 --> 2'1101'

IMO the result is logical, flexible and readable but YMMV. And, yes, it
uses underscore for digit separation.


> Other bases
> don't turn up in real code, nor do floating point in anything other than
> decimal. You'll want a digit separator, however - underscore is
> probably the best choice.
>
> (I'm omitting C's octals and hexadecimal floating point notations, and I
> don't think the type suffixes are a good solution.)

Agreed.


--
James Harris

James Harris

unread,
Nov 9, 2021, 4:29:21 AM11/9/21
to
On 09/11/2021 09:00, Dmitry A. Kazakov wrote:
> On 2021-11-09 09:14, James Harris wrote:
>> On 08/11/2021 21:39, Dmitry A. Kazakov wrote:
>>> On 2021-11-08 21:52, James Harris wrote:
>>
>>> But how would you explain a non-medicated person why
>>>
>>>     a-10
>>>
>>> must be illegal?
>>
>> If it's meant to be the name of an identifier it would presumably be
>> undeclared so the compiler would report it as such.
>>
>> If, on the other hand, it's meant to be a subtraction but lacks
>> required whitespace the compiler could still report it. In fact, it
>> would be easy enough for the compiler to provide apropos hints to
>> people coming from other languages.
>
> What kind of hints?

A standard error message followed by a hint for people coming from other
languages. For example, the report might be

Syntax error: invalid character ('-') in name
If you mean minus then remember to include space before and after


--
James Harris

James Harris

unread,
Nov 9, 2021, 4:35:13 AM11/9/21
to
On 09/11/2021 07:47, Dmitry A. Kazakov wrote:
> On 2021-11-08 23:56, David Brown wrote:
>> On 08/11/2021 23:18, Dmitry A. Kazakov wrote:
>>> On 2021-11-08 22:37, David Brown wrote:

...

>>>> Other bases
>>>> don't turn up in real code, nor do floating point in anything other
>>>> than
>>>> decimal.
>>>
>>> Maybe, but it is simpler to have them for the regularity sake.
>>
>> Not if it means the common cases of binary and hex integers are so
>> hideous to work with.  Have an extra mess to allow base 13 floating
>> point if you want, but don't drag binary and hex into it.
>
> The beauty is in the eye of beholder. I find 0xFE hideous and illogical.

You do? In Ada that's 16#FE#, isn't it, which surely looks worse.

...

> Yes. I am against Unicode in the programming language even in the string
> literals.

Definitely!


--
James Harris

David Brown

unread,
Nov 9, 2021, 6:05:07 AM11/9/21
to
On 09/11/2021 00:52, Bart wrote:
> On 08/11/2021 22:43, David Brown wrote:
>
>> templates, or whatever.  (It should not, however, be done with built-in
>> functions or operators - these are library functions in any
>> well-designed language.)
>
> Why?
>
> + and * aren't usually library functions, what's special about **?
>

"pow" could be an operator - that's not unreasonable. I really meant
the others maths functions.

> These operations are fundamental. My Casio calculator has dedicated
> buttons for Abs, **, sqrt, square, log, sin and so on.

We are discussing programming languages, not calculators.

>
> And what would you be missing out on if they /were/ built-in?
>
> Anyone can add versions implemented via user-functions if they really
> want; vice-versa is a little harder.
>
>

There are many reasons to choose to implement all the various
mathematical functions as library functions (preferably a language
standard library):

It keeps the language itself smaller, making it easier to document,
implement, use, and update.

It makes it easier to have alternative implementations of the functions
for different needs.

It makes it easier to add new functions.

It means you can have separate namespaces and not pollute the global
namespace with rarely-used keywords.

It makes it vastly easier to have different people implementing the
language, and mathematical functions.



Remember, your language is an oddity. It is a /personal/ language - it
makes no difference to you whether a feature is in the language, the
library, or the user code, because it is all part of the same soup.
That is not the case for most languages.


We are not living in the 1960's, trying to re-invent BASIC - nor in the
1970's re-inventing C.

A language for modern times needs namespaces, libraries or modules, a
way of defining simple functions that gives the compiler full insight
(like inline functions) to avoid function call overheads and to allow
extra knowledge, and a way of using a single function declaration with
multiple types, using either generic definitions or specialised definitions.

These are, I think, required features for a useful modern language. If
you don't have those, you might as well not bother (unless the language
is /very/ niche).

And once you have them, putting abs, log, sin, and anything else into a
library is easy.

You might even want to make operators fully programmable, and then
"power" can be an operator defined in the library.


Bart

unread,
Nov 9, 2021, 6:36:13 AM11/9/21
to
On 08/11/2021 21:37, David Brown wrote:
> On 08/11/2021 21:26, Dmitry A. Kazakov wrote:
>
>> Just apply the base to the exponent as Ada does:
>>
>>    2#111#e7
>>
>> means 5 * 2**7. That is why it is E and not 10 in Ada.
>>
> (Surely you mean 7 * 2**7 ?)
>
> Ada's system for non-decimal numbers has always struck me as flexible,
> but possibly the ugliest and most difficult to read and write method I
> have ever seen.
>
> How often does anyone need a base other than 2, 10, or 16 ?

You can have it for fun, or just for completeness:

println 0x100
println 2x100
println 4x100
println 5x100
println 6x100
println 7x100
println 8x100
println 9x100
println 10x100
println 11x100
println 12x100
println 13x100
println 14x100
println 15x100
println 16x100
println

println 0x100.1
println 2x100.1
println 4x100.1
println 5x100.1
println 6x100.1
println 7x100.1
println 8x100.1
println 9x100.1
println 10x100.1
println 11x100.1
println 12x100.1
println 13x100.1
println 14x100.1
println 15x100.1
println 16x100.1
println

static [2:]ichar bases = ("x2","x3","x4","x5","x6","x7","x8",
"x9","x10","x11","x12","x13","x14","x15","x16")
const n = u64.max

for i in bases.bounds do
fprintln "# in base # is #", n, i:"2", n:bases[i]
od

The above prints 100 interpreted as bases 2 to 16 (16 appears twice as
0x and 16x), then 100.1 in the same bases. Finally it displays the same
number in bases 2 to 16. Output is:

256
4
16
25
36
49
64
81
100
121
144
169
196
225
256

256.062500
4.500000
16.250000
25.200000
36.166667
49.142857
64.125000
81.111111
100.100000
121.090909
144.083333
169.076923
196.071429
225.066667
256.062500

18446744073709551615 in base 2 is
1111111111111111111111111111111111111111111111111111111111111111
18446744073709551615 in base 3 is 11112220022122120101211020120210210211220
18446744073709551615 in base 4 is 33333333333333333333333333333333
18446744073709551615 in base 5 is 2214220303114400424121122430
18446744073709551615 in base 6 is 3520522010102100444244423
18446744073709551615 in base 7 is 45012021522523134134601
18446744073709551615 in base 8 is 1777777777777777777777
18446744073709551615 in base 9 is 145808576354216723756
18446744073709551615 in base 10 is 18446744073709551615
18446744073709551615 in base 11 is 335500516A429071284
18446744073709551615 in base 12 is 839365134A2A240713
18446744073709551615 in base 13 is 219505A9511A867B72
18446744073709551615 in base 14 is 8681049ADB03DB171
18446744073709551615 in base 15 is 2C1D56B648C6CD110
18446744073709551615 in base 16 is FFFFFFFFFFFFFFFF

(I can't display floats in any base, because I for those I have a
dependency on C's sprintf.)

> If you are
> into computer palaeontology, perhaps you also want octal - but that's
> stretching things (I believe most cases of C octal constants, such as
> 0123, are mistakes - the programmer probably mean 123).
>
> I have a hard time seeing how it would be possible to get something more
> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101. Other bases
> don't turn up in real code,

I use base 1'000'000'000 in one of my libraries. But it doesn't have
language support!

James Harris

unread,
Nov 9, 2021, 6:47:18 AM11/9/21
to
On 09/11/2021 11:36, Bart wrote:
> On 08/11/2021 21:37, David Brown wrote:

...

>> I have a hard time seeing how it would be possible to get something more
>> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101.  Other bases
>> don't turn up in real code,
>
> I use base 1'000'000'000 in one of my libraries. But it doesn't have
> language support!
>

And you would want to write constants in that base...?!


--
James Harris

Bart

unread,
Nov 9, 2021, 7:12:15 AM11/9/21
to
On 09/11/2021 11:05, David Brown wrote:
> On 09/11/2021 00:52, Bart wrote:
>> On 08/11/2021 22:43, David Brown wrote:
>>
>>> templates, or whatever.  (It should not, however, be done with built-in
>>> functions or operators - these are library functions in any
>>> well-designed language.)
>>
>> Why?
>>
>> + and * aren't usually library functions, what's special about **?
>>
>
> "pow" could be an operator - that's not unreasonable. I really meant
> the others maths functions.
>
>> These operations are fundamental. My Casio calculator has dedicated
>> buttons for Abs, **, sqrt, square, log, sin and so on.
>
> We are discussing programming languages, not calculators.

You're missing the point of the calculator: there are limited number of
dedicated buttons, but they decided Abs etc were fundamental enough to
have their own button.

Similar to how I decided they were fundamental enough to be
dedicated built-in operators.


>
>>
>> And what would you be missing out on if they /were/ built-in?
>>
>> Anyone can add versions implemented via user-functions if they really
>> want; vice-versa is a little harder.
>>
>>
>
> There are many reasons to choose to implement all the various
> mathematical functions as library functions (preferably a language
> standard library):
>
> It keeps the language itself smaller, making it easier to document,
> implement, use, and update.

Why is that important, considering that adding those built-ins amounts
to a few 10s of KB, but typical implementations run to 10s or 100s of MB?

Since the language needs those functions, it still needs to add them but
now needs headers, templates, generics, ... a whole raft of machinery.

And for the user? They have to muck around doing stuff like this:

#include <tgmath.h> // for fabs
#include <stdlib.b> // for abs, labs, llabs

Then need to decide exactly which alternate to apply, and then, if a
type T changes from int to long int, change 100 instances of abs to labs.

I think I'll stick with my approach, thanks.


> A language for modern times needs namespaces, libraries or modules,

Namespaces: check

Libraries: check (even if rather meagre ATM)

Modules: check


> a
> way of defining simple functions that gives the compiler full insight
> (like inline functions) to avoid function call overheads and to allow
> extra knowledge,

Whole program compilation: check (but not taking advantage yet)

> and a way of using a single function declaration with
> multiple types, using either generic definitions or specialised definitions.

Generics: [pause to switch to my dynamic language] check

> These are, I think, required features for a useful modern language. If
> you don't have those, you might as well not bother (unless the language
> is /very/ niche).
>
> And once you have them, putting abs, log, sin, and anything else into a
> library is easy.

With the library again! I've had abs, log, sin etc as builtins since the
early 80s. That was when I had to implement float arithmetic in
software. Now that /was/ a library, but used to transparently support
A+B*C in the language, just like I do now with sin etc.

Since my compilers have always had poor optimisers, the advantage of a
built-in is that it makes it easier to generate inline code, rather than
have to try and inline a function. Which would anyway take extra resources.

So if I now do:

real x, y
y := abs(x)

The IR is:

push x r64
abs r64
pop y r64

And the x64 code is:

mov xmm4, R.x # R.x R.y are xmm registers
andpd xmm4, [...]
mov R.y, xmm54

(This could be optimised better to two instructions)




> You might even want to make operators fully programmable, and then
> "power" can be an operator defined in the library.


And again! You've been coding in C too long. I bet that if C had had
'pow' as a built-in operator from the start, then you would have a
different view now.

Bart

unread,
Nov 9, 2021, 7:19:16 AM11/9/21
to
It's not hard actually, as a single digit is written as a base-10 number
from 000000000 to 999999999; leading zeros are needed except for the
first digit.

Constants tend to be long (for my bignum library) so are handled as
strings. But they don't look any different from normal decimal:

123456789876543210

This is two digits 123456789'876543210, and has a value identical to the
base-10 version.

David Brown

unread,
Nov 9, 2021, 8:02:07 AM11/9/21
to
On 09/11/2021 13:12, Bart wrote:
> On 09/11/2021 11:05, David Brown wrote:
>> On 09/11/2021 00:52, Bart wrote:
>>> On 08/11/2021 22:43, David Brown wrote:
>>>
>>>> templates, or whatever.  (It should not, however, be done with built-in
>>>> functions or operators - these are library functions in any
>>>> well-designed language.)
>>>
>>> Why?
>>>
>>> + and * aren't usually library functions, what's special about **?
>>>
>>
>> "pow" could be an operator - that's not unreasonable.  I really meant
>> the others maths functions.
>>
>>> These operations are fundamental. My Casio calculator has dedicated
>>> buttons for Abs, **, sqrt, square, log, sin and so on.
>>
>> We are discussing programming languages, not calculators.
>
> You're missing the point of the calculator: there are limited number of
> dedicated buttons, but they decided Abs etc were fundamental enough to
> have their own button.
>

It is a /calculator/. Either it is a dedicated function on a button, or
it doesn't happen. It is not a programming language! You might as well
try to tell us that "purple" is a "fundamental colour" because you have
a purple crayon in your pencil case.

> Similar to how I decided they were fundamental enough to be
> dedicated built-in operators.
>
>
>>
>>>
>>> And what would you be missing out on if they /were/ built-in?
>>>
>>> Anyone can add versions implemented via user-functions if they really
>>> want; vice-versa is a little harder.
>>>
>>>
>>
>> There are many reasons to choose to implement all the various
>> mathematical functions as library functions (preferably a language
>> standard library):
>>
>> It keeps the language itself smaller, making it easier to document,
>> implement, use, and update.
>
> Why is that important, considering that adding those built-ins amounts
> to a few 10s of KB, but typical implementations run to 10s or 100s of MB?
>

It probably isn't important to you in your language - things like
documentation, specification, standards, updates, versions, consistency,
compatibility, maintainability, cooperation, are all pretty minor
concepts. It's a different matter for languages with an ambition
greater than one person.

> Since the language needs those functions, it still needs to add them but
> now needs headers, templates, generics, ... a whole raft of machinery.

Any serious language needs something on those lines. If you want BASIC,
you know where to find it.

>
> And for the user? They have to muck around doing stuff like this:
>
>   #include <tgmath.h>        // for fabs
>   #include <stdlib.b>        // for abs, labs, llabs
>
> Then need to decide exactly which alternate to apply, and then, if a
> type T changes from int to long int, change 100 instances of abs to labs.
>
> I think I'll stick with my approach, thanks.
>

And you'll continue to wonder why people don't take you seriously
whenever you discuss your language.

>
>> A language for modern times needs namespaces, libraries or modules,
>
> Namespaces: check
>
> Libraries: check (even if rather meagre ATM)
>
> Modules: check
>
>
>> a
>> way of defining simple functions that gives the compiler full insight
>> (like inline functions) to avoid function call overheads and to allow
>> extra knowledge,
>
> Whole program compilation: check (but not taking advantage yet)
>
>> and a way of using a single function declaration with
>> multiple types, using either generic definitions or specialised
>> definitions.
>
> Generics: [pause to switch to my dynamic language] check
>

An unwillingness to use your own features: check
I code in many languages. Drag yourself out of your ancient history,
and you'll maybe see it makes little sense to put everything into one
pot. A good language design has the building blocks in the language
itself, and everything else in libraries. Look at Ada - it doesn't
really have much in the way of fundamental types, but provides a way to
make the types you need. That makes it more flexible and powerful than
languages with fixed integer types.

David Brown

unread,
Nov 9, 2021, 8:58:11 AM11/9/21
to
On 09/11/2021 10:05, James Harris wrote:
> On 08/11/2021 21:37, David Brown wrote:
>> On 08/11/2021 21:26, Dmitry A. Kazakov wrote:
>
> ...
>
>> How often does anyone need a base other than 2, 10, or 16 ?
>
> You mean you don't write out many gene sequences? ;-)

Not often, no. But if I did, I'd use the letters C, G, A and T, just
like any biologist, and not base 4 digits 0 to 3. And you'd want a long
string of the "digits", not an integer.

That's the point here. It's not that there are no uses for other bases
- base 4 can be used in genetics, as can base 64 (three nucleotides
combined into codons). Base 64 is used for encoding binary files as
email attachments, and plenty of other bases (including weird ones) are
used in electronics, mathematics, and other fields. But you don't write
out numbers in those bases - certainly not floating point numbers.

>
>> If you are
>> into computer palaeontology, perhaps you also want octal - but that's
>> stretching things (I believe most cases of C octal constants, such as
>> 0123, are mistakes - the programmer probably mean 123).
>
> That problem wasn't in BCPL which allowed, AIUI, any of
>
>   #O100
>   #o100
>   #100
>
> but the problem was introduced in B which had the rule: "An octal
> constant is the same as a decimal constant except that it begins with a
> zero".
>

I haven't used B, and don't know all the history, but that's the rule C
inherited.

> It's curious as to how popular octal was back then that languages made
> it the easiest to type.
>

Octal was more popular in the days before the computing world
standardised on 8-bit bytes (except in niche DSP systems). It was used
on systems that had 6-bit units for holding a character, and for some
other situations where three-bit grouping makes sense (most notably,
POSIX file permissions). The most common way to write octal in modern
languages seems to be 0o123, which works okay as long as people don't
insist on using capitals.

>>
>> I have a hard time seeing how it would be possible to get something more
>> convenient and unambiguous than 123.6e5, 0xbeef, 0b1101. 
>
> If you are talking about C having those I am surprised to see the 0b
> notation. When was it introduced?
>

In C23 :-) Okay, 0b integer constants are not yet part of standard C,
but they are included in the current plans for the next standard
(planned for 2023). They have been in C++ since C++14, and have been
supported by many compilers in C and C++ for a lot longer than that.

> It took me a long time and many iterations to come up with a good
> notation for numbers in bases other than decimal (a case of lots of work
> to make something that looks simple) but I am pleased with the result.
> Your two non-decimals would be
>
>   0xbeef  -->  16'beef'
>   0b1101  -->  2'1101'
>
> IMO the result is logical, flexible and readable but YMMV. And, yes, it
> uses underscore for digit separation.
>

It's okay - it's better than Ada, IMHO, since the apostrophe is not as
dense a character as the hash in Ada. I'm not convinced that it is
worth having something different from other languages in order to
support bases that no one will ever use, but it's quite clear and readable.

Bart

unread,
Nov 9, 2021, 9:18:07 AM11/9/21
to
On 09/11/2021 13:02, David Brown wrote:
> On 09/11/2021 13:12, Bart wrote:

>> You're missing the point of the calculator: there are limited number of
>> dedicated buttons, but they decided Abs etc were fundamental enough to
>> have their own button.
>>
>
> It is a /calculator/. Either it is a dedicated function on a button, or
> it doesn't happen. It is not a programming language!

I'm looking at a picture of a HP programmable calculator.

It still appears to have dedicated buttons for many of the operators
that I build in to my languages, although some will be shifted.

Including ABS.

Now, why would that be? Probably for the same reasons I make those
common functions built-in to my language.

(https://upload.wikimedia.org/wikipedia/commons/9/9c/Hp35s_Calculator.jpg)

> You might as well
> try to tell us that "purple" is a "fundamental colour" because you have
> a purple crayon in your pencil case.

It /is/ a common colour name, example:

global tabledata() colournames, colourvalues =
! BB'GG'RR
....
(purple, $, 0x_5E'0D'73),
....


This is from a list of 60 named colours, and of a possible 16777216.

It's for convenience, unless you want everyone was to define their own
versions of Black and White using 0x000000 and 0xFFFFFF.

>> Generics: [pause to switch to my dynamic language] check
>>
>
> An unwillingness to use your own features: check

The generics in that dynamic language is for user-code.

Since it also interpreted, it would be crazy to implement basic language
operations as interpreted bytecode. Ones like ABS have a dedicated
bytecode instruction, because it makes sense to execute one instruction
instead of half a dozen.

>> And again! You've been coding in C too long. I bet that if C had had
>> 'pow' as a built-in operator from the start, then you would have a
>> different view now.
>
> I code in many languages.

Which have likely all been influenced by C.

However even Python ranks 'abs' above 'sqrt', since you don't need to
import anything in order to use abs. Although it doesn't stop you doing:

abs = 42

or:

abs = math.sqrt

Yeah, this is the drawback of my approach; it's harder to write nonsense!


> Drag yourself out of your ancient history,

I'm not as deeply mired in it as you are. You're still using C for a start.


> and you'll maybe see it makes little sense to put everything into one
> pot.

I put the basics into one convenient place, instead of having to chase
headers and imports to provide 'sqrt'.

A good language design has the building blocks in the language
> itself, and everything else in libraries.

That is one approach that many think is a good idea. That way you that
can end up with monstrosities like C++ that are impossible for any one
person to fully understand, and that take forever to compile and with
incomprehensible error messages.

I decided not to go down that route...

Language-building features and metaprogramming, I'm just not into. Other
people who make their own personal languages can implement their own
preferences.


Look at Ada - it doesn't
> really have much in the way of fundamental types, but provides a way to
> make the types you need. That makes it more flexible and powerful than
> languages with fixed integer types.


Yeah. It makes it so easy to use....

Again, I'm not reimplementating Ada.

Dmitry A. Kazakov

unread,
Nov 9, 2021, 10:28:23 AM11/9/21
to
On 2021-11-09 14:58, David Brown wrote:

> It's okay - it's better than Ada, IMHO, since the apostrophe is not as
> dense a character as the hash in Ada.

In Ada you can use colon (:) instead of #. Colon is a replacement
character for # and ! is a replacement for |.

Apparently, for the case somebody had chopped off parts of your
teletype... (:-))

There are funny stories of people using the standard input library to
parse something like:

4:4:6

They get mighty surprised as nobody remembers about the replacement
characters... (:-))

David Brown

unread,
Nov 9, 2021, 10:31:02 AM11/9/21
to
On 09/11/2021 15:18, Bart wrote:

>
> Again, I'm not reimplementating Ada.
>

No, you are not. Ada is a language lots of people use. Your languages
have one aim, and one aim only - to be languages that suit /you/. (I'm
not saying that they are necessarily bad, either in their entirety or in
particular features - merely that things you think work well in those
languages can't be assumed to work for more generally useful languages.)

But really, this thread is not about what /you/ use for your old
languages designed in the 80's using ideas from the 60's. It is about
what makes sense for James to use in his language, or what other people
think might be good in other languages.

Bart

unread,
Nov 9, 2021, 12:28:19 PM11/9/21
to
On 09/11/2021 15:31, David Brown wrote:
> On 09/11/2021 15:18, Bart wrote:
>
>>
>> Again, I'm not reimplementating Ada.
>>
>
> No, you are not. Ada is a language lots of people use. Your languages
> have one aim, and one aim only - to be languages that suit /you/.

Actually, lots of people could use my language designs too. They just
need a decent implementation.

With C, lots of people have put in that work (it must be the most
implemented language on the planet).

Now you might want to tell me why my way of making available **, sqrt
and sin is completely unsuitable for EVERYONE except me. I don't get it.

Come on, what would they be missing out on if my way wasn't just a copy
of how C does everything.

(Which BTW is a sham; gcc compiling C treats abs etc as though they are
built-ins just like mine.

It knows the advantages that my approach brings, such as being able
reduce constant expressions involving those ops. But it still has to
work within C's ancient framework, so it has to make a show of them
being user-functions and allow people to override them with their own
versions.)



> But really, this thread is not about what /you/ use for your old
> languages designed in the 80's using ideas from the 60's.

> It is about
> what makes sense for James to use in his language, or what other people
> think might be good in other languages.

OK, so your idea is for:

* The language to know NOTHING about abs, sqrt, sin etc

* They should be user-functions like any other, which just reside in
some standard library

* The language needs to acquire function overloading, or some generic
features, to make those functions work on different types

* The language possibly needs an inline assembler so that those
functions can be implemented efficiently where there are special
instructions available

* The language needs advanced optimisation methods, link-time optimising
etc so that the code for some of these function can be inlined

* The language needs even more advanced techniques such as C++'s
constexpr, so that constant expressions involving abs, sqrt etc can be
reduced to a constant value

This is the big new idea which is better than my '1980s' language, which
is so easy to implement.

James can make up his own mind of course. My suggestion is to make a lot
of these built-ins, so that those big features above are not essential
just to get sqrt working.

Dmitry A. Kazakov

unread,
Nov 9, 2021, 12:57:38 PM11/9/21
to
On 2021-11-09 18:28, Bart wrote:

> This is the big new idea which is better than my '1980s' language, which
> is so easy to implement.

You know what? Ford model T is pretty easy to build. Would you start
building such cars to compete with Elon?

There are certain expectations people have buying a car today. The same
is true for programming languages. You could move a bit in this or that
direction, favor this or that programming paradigm, but there is not
much freedom.

P.S. People telling you that your language is 80's are shameless
flatterers... (:-))

Bart

unread,
Nov 9, 2021, 1:33:20 PM11/9/21
to
On 09/11/2021 17:57, Dmitry A. Kazakov wrote:
> On 2021-11-09 18:28, Bart wrote:
>
>> This is the big new idea which is better than my '1980s' language,
>> which is so easy to implement.

You misunderstood; it is that big list of major language features which
I sarcastically said was so easy.

Adding a dozen built-on ops: about a days's work.

Adding the ability to define those via user-code, and make them
transparently work as though they were built-in: at least a year's work.

He doesn't appreciate that point because teams of other people have
spent decades making that possible in the big tool-sets that he favours.


> You know what? Ford model T is pretty easy to build. Would you start
> building such cars to compete with Elon?

That's apparently what David Brown wants!

The Model T was famous for nearly everthing being an accessory that you
had to buy separately, even things that are a legal necessity now.


> There are certain expectations people have buying a car today.

My 1980s car would have lights, mirrors, fuel guage, speedometer etc.
all built-in and not user-modifiable.

DB says that is no good; why not?

The same
> is true for programming languages.

DB hasn't answered yet, perhaps you can: what exactly is the problem
with having SQRT, say, as a built-in function or operator in a language?

Someone give me a convincing answer, and I will change my
implementation, provided it doesn't involve reimplementing the whole of
C++, and making my build-times 100 times slower.

Bart

unread,
Nov 9, 2021, 2:14:01 PM11/9/21
to
On 08/11/2021 22:43, David Brown wrote:
> On 08/11/2021 22:56, Bart wrote:

>> tgmath.h is anyway not universal. tcc doesn't have it. MSVC warns its
>> version is not compatible with C99 (possibly due to not have _Generic).
>> (You have to use ctgmath.h, for C++.)
>
> I have little interest in half-baked sort-of-C compilers. MSVC has
> traditionally had terrible C support

So, MSVC doesn't count.

> - perhaps because they want users
> to think C is bad and choose lock-in C# instead. I have heard that the
> more recent versions of MSVC are better, but have not tried them myself.
>
> tcc is a toy

So, tcc doesn't count.

(And it's definitely not a toy - try writing something half as good. It
turns working C code into executable binary code that runs at half the
speed of -O3.

But it checks fewer things, and has the odd thing missing - like
tgmath.h. For building debugged code and doing it quickly, it is does
that job well.)

I've just now tried Clang. That is, Clang running on Windows, part of an
large LLVM installation, and with links into MSBUILD tools.

With this program:

#include <tgmath.h>

It gives 20 errors before it give up.

I guess, Clang doesn't count either! Apparently the only one that counts
is yours.

Somehow I don't get the impression that C has solved the problem of
overloading pow(), even for the two float types that most people use.

But you seem to like blaming implementations and OSes instead of blaming
the language.

Mine runs on Windows and yet overloaded ** runs fine.

Dmitry A. Kazakov

unread,
Nov 9, 2021, 3:59:55 PM11/9/21
to
On 2021-11-09 19:33, Bart wrote:

> DB hasn't answered yet, perhaps you can: what exactly is the problem
> with having SQRT, say, as a built-in function or operator in a language?

Occam's Razor and you cannot really have it.

You can have an operator with the name sqrt, but you cannot have sqrt
itself. Would you implement matrix sqrt for all possible combinations of
matrix index and matrix elements? Complex sqrt with two branches? There
are thousands of different sqrt's, there are specialized low accuracy
variants for graphic rendering, the number of variants is basically
infinite.

> Someone give me a convincing answer, and I will change my
> implementation, provided it doesn't involve reimplementing the whole of
> C++, and making my build-times 100 times slower.

Unfortunately it does involve more or less whole C++ or an equivalent in
terms of the elaborated type system and generic/OO programming support
to keep sqrt-stuff out of the language in the libraries. [C++ is not
that bad, it made some poor choices, especially regarding safety, but
its type system is very powerful.]

It is interesting to monitor evolution of new languages. They all start
"small" and if successful end up as a huge pile of assorted
half-digested manure.

Bart

unread,
Nov 9, 2021, 4:45:29 PM11/9/21
to
On 09/11/2021 20:59, Dmitry A. Kazakov wrote:
> On 2021-11-09 19:33, Bart wrote:
>
>> DB hasn't answered yet, perhaps you can: what exactly is the problem
>> with having SQRT, say, as a built-in function or operator in a language?
>
> Occam's Razor and you cannot really have it.
>
> You can have an operator with the name sqrt, but you cannot have sqrt
> itself. Would you implement matrix sqrt for all possible combinations of
> matrix index and matrix elements? Complex sqrt with two branches? There
> are thousands of different sqrt's, there are specialized low accuracy
> variants for graphic rendering, the number of variants is basically
> infinite

You can make the same remarks about multiply:

* It can apply to matrices (more elaborate than sqrt since they can be
different sizes)

* You may want low accuracy versions of the same type

* It can apply to complex numbers

* Actually it can also apply (and does in my case) to list*number,
string*number, set*set, bignum*bignum, and (in one old language)
vector*vector (cross-product)

And yet, most languages manage to have a version of multiply built-in
that works on its built-in numeric types.

How is that possible, given the vast number of possibilities that remain
unimplemented?

But apparently it is. So tell me again why a language can't do the same
with Sqrt?

Dmitry A. Kazakov

unread,
Nov 10, 2021, 2:24:36 AM11/10/21
to
On 2021-11-09 22:45, Bart wrote:
> On 09/11/2021 20:59, Dmitry A. Kazakov wrote:
>> On 2021-11-09 19:33, Bart wrote:
>>
>>> DB hasn't answered yet, perhaps you can: what exactly is the problem
>>> with having SQRT, say, as a built-in function or operator in a language?
>>
>> Occam's Razor and you cannot really have it.
>>
>> You can have an operator with the name sqrt, but you cannot have sqrt
>> itself. Would you implement matrix sqrt for all possible combinations
>> of matrix index and matrix elements? Complex sqrt with two branches?
>> There are thousands of different sqrt's, there are specialized low
>> accuracy variants for graphic rendering, the number of variants is
>> basically infinite
>
> You can make the same remarks about multiply:

Yes, but multiplication is much easier to implement and you cannot do
much without it. It is a fundamental operation.

P.S. I remember that some early IBM machines did not have multiplication
and division.

James Harris

unread,
Nov 10, 2021, 2:46:02 AM11/10/21
to
On 09/11/2021 15:31, David Brown wrote:
> On 09/11/2021 15:18, Bart wrote:
>
>>
>> Again, I'm not reimplementating Ada.

...

> But really, this thread is not about what /you/ use for your old
> languages designed in the 80's using ideas from the 60's. It is about
> what makes sense for James to use in his language, or what other people
> think might be good in other languages.

It's kind of you to put it that way but surely these discussions are for
anyone to benefit from in any way that suits him. I find them helpful
for the language I am working on, for sure, but I suspect that lots of
others benefit, even some who don't post often or at all.

In fact, despite the lack of security with Usenet (leading to spam) and
there being other online fora this is the best place I've found on the
Internet to discuss language design and related issues.

One thing that could make it easier to follow, perhaps, is if people are
going to bring up a significant topic they do so in a new thread rather
than a reply - though of course it's not always easy to determine when a
topic will lead to a long discussion!


--
James Harris

David Brown

unread,
Nov 10, 2021, 6:00:16 AM11/10/21
to
On 09/11/2021 18:28, Bart wrote:
> On 09/11/2021 15:31, David Brown wrote:
>> On 09/11/2021 15:18, Bart wrote:
>>
>>>
>>> Again, I'm not reimplementating Ada.
>>>
>>
>> No, you are not.  Ada is a language lots of people use.  Your languages
>> have one aim, and one aim only - to be languages that suit /you/.
>
> Actually, lots of people could use my language designs too. They just
> need a decent implementation.
>
> With C, lots of people have put in that work (it must be the most
> implemented language on the planet).
>
> Now you might want to tell me why my way of making available **, sqrt
> and sin is completely unsuitable for EVERYONE except me. I don't get it.

It is unsuitable as a way of designing a language. For /users/ of a
language, it usually makes little difference if "abs" is a built-in
function or a library function. For people involved in implementing,
porting, expanding, documenting, standardising, testing, it is a very
different matter.

You seem to have a serious aversion to all kinds of structure and
modularisation. I don't know why - perhaps it is a background in
assembly programming where everything is held at very flat levels.
(Though I have done far more than my fair share of assembly, and also of
C programming which is relatively flat in comparison to more modern
languages, and I don't suffer from the same problem.) Maybe you are
just used to working on your own, doing everything yourself.

Whatever it is, you prefer to have everything together in one lump. For
a little system with few users, that might be okay - interfaces and
separations between parts can lead to inefficiencies, and can be more
effort to develop if the alternative is small enough to be made by a
single person.

>
> Come on, what would they be missing out on if my way wasn't just a copy
> of how C does everything.
>
> (Which BTW is a sham; gcc compiling C treats abs etc as though they are
> built-ins just like mine.
>

Advanced C implementations can have features to help get more efficient
results.

However, no matter how often you claim I am recommending "make it like
C", I am very specifically /not/ recommending making a language like C.
If nothing else, it would be a pointless exercise - no one is going to
make something that is "mostly like C" but has enough advantages to
outweigh the advantages of the existing mass of C code, C tools, and C
knowledge.

I suppose I could explain /again/, but would you listen this time?


> It knows the advantages that my approach brings, such as being able
> reduce constant expressions involving those ops. But it still has to
> work within C's ancient framework, so it has to make a show of them
> being user-functions and allow people to override them with their own
> versions.)
>

That is not an advantage you get from having these functions built into
the language - even in C there is no problem optimising maths functions.
And with /better/ facilities (remember, I am not recommending copying
C), you can get all the optimisation you want while having these
functions defined outside the base language. (Again, I could explain if
I thought you would listen.)

>
>
>> But really, this thread is not about what /you/ use for your old
>> languages designed in the 80's using ideas from the 60's.
>
>> It is about
>> what makes sense for James to use in his language, or what other people
>> think might be good in other languages.
>
> OK, so your idea is for:
>
> * The language to know NOTHING about abs, sqrt, sin etc
>

Yes.

> * They should be user-functions like any other, which just reside in
> some standard library
>

Yes. You seem to think this means dumbing down these functions, making
them less efficient or stopping them being usable at compile time. I
think it means making the language better so that /any/ such functions
can be implemented with maximal efficiency and usability by using the
language. If the language itself is not good enough to implement "abs"
or "sin" as efficiently and flexibly as you could achieve with a
built-in function, then the language is not good enough.

> * The language needs to acquire function overloading, or some generic
> features, to make those functions work on different types
>

No - the language should not need to "acquire" anything. Unless you are
talking about a small scripting language or other niche language, if it
can't handle generic or templated code, there's no point in creating it
in the first place. (Well, fun or learning is always a good reason, but
then none of this matters.)

> * The language possibly needs an inline assembler so that those
> functions can be implemented efficiently where there are special
> instructions available
>

Yes, that is reasonable if the language is to be low-level and efficient.

> * The language needs advanced optimisation methods, link-time optimising
> etc so that the code for some of these function can be inlined
>

I thought we were talking about languages that could have efficient code
generation anyway. Was that wrong?

There is no need for link-time optimisation for inlining code. Or did
you think "library" meant nothing more than a collection of
assembly-level entry point symbols with opaque object code requiring
full ABI-compliant function calls?

> * The language needs even more advanced techniques such as C++'s
> constexpr, so that constant expressions involving abs, sqrt etc can be
> reduced to a constant value
>

C++'s "constexpr" is only needed because the rules and features for
constants and compile-time evaluation were modified and enhanced over
time while maintaining backwards compatibility. That is not an issue
for a new language.

> This is the big new idea which is better than my '1980s' language, which
> is so easy to implement.
>

A BASIC-like language is not too hard to implement (though certainly not
trivial, especially if you insist on implementing it without using
higher level languages or ready-made tools) - but what is the point,
except for fun and learning?

> James can make up his own mind of course. My suggestion is to make a lot
> of these built-ins, so that those big features above are not essential
> just to get sqrt working.

Of course James will have to make up his own mind. (Or, true to form,
will continue discussing the language for decades to come. But these
are sometimes interesting discussions.)

Being able to find square roots is irrelevant for most programs, and no
one will miss an "abs" function - it is the features of the language
that are important.

David Brown

unread,
Nov 10, 2021, 7:03:43 AM11/10/21
to
On 09/11/2021 20:14, Bart wrote:
> On 08/11/2021 22:43, David Brown wrote:
>> On 08/11/2021 22:56, Bart wrote:
>
>>> tgmath.h is anyway not universal. tcc doesn't have it. MSVC warns its
>>> version is not compatible with C99 (possibly due to not have _Generic).
>>> (You have to use ctgmath.h, for C++.)
>>
>> I have little interest in half-baked sort-of-C compilers.  MSVC has
>> traditionally had terrible C support
>
> So, MSVC doesn't count.
>

Should we blame the language C because MS knowingly and intentionally
makes a bad implementation of it?

>> - perhaps because they want users
>> to think C is bad and choose lock-in C# instead.  I have heard that the
>> more recent versions of MSVC are better, but have not tried them myself.
>>
>> tcc is a toy
>
> So, tcc doesn't count.

Correct.

>
> (And it's definitely not a toy - try writing something half as good. It
> turns working C code into executable binary code that runs at half the
> speed of -O3.
>
> But it checks fewer things, and has the odd thing missing - like
> tgmath.h. For building debugged code and doing it quickly, it is does
> that job well.)

It's a toy.

Toys can be fun, but no one - not even tcc's developers - would think of
it as a major compiler or a reference for a complete implementation of
modern C.

Oh, and tcc is a compiler - not a library. Of course it doesn't have
<tgmath.h> or any other library files.

>
> I've just now tried Clang. That is, Clang running on Windows, part of an
> large LLVM installation, and with links into MSBUILD tools.
>
> With this program:
>
>   #include <tgmath.h>
>
> It gives 20 errors before it give up.
>
> I guess, Clang doesn't count either! Apparently the only one that counts
> is yours.
>
> Somehow I don't get the impression that C has solved the problem of
> overloading pow(), even for the two float types that most people use.
>
> But you seem to like blaming implementations and OSes instead of blaming
> the language.

No, I blame /you/ and your amazing talent for failing to set up working
C toolchains on Windows. I just spent 30 seconds installing clang for
windows, and it had no problem with a file containing nothing but
#include <tgmath.h>. (As expected.)

Bart

unread,
Nov 10, 2021, 7:39:10 AM11/10/21
to
On 10/11/2021 11:00, David Brown wrote:
> On 09/11/2021 18:28, Bart wrote:

>> Now you might want to tell me why my way of making available **, sqrt
>> and sin is completely unsuitable for EVERYONE except me. I don't get it.
>
> It is unsuitable as a way of designing a language.

That is your opinion. And of course you've designed many languages.

> For /users/ of a
> language, it usually makes little difference if "abs" is a built-in
> function or a library function.

Yes, my languages are for end-users, not language-builders.

> For people involved in implementing,
> porting, expanding, documenting, standardising, testing, it is a very
> different matter.

None of those is impacted by the way I do things, except for expanding.

My languages are self-contained. If someone wants to add a feature, they
take the source code and modify it. Being fairly small, that is not hard.

> You seem to have a serious aversion to all kinds of structure and
> modularisation.

You have no idea what the structure of my compilers is like.

As for the languages themselves, they've had a proper module system for
the last decade (unlike C and C++). And I'm now revising it, based on
that experience, to be better build programs out of multi-module components.

Get your own house in order first I think.

> I don't know why - perhaps it is a background in
> assembly programming where everything is held at very flat levels.

Hmm, I suspect you still think those one-file C distributions I used to
do were how my programs were actually written: as a single, flat source
file!

Most of my EXE files are also presented as a single flat file; so the
original source code must be a single, flat file too!

> Maybe you are
> just used to working on your own, doing everything yourself.

Yes, and that can be good as well. Thank god I never ended up using C
and/or Unix, and devised my own solutions.

> Whatever it is, you prefer to have everything together in one lump. For

FFS, I've talking about a dozen common functions as built-ins. Is it
really that much of a big deal that I have to make my compiler 100 times
bigger, 100 times more complex, and 100 times slower, just so they can
written in user code to the same standard?

I bet you don't write your own compilers! You seem to have no idea what
is practical.

> a little system with few users,

Keep on patronising. I was selling £millions of software written in my
languages with those built-in operators. Or I could have delayed it 20
years while I developed one of those heavy-duty compilers you favour.


> That is not an advantage you get from having these functions built into
> the language - even in C there is no problem optimising maths functions.

Only by recognising that 'sqrt(x)' is THE square root function. That is
only possible if the language makes a special case for it, AS THOUGH it
was built-in. Which is exactly what I do.

>> * The language to know NOTHING about abs, sqrt, sin etc
>>
>
> Yes.

Um, no. How about the language knows nothing about + - * / either. Just
implement those in user-code as functions.

Add in user-defined symbolic operators.

Add in operating overloading.

Add in whole-program optimisation of source code.

Add in function inlining.

Add in the ability to take a bit-shuffling algorithm and recognise that
the code could be reduced to one machine ADD instruction.

Be prepared to wait a long time to compile any program because of the
huge prelude needed, and the time to reduce down all that boilerplate.

People do write implementations like that. THOSE are the hobbyist or
academic languages designed as experiments or proof-of-concepts.

Mine have /always/ been pragmatic because they had an actual job to do.
(Not now; now it's just for the satisfaction of wiping the floor with
products like C or LLVM.)

>> * The language needs to acquire function overloading, or some generic
>> features, to make those functions work on different types
>>
>
> No - the language should not need to "acquire" anything. Unless you are
> talking about a small scripting language or other niche language, if it
> can't handle generic or templated code, there's no point in creating it
> in the first place. (Well, fun or learning is always a good reason, but
> then none of this matters.)

OK. You are completely dismissing any language that doesn't have the
same feature set as C++. Including C presumably.

And dismissing any implementation that doesn't have 60-pass optimisers.

So, according to you, only big, sprawling, SLOW implementations count.
Dismiss everything else, they're just toys!


>> * The language possibly needs an inline assembler so that those
>> functions can be implemented efficiently where there are special
>> instructions available
>>
>
> Yes, that is reasonable if the language is to be low-level and efficient.

Another difficult feature, which doesn't port.

>> * The language needs advanced optimisation methods, link-time optimising
>> etc so that the code for some of these function can be inlined
>>
>
> I thought we were talking about languages that could have efficient code
> generation anyway. Was that wrong?

Hyper-optimisatation is quite a hard language feature; gcc might uses
dozens of passes to get decent code.

I write smaller, simpler compilers, so I can't do that. Self-contained,
too, so I can't depend on monstrosities like LLVM.

Instead, I design MY LANGUAGE so that it is easier to get reasonable code.

One way is to build in many common things that other languages would
need writing in user-code, requiring a lot of work to make as easy to
use and as fast as my built-in versions.

When you design YOUR LANGUAGE, then you can make your own choices.

In mine, reducing sqrt(9.0) to 3.0 is utterly trivial. This is the
support needed in the compiler to make it possible:

when ksqrt then z:=sqrt(x)

One line of code.


> A BASIC-like language is not too hard to implement (though certainly not
> trivial, especially if you insist on implementing it without using
> higher level languages or ready-made tools) - but what is the point,
> except for fun and learning?

More patronising.

Let me guess, you're envious that you never got around to writing a
language of your own, so you have to piss all over anyone else's attempts?


> Being able to find square roots is irrelevant for most programs,

Yeah. That's why there's a special button for it on pretty much every
calculator!

> and no
> one will miss an "abs" function - it is the features of the language
> that are important.

It seems to be important enough to be instantly available in Python. And
available in the standard C library in half a dozen variations.


Bart

unread,
Nov 10, 2021, 8:02:13 AM11/10/21
to
On 10/11/2021 12:03, David Brown wrote:
> On 09/11/2021 20:14, Bart wrote:
>> On 08/11/2021 22:43, David Brown wrote:
>>> On 08/11/2021 22:56, Bart wrote:
>>
>>>> tgmath.h is anyway not universal. tcc doesn't have it. MSVC warns its
>>>> version is not compatible with C99 (possibly due to not have _Generic).
>>>> (You have to use ctgmath.h, for C++.)
>>>
>>> I have little interest in half-baked sort-of-C compilers.  MSVC has
>>> traditionally had terrible C support
>>
>> So, MSVC doesn't count.
>>
>
> Should we blame the language C because MS knowingly and intentionally
> makes a bad implementation of it?

At least in this case you can't claim that MSVC is a one-person toy
product that no one else uses.

They just give low-priority to C, and decided to go with their own idea
of it. Good for them.

>
>>> - perhaps because they want users
>>> to think C is bad and choose lock-in C# instead.  I have heard that the
>>> more recent versions of MSVC are better, but have not tried them myself.
>>>
>>> tcc is a toy
>>
>> So, tcc doesn't count.
>
> Correct.
>
>>
>> (And it's definitely not a toy - try writing something half as good. It
>> turns working C code into executable binary code that runs at half the
>> speed of -O3.
>>
>> But it checks fewer things, and has the odd thing missing - like
>> tgmath.h. For building debugged code and doing it quickly, it is does
>> that job well.)
>
> It's a toy.

In the same way that a bike is a toy compared with a car then.

> Toys can be fun, but no one - not even tcc's developers - would think of
> it as a major compiler or a reference for a complete implementation of
> modern C.

You are just being snobbish. Here are two versions of one of my programs:

C:\oldqx>dir *.exe
18/10/2021 00:12 885,248 one.exe
18/10/2021 00:06 857,600 two.exe

One is compiled with gcc, one with tcc. Both work fine and give the same
results:

C:\oldqx>one fib
fib(36) = 14930352

C:\oldqx>two fib
fib(36) = 14930352

Can you tell which is which? Does it matter?

Perhaps if I tell you that one.exe took 15.5 seconds to build
[optimised, which would be the main point in using it], and two.exe took
0.1 seconds, it might give you a clue.

I want that toy!


> Oh, and tcc is a compiler - not a library. Of course it doesn't have
> <tgmath.h> or any other library files.

I don't care. I just want to call abs(). What the hell do I need to know
about tgmath for anyway?

> No, I blame /you/ and your amazing talent for failing to set up working
> C toolchains on Windows. I just spent 30 seconds installing clang for
> windows, and it had no problem with a file containing nothing but
> #include <tgmath.h>. (As expected.)

Which means of course that it works for everyone, since there is only
one version. My version cames as part of a LLVM download, and uses a
combination of LLVM headers, and headers which are part of MSVC/MSBUILD.

This is something I stated, since rextester.com's clang works.

Whatever, the fact is that all this ******* about with how 'abs' or
'pow' is implemented in C, means that it might not work on your
installation.


Bart

unread,
Nov 10, 2021, 11:05:25 AM11/10/21
to
The first computer I made, with a Z80 chip, didn't have them either.
Neither did it have floats at all.

I had to implement those, plus the maths and trig functions I needed for
the programs I wanted to write.

That didn't stop multiply appearing to be built-in to my language.

With functions like SQRT and SIN, if you only have one float type, then
probably there's little difference if they are operators in the
language, or user-code functions, provided they are always there
ready-to-use.

Ones like SQR (square) and ABS will generally work on both ints and
floats, so they will need the auto-overloading that language-supported
operators provide.





David Brown

unread,
Nov 10, 2021, 11:31:07 AM11/10/21
to
On 10/11/2021 14:02, Bart wrote:
> On 10/11/2021 12:03, David Brown wrote:
>> On 09/11/2021 20:14, Bart wrote:
>>> On 08/11/2021 22:43, David Brown wrote:
>>>> On 08/11/2021 22:56, Bart wrote:
>>>
>>>>> tgmath.h is anyway not universal. tcc doesn't have it. MSVC warns its
>>>>> version is not compatible with C99 (possibly due to not have
>>>>> _Generic).
>>>>> (You have to use ctgmath.h, for C++.)
>>>>
>>>> I have little interest in half-baked sort-of-C compilers.  MSVC has
>>>> traditionally had terrible C support
>>>
>>> So, MSVC doesn't count.
>>>
>>
>> Should we blame the language C because MS knowingly and intentionally
>> makes a bad implementation of it?
>
> At least in this case you can't claim that MSVC is a one-person toy
> product that no one else uses.
>
> They just give low-priority to C, and decided to go with their own idea
> of it. Good for them.

No, not good for them (though presumably they /thought/ it would be good
for them) - and certainly not good for anyone else. There are good
reasons why people like standards, and one of the worst things about MS
is how rarely they follow them (even for the standards they make).

>
>>
>>>> - perhaps because they want users
>>>> to think C is bad and choose lock-in C# instead.  I have heard that the
>>>> more recent versions of MSVC are better, but have not tried them
>>>> myself.
>>>>
>>>> tcc is a toy
>>>
>>> So, tcc doesn't count.
>>
>> Correct.
>>
>>>
>>> (And it's definitely not a toy - try writing something half as good. It
>>> turns working C code into executable binary code that runs at half the
>>> speed of -O3.
>>>
>>> But it checks fewer things, and has the odd thing missing - like
>>> tgmath.h. For building debugged code and doing it quickly, it is does
>>> that job well.)
>>
>> It's a toy.
>
> In the same way that a bike is a toy compared with a car then.

Fair enough, that's not too bad an analogy.


>> Toys can be fun, but no one - not even tcc's developers - would think of
>> it as a major compiler or a reference for a complete implementation of
>> modern C.
>
> You are just being snobbish. Here are two versions of one of my programs:
>
>   C:\oldqx>dir *.exe
>   18/10/2021  00:12           885,248 one.exe
>   18/10/2021  00:06           857,600 two.exe
>
> One is compiled with gcc, one with tcc. Both work fine and give the same
> results:
>
>   C:\oldqx>one fib
>   fib(36) = 14930352
>
>   C:\oldqx>two fib
>   fib(36) = 14930352
>
> Can you tell which is which? Does it matter?
>
> Perhaps if I tell you that one.exe took 15.5 seconds to build
> [optimised, which would be the main point in using it], and two.exe took
> 0.1 seconds, it might give you a clue.
>
> I want that toy!

What you want is an interpreted scripting language.

>
>
>> Oh, and tcc is a compiler - not a library.  Of course it doesn't have
>> <tgmath.h> or any other library files.
>
> I don't care. I just want to call abs(). What the hell do I need to know
> about tgmath for anyway?

I know you don't care - you are proud of your ignorance in how the C
language and how C implementations work.

>
>> No, I blame /you/ and your amazing talent for failing to set up working
>> C toolchains on Windows.  I just spent 30 seconds installing clang for
>> windows, and it had no problem with a file containing nothing but
>> #include <tgmath.h>.  (As expected.)
>
> Which means of course that it works for everyone, since there is only
> one version. My version cames as part of a LLVM download, and uses a
> combination of LLVM headers, and headers which are part of MSVC/MSBUILD.
>

It means it works for people other than you.

> This is something I stated, since rextester.com's clang works.
>
> Whatever, the fact is that all this ******* about with how 'abs' or
> 'pow' is implemented in C, means that it might not work on your
> installation.
>

No, it might not work on /your/ installation. Other people manage fine.
You seem to forget that - getting working C implementations is not
rocket science. Breaking them as successfully and repeatedly as you do,
/that/ takes some skill.

Dmitry A. Kazakov

unread,
Nov 10, 2021, 11:38:00 AM11/10/21
to
On 2021-11-10 17:05, Bart wrote:

> With functions like SQRT and SIN, if you only have one float type, then
> probably there's little difference if they are operators in the
> language, or user-code functions, provided they are always there
> ready-to-use.

But I do not want a language with single floating-point type and even
less a language with a floating type which accuracy and precision are
undefined = defined by some arbitrary target hardware.

It is no problem to provide accurate down to the declared precision
arithmetic for any floating-point type, but it becomes an unnecessary
burden for irrational functions. So leaving that to the libraries is a
rational choice.

> Ones like SQR (square) and ABS will generally work on both ints and
> floats, so they will need the auto-overloading that language-supported
> operators provide.

That applies to all operators, all subprograms, all literals, all named
objects.

Dmitry A. Kazakov

unread,
Nov 10, 2021, 11:55:41 AM11/10/21
to
On 2021-11-10 17:31, David Brown wrote:
> On 10/11/2021 14:02, Bart wrote:

>> They just give low-priority to C, and decided to go with their own idea
>> of it. Good for them.
>
> No, not good for them (though presumably they /thought/ it would be good
> for them) - and certainly not good for anyone else.

If I correctly remember, they bought the compiler from a third firm. The
original MS C compiler for MS-DOS was a pure abomination.

> There are good
> reasons why people like standards, and one of the worst things about MS
> is how rarely they follow them (even for the standards they make).

Hey, they probably write Windows 11 code in Basic, still. Although, each
new version of Basic is incompatible with the previous one...

Bart

unread,
Nov 10, 2021, 1:14:19 PM11/10/21
to
On 10/11/2021 16:31, David Brown wrote:
> On 10/11/2021 14:02, Bart wrote:

>> I don't care. I just want to call abs(). What the hell do I need to know
>> about tgmath for anyway?
>
> I know you don't care - you are proud of your ignorance in how the C
> language and how C implementations work.

I want to write a program and use abs().

That is not a very difficult operator to provide. You can write your own
versions easily enough, even as macros.

Yet languages generally provide it: Pascal, Python and C among many.

C is the exception in originally providing it as a bundled user-code
function, with multiple versions for different types, using either
stdlib.h or math.h or tgmath.h.

They may be various reasons why it was done like that in the neolithic
period when C first came out, but those are still the requirements now.

I believe that using tgmath.h instead of math.h emulates overloading of
fabs() for various float types, but I showed 3 compiler implementations
that had problems with it in 2021.

It IS a consequence of how C decided to do this stuff in the distant
past, and still does.

As it happens, I know how C deals with abs(), since I've implemented C.


> It means it works for people other than you.

> No, it might not work on /your/ installation. Other people manage fine.
> You seem to forget that - getting working C implementations is not
> rocket science. Breaking them as successfully and repeatedly as you do,
> /that/ takes some skill.

OK, YOU tell ME exactly how I managed to get the list of errors below,
since you're so much more skilled than I am:

The input is a file C:\c\c.c that contains:

#include <tgmath.h>

Installed is a 1.7GB installation of LLVM that includes clang.exe. And
a 2.8GB, 14,000-file installion of MSBuild tools or what is necessary to
run MSVC.

My contention is that it is how this language implements fundemental
features that makes it particularly prone to things going wrong like this.

Yours I already know:

* Bart doesn't know what the hello he's doing

* Microsoft don't know what the hell they're doing

* Windows is rubbish anyway


-------------------------------------------

In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:72:50: error: passing
'_Complex float' to parameter of incompatible type '_Fcomplex' (aka
'struct _C_float_complex')
__tg_acos(float _Complex __x) {return cacosf(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:94:50: note: passing
argument to parameter '_Z' here
_ACRTIMP _Fcomplex __cdecl cacosf(_In_ _Fcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:76:50: error: passing
'_Complex double' to parameter of incompatible type '_Dcomplex' (aka
'struct _C_double_complex')
__tg_acos(double _Complex __x) {return cacos(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:69:49: note: passing
argument to parameter '_Z' here
_ACRTIMP _Dcomplex __cdecl cacos(_In_ _Dcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:80:56: error: passing
'_Complex long double' to parameter of incompatible type '_Lcomplex'
(aka 'struct _C_ldouble_complex')
__tg_acos(long double _Complex __x) {return cacosl(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:119:52: note: passing
argument to parameter '_Z' here
_ACRTIMP _Lcomplex __cdecl cacosl(_In_ _Lcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:101:50: error: passing
'_Complex float' to parameter of incompatible type '_Fcomplex' (aka
'struct _C_float_complex')
__tg_asin(float _Complex __x) {return casinf(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:97:50: note: passing
argument to parameter '_Z' here
_ACRTIMP _Fcomplex __cdecl casinf(_In_ _Fcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:105:50: error: passing
'_Complex double' to parameter of incompatible type '_Dcomplex' (aka
'struct _C_double_complex')
__tg_asin(double _Complex __x) {return casin(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:72:49: note: passing
argument to parameter '_Z' here
_ACRTIMP _Dcomplex __cdecl casin(_In_ _Dcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:109:56: error: passing
'_Complex long double' to parameter of incompatible type '_Lcomplex'
(aka 'struct _C_ldouble_complex')
__tg_asin(long double _Complex __x) {return casinl(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:122:52: note: passing
argument to parameter '_Z' here
_ACRTIMP _Lcomplex __cdecl casinl(_In_ _Lcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:130:50: error: passing
'_Complex float' to parameter of incompatible type '_Fcomplex' (aka
'struct _C_float_complex')
__tg_atan(float _Complex __x) {return catanf(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:99:50: note: passing
argument to parameter '_Z' here
_ACRTIMP _Fcomplex __cdecl catanf(_In_ _Fcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:134:50: error: passing
'_Complex double' to parameter of incompatible type '_Dcomplex' (aka
'struct _C_double_complex')
__tg_atan(double _Complex __x) {return catan(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:74:49: note: passing
argument to parameter '_Z' here
_ACRTIMP _Dcomplex __cdecl catan(_In_ _Dcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:138:56: error: passing
'_Complex long double' to parameter of incompatible type '_Lcomplex'
(aka 'struct _C_ldouble_complex')
__tg_atan(long double _Complex __x) {return catanl(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:124:52: note: passing
argument to parameter '_Z' here
_ACRTIMP _Lcomplex __cdecl catanl(_In_ _Lcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:159:52: error: passing
'_Complex float' to parameter of incompatible type '_Fcomplex' (aka
'struct _C_float_complex')
__tg_acosh(float _Complex __x) {return cacoshf(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:95:51: note: passing
argument to parameter '_Z' here
_ACRTIMP _Fcomplex __cdecl cacoshf(_In_ _Fcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:163:52: error: passing
'_Complex double' to parameter of incompatible type '_Dcomplex' (aka
'struct _C_double_complex')
__tg_acosh(double _Complex __x) {return cacosh(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:70:50: note: passing
argument to parameter '_Z' here
_ACRTIMP _Dcomplex __cdecl cacosh(_In_ _Dcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:167:58: error: passing
'_Complex long double' to parameter of incompatible type '_Lcomplex'
(aka 'struct _C_ldouble_complex')
__tg_acosh(long double _Complex __x) {return cacoshl(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:120:53: note: passing
argument to parameter '_Z' here
_ACRTIMP _Lcomplex __cdecl cacoshl(_In_ _Lcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:188:52: error: passing
'_Complex float' to parameter of incompatible type '_Fcomplex' (aka
'struct _C_float_complex')
__tg_asinh(float _Complex __x) {return casinhf(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:98:51: note: passing
argument to parameter '_Z' here
_ACRTIMP _Fcomplex __cdecl casinhf(_In_ _Fcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:192:52: error: passing
'_Complex double' to parameter of incompatible type '_Dcomplex' (aka
'struct _C_double_complex')
__tg_asinh(double _Complex __x) {return casinh(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:73:50: note: passing
argument to parameter '_Z' here
_ACRTIMP _Dcomplex __cdecl casinh(_In_ _Dcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:196:58: error: passing
'_Complex long double' to parameter of incompatible type '_Lcomplex'
(aka 'struct _C_ldouble_complex')
__tg_asinh(long double _Complex __x) {return casinhl(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:123:53: note: passing
argument to parameter '_Z' here
_ACRTIMP _Lcomplex __cdecl casinhl(_In_ _Lcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:217:52: error: passing
'_Complex float' to parameter of incompatible type '_Fcomplex' (aka
'struct _C_float_complex')
__tg_atanh(float _Complex __x) {return catanhf(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:100:51: note: passing
argument to parameter '_Z' here
_ACRTIMP _Fcomplex __cdecl catanhf(_In_ _Fcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:221:52: error: passing
'_Complex double' to parameter of incompatible type '_Dcomplex' (aka
'struct _C_double_complex')
__tg_atanh(double _Complex __x) {return catanh(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:75:50: note: passing
argument to parameter '_Z' here
_ACRTIMP _Dcomplex __cdecl catanh(_In_ _Dcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:225:58: error: passing
'_Complex long double' to parameter of incompatible type '_Lcomplex'
(aka 'struct _C_ldouble_complex')
__tg_atanh(long double _Complex __x) {return catanhl(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:125:53: note: passing
argument to parameter '_Z' here
_ACRTIMP _Lcomplex __cdecl catanhl(_In_ _Lcomplex _Z);
^
In file included from c.c:1:
C:\LLVM\lib\clang\11.0.0\include\tgmath.h:246:48: error: passing
'_Complex float' to parameter of incompatible type '_Fcomplex' (aka
'struct _C_float_complex')
__tg_cos(float _Complex __x) {return ccosf(__x);}
^~~
C:\Program Files (x86)\Windows
Kits\10\include\10.0.18362.0\ucrt\complex.h:101:49: note: passing
argument to parameter '_Z' here
_ACRTIMP _Fcomplex __cdecl ccosf(_In_ _Fcomplex _Z);
^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.


David Brown

unread,
Nov 10, 2021, 1:56:44 PM11/10/21
to
I can only guess at what you have been doing to get your system so mixed
up. But one guess would be that you are mixing C and C++ in some way
("struct _C_float_complex" looks a bit like a C++ complex number type,
since these are handled by classes in C++ rather than a fundamental type
like in C).

The other guess is that you are using <tgmath.h> designed for one
compiler with a different compiler, since <tgmath.h> is usually
implemented in a compiler-specific manner. For example, maybe you are
using MSVC libraries with clang, but these are not expected to work
unless you run clang via an MSVC front-end.


Personally, on my Windows system I did this :

pacman -Ss clang

30 seconds or so later, after installation of clang...

clang -c c.c

Bart

unread,
Nov 10, 2021, 2:41:36 PM11/10/21
to
On 10/11/2021 18:56, David Brown wrote:
> On 10/11/2021 19:14, Bart wrote:

[Compiling tgmath.h]

>> In file included from c.c:1:
>> C:\LLVM\lib\clang\11.0.0\include\tgmath.h:72:50: error: passing
>> '_Complex float' to parameter of incompatible type '_Fcomplex' (aka
>> 'struct _C_float_complex')
>>     __tg_acos(float _Complex __x) {return cacosf(__x);}
>>                                                  ^~~
>
> I can only guess at what you have been doing to get your system so mixed
> up. But one guess would be that you are mixing C and C++ in some way
> ("struct _C_float_complex" looks a bit like a C++ complex number type,
> since these are handled by classes in C++ rather than a fundamental type
> like in C).
>
> The other guess is that you are using <tgmath.h> designed for one
> compiler with a different compiler, since <tgmath.h> is usually
> implemented in a compiler-specific manner. For example, maybe you are
> using MSVC libraries with clang, but these are not expected to work
> unless you run clang via an MSVC front-end.
>
>
> Personally, on my Windows system I did this :
>
> pacman -Ss clang
>
> 30 seconds or so later, after installation of clang...
>
> clang -c c.c
>

My Clang is:

clang version 11.0.0
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\LLVM\bin

The only working version I can try is from rextester.com, which says:

clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

(What does your say?)

Clang is rather peculiar: it is a parasitical compiler that piggy-backs
onto other compilers. The first version I used on Windows, required gcc
installed, and utilised its headers, linker etc. (I didn't find out for
two years; I thought I had two separate compilers!)

Then it changed its allegiance to MSVC, when it stopped working
completely for several years since it could never properly sync to my
MSVC installation.

Eventually I must have done something right, or the LLVM clang is
different, as a year ago it managed to work - a miracle!

(But I'm still surprised that a 1700MB compiler installation doesn't
come with its own headers and stuff.)

My clang is on my old Windows 7 PC. I have a new PC now with Windows 10,
but I haven't bothered with MSVC or clang.

Maybe if I used your pacman it would work like yours.

But, W10 says 'pacman' is not recognised. On WSL, it says it's not
installed but can be with 'apt install'. If this is how you got clang,
then you're not running clang under actual Windows, so your comparison
would be invalid.

(A search for 'Windows pacman' gave me links to an arcade game.)

David Brown

unread,
Nov 11, 2021, 5:53:26 AM11/11/21
to
clang version 11.0.0
Target: x86_64-pc-windows-msys
Thread model: posix
InstalledDir: /usr/bin

So, the same compiler but targeting msys run-time rather than msvc's C
runtime.

>
> The only working version I can try is from rextester.com, which says:
>
>   clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
>   Target: x86_64-pc-linux-gnu
>   Thread model: posix
>   InstalledDir: /usr/bin
>

Why do you insist on using rextester.com which is known to have a poor
setup that disables warnings by default and has only a limited selection
of tools? Go to <https://godbolt.org> - it is, as far as I can see, the
tool of choice - dozens of languages (not just C and C++), heaps of
compilers (such as clang from 3.0 to 13 and development branches, 32-bit
and 64-bit, x86 and ARM - and tcc) and lots of functions. If there is
something useful that rextester.com can do that godbolt.org cannot, then
use that as an extra.

> (What does your say?)
>
> Clang is rather peculiar: it is a parasitical compiler that piggy-backs
> onto other compilers. The first version I used on Windows, required gcc
> installed, and utilised its headers, linker etc. (I didn't find out for
> two years; I thought I had two separate compilers!)

No, it is not "peculiar" - it is a C and C++ compiler. It is not a
complete toolchain, and does not come with a library, assembler or
linker (though llvm also provides an assembler and linker). The same
applies to gcc. Some pre-built packings of clang come with a library,
just as some is the case with gcc. Other packages separate these. But
however you get the tools, from packages or if you build from source,
you need a compiler, assembler, linker and library in order to have a
complete implementation or toolchain. And they need to work together -
the standard library and the compiler need to match to some extent
(though most of the library can be compiler-independent).

This has been explained to you countless times. But you are so utterly
convinced that /your/ choice of structuring - compiler and library
rolled into one - is the only "correct" way that you can't seem to
understand this. So you ignore all information and guides, and get the
setup wrong again and again. (In reality, there are pros and cons of
making complete packages with everything in the toolchain from one
place. Different arrangements are useful for different purposes.)

>
> Then it changed its allegiance to MSVC, when it stopped working
> completely for several years since it could never properly sync to my
> MSVC installation.

clang did not "change allegiance". MSVC choose to start supporting
clang as an alternative to their own C compiler.

>
> Eventually I must have done something right, or the LLVM clang is
> different, as a year ago it managed to work - a miracle!
>
> (But I'm still surprised that a 1700MB compiler installation doesn't
> come with its own headers and stuff.)
>
> My clang is on my old Windows 7 PC. I have a new PC now with Windows 10,
> but I haven't bothered with MSVC or clang.
>
> Maybe if I used your pacman it would work like yours.

I've recommended using msys2 / mingw-64 to you before.

For some things, the "Windows way" is better. For others, the "Linux
way" is better. (I use two PC's at the office - one Windows 7, one
Linux.) In this situation, as for many software development tasks, the
"Linux way" is /hugely/ better. Install msys2, and then use its package
manager "pacman" (borrowed from Arch Linux) and you'll have everything
working in minutes.

I have not used WSL, but I gather it is getting better with each Windows
version. If you have that and run "apt install clang" rather than msys2
and "pacman -Ss clang", then that will work fine too - it's the same
principle.

>
> But, W10 says 'pacman' is not recognised. On WSL, it says it's not
> installed but can be with 'apt install'. If this is how you got clang,
> then you're not running clang under actual Windows, so your comparison
> would be invalid.
>

It's a Windows machine. It is not a virtual machine of any sort. I can
run "pacman" and "clang" under a normal command prompt (though I prefer
to use msys2's terminal). I can compile programs with "clang" on that
Windows system and run them on Windows. It is Windows. /Actual/
Windows, whatever that might mean.


Bart

unread,
Nov 11, 2021, 6:41:58 AM11/11/21
to
On 11/11/2021 10:53, David Brown wrote:

>> My Clang is:
>>
>>   clang version 11.0.0
>>   Target: x86_64-pc-windows-msvc
>>   Thread model: posix
>>   InstalledDir: C:\LLVM\bin
>
> clang version 11.0.0
> Target: x86_64-pc-windows-msys
> Thread model: posix
> InstalledDir: /usr/bin

Thanks.

> So, the same compiler but targeting msys run-time rather than msvc's C
> runtime.

Try deleting msys' gcc installation, and see if it still works. If it
does try deleting msys' standard C headers, if they come with that product.

>>
>> The only working version I can try is from rextester.com, which says:
>>
>>   clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
>>   Target: x86_64-pc-linux-gnu
>>   Thread model: posix
>>   InstalledDir: /usr/bin
>>
>
> Why do you insist on using rextester.com

Because that is a known working product isolated from my machine.

>> (What does your say?)
>>
>> Clang is rather peculiar: it is a parasitical compiler that piggy-backs
>> onto other compilers. The first version I used on Windows, required gcc
>> installed, and utilised its headers, linker etc. (I didn't find out for
>> two years; I thought I had two separate compilers!)
>
> No, it is not "peculiar" - it is a C and C++ compiler.

It IS peculiar, at least on Windows, where the OS doesn't natively
provide C headers, assemblers, link tools etc. Because it uses those of
another installed C compiler (was gcc/mingw, now MSVC).

I haven't seen that on any other C compiler for Windows, which are all
self-contained.

I call that peculiar. You of are course have to be contrary.

(I have seen that behaviour in languages like Rust, but that is also
associated with LLVM.)

> This has been explained to you countless times. But you are so utterly
> convinced that /your/ choice of structuring - compiler and library
> rolled into one - is the only "correct" way that you can't seem to
> understand this.

It is the typical way that any compiler comes on Windows. Even gcc is
usually obtained as self-contained bundle (what good is it otherwise?).

Imagine if clang was still dependent on a gcc/mingw installation. And
gcc/mingw decided to do the same thing - not bother with as, ld, headers
etc; let's piggyback on clang's!

You don't see a problem there?
> and guides, and get the
> setup wrong again and again. (In reality, there are pros and cons of
> making complete packages with everything in the toolchain from one
> place. Different arrangements are useful for different purposes.)


>>
>> Then it changed its allegiance to MSVC, when it stopped working
>> completely for several years since it could never properly sync to my
>> MSVC installation.
>
> clang did not "change allegiance". MSVC choose to start supporting
> clang as an alternative to their own C compiler.

CL.EXE is still a thing ATM. It is not clang.exe which is a gcc clone.

But something clearly changed inside clang, for it to switch from a gcc
installation to msvc. This is also a detail they didn't disclose to anyone.

> I've recommended using msys2 / mingw-64 to you before.
>

Someone says 'X doesn't work on Windows'.

You say, 'Nope, X works fine on Windows. You must be a fool'.

Then it turns on you haven't run X on Windows at all, it is one of
Cygwin or MSYS2 or WSL, which all drag diferent elements of Unix.

That seems to be point that YOU repeatedly fail to understand.

The ludicrousness of effectively having to switch OSes just to enable a
working abs() or pow() function in a language seems to have escaped you too.

Here is an extract from a stackoverflow question:

"I'd like to use clang without GCC on Linux and without MSVC on Windows..."

Bart

unread,
Nov 11, 2021, 7:16:03 AM11/11/21
to
On 11/11/2021 11:41, Bart wrote:
> On 11/11/2021 10:53, David Brown wrote:

>> This has been explained to you countless times.  But you are so utterly
>> convinced that /your/ choice of structuring - compiler and library
>> rolled into one - is the only "correct" way that you can't seem to
>> understand this.
>
> It is the typical way that any compiler comes on Windows. Even gcc is
> usually obtained as self-contained bundle (what good is it otherwise?).

I've got clang lying around as part of LLVM. Here's what happens when I
try and compile hello.c:

F:\llvm\bin>clang hello.c
clang: warning: unable to find a Visual Studio installation; try
running Clang from a developer command prompt [-Wmsvc-not-found]
hello.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>

So the ideal way of distributing a compiler is to require a 6000MB
download of another compiler?

I wonder what that toy compiler will do:

F:\llvm\bin>tcc hello.c -run
Hello, World!

How about that? Or this toy compiler:

F:\llvm\bin>bcc hello -run
Compiling hello.c to hello.exe
Hello, World!

I like products that get the job done with no fuss. If it was vitally
important to compiler/run some program RIGHT NOW, and all I had was
clang, I'd be stuck.

A 1700MB compiler (three times the size of gcc) that can't even build a
Hello World program?

It's like buying a £100m 747 to go shopping with, instead of a £100
bike. Except it doesn't come with any engines so doesn't work anyway!

But here's more fun with clang. If I provide a suitable "stdio.h" then

F:\llvm\bin>clang hello.c -c

produces hello.o. Now I try and link:

F:\llvm\bin>lld-link hello.o
lld-link: error: <root>: undefined symbol: mainCRTStartup
lld-link: error: undefined symbol: printf

OK, let's provide a C runtime:

F:\llvm\bin>lld-link hello.o \windows\system32\msvcrt.dll
lld-link: error: \windows\system32\msvcrt.dll: bad file type. Did you
specify a DLL instead of an import library?

Yes, I did. So a 63MB linker doesn't understand DLL files? Even the
0.18MB tcc will work with DLLs!

What a heap of junk.

David Brown

unread,
Nov 11, 2021, 10:44:06 AM11/11/21
to
On 11/11/2021 12:41, Bart wrote:
> On 11/11/2021 10:53, David Brown wrote:
>
>>> My Clang is:
>>>
>>>    clang version 11.0.0
>>>    Target: x86_64-pc-windows-msvc
>>>    Thread model: posix
>>>    InstalledDir: C:\LLVM\bin
>>
>> clang version 11.0.0
>> Target: x86_64-pc-windows-msys
>> Thread model: posix
>> InstalledDir: /usr/bin
>
> Thanks.
>
>> So, the same compiler but targeting msys run-time rather than msvc's C
>> runtime.
>
> Try deleting msys' gcc installation, and see if it still works. If it
> does try deleting msys' standard C headers, if they come with that product.

That does not even make sense.

Let me try to explain what I mean by that. A "package manager" is not
just format for zipping up files for a program. It handles downloading
packages from one or more repositories, tracking a database of installed
packages, ensuring dependencies are in place before installing packages,
updates, upgrades, start/stop scripts, installation scripts for setup
and configuration, and many other things.

(By "package manager", I don't just mean "pacman" - other package
managers such as "apt", "yum", "portage", etc., on Linux, "ports" on
BSD, and Windows package managers such as Ninite or NuGet. They all
follow similar principles. Wikipedia has a list of package managers for
Windows.)

So when you use a package manager to install "clang", it will first
install any required dependency packages such as libraries, assemblers,
etc. If you uninstall a package, then any other packages that d