February 09

On Friday, 9 February 2024 at 11:00:09 UTC, thinkunix wrote:

>

If your issue is that the compiler didn't catch this, shouldn't you
raise the issue on a compiler internals list? Maybe I've misunderstood
the purpose of d-learn "Questions about learning and using D".

It's been discussed many, many times. The behavior is not going to change - there won't even be a compiler warning. (You'll have to check with the leadership for their reasons.)

I think something like this, which is such an obviously bad design and hits so many new users, should be discussed in the learn forum so new users are aware of what's going on.

February 09
On Friday, 9 February 2024 at 11:00:09 UTC, thinkunix wrote:
>
> First off I, I am just a beginner with D.  I joined this list to try to
> learn more about the language not to but heads with experts.  I'm sorry
> if you took my response that way.

Hi thinkunix,

I did interpret your post as critical. Sorry if it wasn't intended to be and my reply had a little too much heat. I still think my reply was at least accurate, so replies below.

> My post was merely to show how, with my rudimentary knowledge, I could
> get the loop to execute 4 times, which appeared (to me) to be the intent of your code.  Thank you for the exercise.  I learned more about the D type system.
>
> I said I would not write code like that because:
> * why start at -1 if array indexes start at 0?

The program that I was writing was most elegant doing that. Obviously I wasn't doing something as simple as the example. The post is simply to highlight the issue.

Unfortunately I can't find the examples now. The code has been altered so grepping isn't finding it and, since AoC has 25 days, I'm not sure which ones it was. It /might/ have been this, where 'where_to_start' is signed and can be negative. It's a weird index of indexes thing, and quite unconventional.

        // Try it in the remaining groups.
        for (auto i = where_to_start; i < num_ss.length; ++i)

> * why use auto which made the type different than what .length is?

Google "almost always auto" for why you should prefer it - don't miss Herb Sutter's post - but as someone else pointed out, it's no better with 'int' *or* 'ulong'.

The "best" solution is to cast the returned length to long. This makes it work and, unless you're counting the atoms in the universe, should be sufficient on a reasonable machine.

This is why I brought up the example. zjh was lamenting having to cast, as am I, much less think this hard about it.

> You provided no context, or comment indicated what you were trying
> to achieve by starting with -1.  Clearly I didn't understand your
> intent.

I wasn't asking a question. I know how to code this in D and I made it work. My post was to highlight the completely unnecessary need to cast.

What happens when there's a more reasonable example? What happens when you need to compare 2 library function results when one is signed and the other not? Would you even know that you had to cast one? Or would you just get strange results and not know why? The issue exists completely outside of my example.

Since you sound new, I'll mention that, yes, what I'm proposing can be a hair slower. But so what? 99 of a 100 programs won't notice and, if it does, your profiler will tell you where, you add the cast (or you add it ahead time, since that's what we have to do now), done.

I understand that it is almost certainly too late for D but the world seems ready for an alternative to C++ and lots of languages are coming. This is just part of that discussion, right?

February 09

On Friday, 9 February 2024 at 12:15:29 UTC, Sergey wrote:

>

On Friday, 9 February 2024 at 08:04:56 UTC, Danilo wrote:

>

Rust, Nim, Zig, Odin…?

Here is the Forum for D(lang). ;)

But it is fine to see what others have..
Teach on their experience is useful

This is how research is going

Thank you Sergey! I definitely appreciate the wider perspective I've gained by peering into multiple languages.

For example, Ada, being a Wirthian language, has an N-index based system, so indices can be negative which necessitates a return type of a signed type for the Length attribute. Pascal, Lua, and PL/I are other languages that are also N-index based vs just being either 0-index(most languages) or 1-index based (eg. Julia, Matlab, Fortran). :)

February 09

On Friday, 9 February 2024 at 12:15:29 UTC, Sergey wrote:

> >

Rust, Nim, Zig, Odin…?

Here is the Forum for D(lang). ;)

But it is fine to see what others have..
Teach on their experience is useful

This is how research is going

Sorry, I probably got confused by the use of different languages in every posting.

February 09

On Friday, 9 February 2024 at 16:49:37 UTC, Gary Chike wrote:

The underlying architecture of the language will often times dictate how certain constructs or design decisions are made. For example in Ada, every array has a Length attribute and it returns an integer type.

And since Ada is a very strongly typed language, there is no choice but to explicitly cast both the numerator and denominator. Ada will not allow you to cast only the numerator and allow the compiler to implicitly cast the denominator as is the case in most C-based languages. This will not compile:
Avg := Float(Sum) / Len;

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;

procedure Main is
   type Int_Array is array (Positive range <>) of Integer;

   A   : Int_Array := (-5000, 0);
   Len : Integer := A'Length;
   Sum : Integer := A(1) + A(2);
   Avg : Float;
begin
   Avg := Float(Sum) / Float(Len);
   Put(Avg, 1, 2, 0);
   New_Line;
end Main;

Output: -2500.00

February 12

On Friday, 9 February 2024 at 15:19:32 UTC, bachmeier wrote:

>

It's been discussed many, many times. The behavior is not going to change - there won't even be a compiler warning. (You'll have to check with the leadership for their reasons.)

Was (part of) the reason because it would disrupt existing code? If that was the blocker then editions are the solution.

February 12
On Mon, Feb 12, 2024 at 05:26:25PM +0000, Nick Treleaven via Digitalmars-d-learn wrote:
> On Friday, 9 February 2024 at 15:19:32 UTC, bachmeier wrote:
> > It's been discussed many, many times. The behavior is not going to change - there won't even be a compiler warning. (You'll have to check with the leadership for their reasons.)
> 
> Was (part of) the reason because it would disrupt existing code? If that was the blocker then editions are the solution.

Honestly, I think this issue is blown completely out of proportion. The length of stuff in any language needs to be some type. D decided on an unsigned type. You just learn that and adapt your code accordingly, end of story.  Issues like these can always be argued both ways, and the amount of energy spent in these debates far outweigh the trivial workarounds in code, of which there are many (use std.conv.to for bounds checks, just outright cast it if you know what you're doing (or just foolhardy), use CheckedInt, etc.). And the cost of any change to the type now also far, far outweighs any meager benefits it may have brought.  It's just not worth it, IMNSHO.


T

-- 
Verbing weirds language. -- Calvin (& Hobbes)
February 12

On Monday, 12 February 2024 at 17:26:25 UTC, Nick Treleaven wrote:

>

On Friday, 9 February 2024 at 15:19:32 UTC, bachmeier wrote:

>

It's been discussed many, many times. The behavior is not going to change - there won't even be a compiler warning. (You'll have to check with the leadership for their reasons.)

Was (part of) the reason because it would disrupt existing code? If that was the blocker then editions are the solution.

I don't want to write a speculative answer on Walter's reasoning, but I know that (a) this has come up many times, and (b) I've never seen him express an opinion that anything in the language related to unsigned types is problematic. I can't imagine that he has any intention of changing it, given the number of times it's been raised, but I can't claim any special knowledge of his views.

February 12
On Monday, 12 February 2024 at 18:22:46 UTC, H. S. Teoh wrote:

> Honestly, I think this issue is blown completely out of proportion.

Only for people that don't have to deal with the problems it causes.

> D decided on an unsigned type. You just learn that and adapt your code accordingly, end of story.  Issues like these can always be argued both ways, and the amount of energy spent in these debates far outweigh the trivial workarounds in code, of which there are many (use std.conv.to for bounds checks, just outright cast it if you know what you're doing (or just foolhardy), use CheckedInt, etc.).

A terrible language is one that makes you expend your energy thinking about workarounds rather than solving your problems. The default should be code that works. The workarounds should be for cases where you want to do something extremely unusual like subtracting from an unsigned type and having it wrap around.
February 12
On Mon, Feb 12, 2024 at 07:34:36PM +0000, bachmeier via Digitalmars-d-learn wrote:
> On Monday, 12 February 2024 at 18:22:46 UTC, H. S. Teoh wrote:
> 
> > Honestly, I think this issue is blown completely out of proportion.
> 
> Only for people that don't have to deal with the problems it causes.

I've run into size_t vs int issues many times.  About half the time it exposed fallacious assumptions on my part about value types. The other half of the time a simple cast or std.conv.to invocation solved the problem.

My guess is that most common use of .length in your typical D code is in (1) passing it to code that expect a length for various reasons, and (2) in loop conditions to avoid overrunning a buffer or overshooting some range. (1) is a non-problem, 90% of (2) is solved by using constructs like foreach() and/or ranges instead of overly-clever arithmetic involving length, which is almost always wrong or unnecessary.  If you need to do subtraction with lengths, that's a big red flag that you're approaching your problem from the wrong POV. About the only time you need to do arithmetic with lengths is in low-level code like allocators or array copying, for which you really should be using higher-level constructs instead.


> > D decided on an unsigned type. You just learn that and adapt your code accordingly, end of story.  Issues like these can always be argued both ways, and the amount of energy spent in these debates far outweigh the trivial workarounds in code, of which there are many (use std.conv.to for bounds checks, just outright cast it if you know what you're doing (or just foolhardy), use CheckedInt, etc.).
> 
> A terrible language is one that makes you expend your energy thinking about workarounds rather than solving your problems. The default should be code that works. The workarounds should be for cases where you want to do something extremely unusual like subtracting from an unsigned type and having it wrap around.

Yes, if I had my way, implicit conversions to/from unsigned types should be a compile error. As should comparisons between signed/unsigned values.

But regardless, IMNSHO any programmer worth his wages ought to learn what an unsigned type is and how it works. A person should not be writing code if he can't even be bothered to learn how the machine that's he's programming actually works.  To quote Knuth:

	People who are more than casually interested in computers should
	have at least some idea of what the underlying hardware is like.
	Otherwise the programs they write will be pretty weird. -- D.
	Knuth

One of the reasons Walter settled on size_t being unsigned is that this reflects how the hardware actually works.  Computer arithmetic is NOT highschool arithmetic; you do not have infinite width nor infinite precision, and you're working with binary, not decimal. This has consequences, and having the language pretend the distinction doesn't exist does not solve any problems.

If an architectural astronaut works at such a high level of abstraction that he doesn't even understand how basic things about the hardware, like how uint or ulong work and how to use them correctly, maybe he should be promoted to a managerial role instead of writing code.


T

-- 
You are only young once, but you can stay immature indefinitely. -- azephrahel