February 08
On 8/2/24 16:00, Kevin Bailey wrote:
> I'm asking, why is the default C compatibility (of all things) rather than "safety that I can override if I need to make it faster" ?

I'm sure there are more experienced people here that will be able to answer better, but as far as I remember, the policy has been like this since times immemorial:

> D code that happens to be valid C code as well should either behave exactly like C, or not compile at all.

I can't find a quote in the official documentation right now, though.

IIRC, there are a couple of specific situations where this is not the case, but I think this is the answer to your question ("why?").

You can well disagree with this policy, and there are probably many good reasons for that, but that's probably a deeper discussion.
February 08

On Thursday, 8 February 2024 at 15:00:54 UTC, Kevin Bailey wrote:

>

By all means, please share with us how you would have written that just as elegantly but "correct".

Elegant and correct is this version:

import std.stdio;

int main()
{
        char[] something = ['a', 'b', 'c'];

        writeln("len: ", something.length);
        writeln("typeid(something.length): ",
                typeid(something.length));

        writeln ("i: -1");
        foreach (i, _; something)
                writeln("i: ", i);
        return 0;
}

But it is still a bit too "clever" in the foreach statement due to the unused variable _.

February 08

Arafel,

You're certainly correct. Priorities change. It used to be thought that backwards compatibility was the way to attract developers. But today the keyword is "safety".

Apparently 2022 was the year of the C++ successor. Some features of D were mentioned in the discussion but D as a candidate was not. Maybe it's time to re-visit the priorities.

Anyways, my post was simply to highlight the issue.

On Thursday, 8 February 2024 at 15:26:16 UTC, kdevel wrote:

>

Elegant and correct is this version:

import std.stdio;

int main()
{
        char[] something = ['a', 'b', 'c'];

        writeln("len: ", something.length);
        writeln("typeid(something.length): ",
                typeid(something.length));

        writeln ("i: -1");
        foreach (i, _; something)
                writeln("i: ", i);
        return 0;
}

But it is still a bit too "clever" in the foreach statement due to the unused variable _.

It has a bigger problem. What happens when I change the code in the loop but forget to change the code outside the loop? This is why people complain about Python's lack of a do/while loop. So no, not elegant.

Additionally, it doesn't address the issue. It still requires me to both realize the issue with comparing an int to length's mystery type, as well as to fix it for the compiler.

(And it's beside the fact that the start value could just as easily be an int (parameter for example) that could take a negative value. This was the case for one of my cases.)

February 08

On Thursday, 8 February 2024 at 16:54:36 UTC, Kevin Bailey wrote:

>

[...]
On Thursday, 8 February 2024 at 15:26:16 UTC, kdevel wrote:

>

Elegant and correct is this version:

import std.stdio;

int main()
{
        char[] something = ['a', 'b', 'c'];

        writeln("len: ", something.length);
        writeln("typeid(something.length): ",
                typeid(something.length));

        writeln ("i: -1");
        foreach (i, _; something)
                writeln("i: ", i);
        return 0;
}

But it is still a bit too "clever" in the foreach statement due to the unused variable _.

It has a bigger problem. What happens when I change the code in the loop but forget to change the code outside the loop?

How exactly is that pseudo index -1 related to the real indices of the array something? This is absolutely not clear to me. I simply don't see what problem you are trying to solve.

February 09

On Thursday, 8 February 2024 at 16:54:36 UTC, Kevin Bailey wrote:

>

Additionally, it doesn't address the issue. It still requires me to both realize the issue with comparing an int to length's mystery type, as well as to fix it for the compiler.

(And it's beside the fact that the start value could just as easily be an int (parameter for example) that could take a negative value. This was the case for one of my cases.)

It appears that some strongly typed languages like Rust necessitate explicit casting similar to D in this particular case. And some extremely strongly typed languages like Ada requires it to another level.


fn main() {
    let something = vec!['a', 'b', 'c'];

    println!("len: {}", something.len()); // 3

    for i in -1..=something.len() as i32 {
        println!("i: {}", i);
    }
}

Like D, Rust's 'len()' function returns an unsigned integer usize. It has to be cast to int to deal with the -1 index or it will not compile.

 for i in -1..=something.len() {
  |              ^^ the trait `Neg` is not implemented for `usize`

But there are some modern languages in which the length function returns a signed integer by default .. such as Odin. len :: proc(v: Array_Type) -> int {…}. So there is no requirement for casting in Odin in this particular case. An experienced Odin programmer replied to me on the Odin Discord stated: "It is int in the default context, but if the type system sees it is being used in the context of something that wants a uint it will return that."

package main

import "core:fmt"

main :: proc() {
    something := []byte{'a', 'b', 'c'}

    fmt.println("length of 'len(something): ", len(something))
    fmt.printf("type of 'len(something)': %T\n", len(something))  // int
    for i := -1; i < len(something); i += 1 {
        fmt.println("i: ", i)
    }
}

Thank you everyone for this interesting discussion on languages and language design.

February 09

On Friday, 9 February 2024 at 02:13:04 UTC, Gary Chike wrote:

Reviewing the default return type in a couple more newer languages for the length function or equivalent. (len(), length(), size()):

The Nim language appears to return an int type:

let something = @['a', 'b', 'c']

echo("len: ", something.len) # 3
echo("type: ", typeof(something.len)) # int
for i in -1..something.len.int:
    echo("i: ", i)

The Crystal language appears to return an Int32 type:

something = ['a', 'b', 'c']

puts "len: #{something.size}" # .size returns length
puts typeof(something.size) # Int32
(-1..something.size).each do |i|
    puts "i: #{i}"
end

Interesting to see that the signed integer type has been adopted as the return type for the length function by these newer languages.

February 09

On Friday, 9 February 2024 at 02:55:48 UTC, Gary Chike wrote:

>

On Friday, 9 February 2024 at 02:13:04 UTC, Gary Chike wrote:

I spoke too soon, it appears Zig's default return type for its len() function is: `usize' - similar to Rust.

const std = @import("std");

pub fn main() !void {
    const something = [_]u8{ 'a', 'b', 'c' };

    std.debug.print("len: {d}\n", .{something.len}); // Len: 3
    const len_type = @typeName(@TypeOf(something.len));
    std.debug.print("len type: {s}\n", .{len_type}); // len type: usize

    var i: i32 = -1;
    while (i <= @intCast(i32, something.len)) : (i += 1) {
        std.debug.print("i: {d}\n", .{i});
    }
}

Output:

len: 3
len type: usize
i: -1
i: 0
i: 1
i: 2
i: 3
February 09

Rust, Nim, Zig, Odin…?

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

February 09
Kevin Bailey via Digitalmars-d-learn wrote:
> On Thursday, 8 February 2024 at 08:23:12 UTC, thinkunix wrote:
>>
>> I would never write code like this.
> 
> By all means, please share with us how you would have written that just as elegantly but "correct".

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.

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?
* why use auto which made the type different than what .length is?

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


>> It would also break if the array 'something' had more than int.max elements.
> 
> Then don't cast it to an int. First of all, why didn't you cast it to a long? 

I only "cast(int)something.length" so the type would match the type
that "auto i = -1" would get, which was int, and this was to prevent
comparing incompatible types, which caused the conversion, and the
loop not to execute at all.

As a beginner, I would expect that if you mismatch types, you can
expect bad things to happen, and this is probably true in any language.
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".

scot

February 09

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