October 24, 2022

On Monday, 24 October 2022 at 14:05:47 UTC, Quirin Schroll wrote:

> >

A more modern one would be:

match (x)
{
    0 => foo();
    3 => bar();
}

Note the lack of need for break.

No. Java re-used the swtich keyword and IMO is correct in doing so. The rest is great as in Java.

IMO match is a much better name than switch, which I didn't find intuitive when I first encountered it, and it only made sense because it was followed by a series of case statements. I would like the above syntax plus

match (x)
{
      0 => &foo;
      3 => &bar;
}

where foo and bar are functions taking one argument, and

match (x)
{
      case(0):
         lines of code
         break;
      3 => &foo;
      4 => bar();
}

No idea if this would be possible/sensible, but it's one of the few things that would be a big improvement when I'm writing D programs.

October 24, 2022

On Monday, 24 October 2022 at 14:39:26 UTC, bachmeier wrote:

>

On Monday, 24 October 2022 at 14:05:47 UTC, Quirin Schroll wrote:

> >

A more modern one would be:

match (x)
{
    0 => foo();
    3 => bar();
}

Note the lack of need for break.

No. Java re-used the swtich keyword and IMO is correct in doing so. The rest is great as in Java.

IMO match is a much better name than switch, which I didn't find intuitive when I first encountered it, and it only made sense because it was followed by a series of case statements. I would like the above syntax plus

match (x)
{
      0 => &foo;
      3 => &bar;
}

where foo and bar are functions taking one argument, and

match (x)
{
      case(0):
         lines of code
         break;
      3 => &foo;
      4 => bar();
}

No idea if this would be possible/sensible, but it's one of the few things that would be a big improvement when I'm writing D programs.

What about:

auto result = switch (x)
{
   0,1,2 => aaa();
   3 => bbb();
   4 => ccc();
   5 => {
        int a = 1+1;
        return a;
   };
   else => 0;
}

If the symbol after switch is not "case" or "default", then the compiler can process it as "enhanced" switch

October 24, 2022
There's a misunderstanding here. @live *does* work in @safe code, and confers benefits.

I oversimplified things by talking about `free`. Of course, `free()` is @system and is not callable from @safe code. But what I am *really* talking about is when a pointer is passed as an argument to a function, is it being "moved" or "copied"?

If it is "copied", that means the caller retains ownership of the pointer. If it is "moved", the caller transfers ownership to the callee. What the callee does with the pointer that was transferred to it is not relevant to the caller.

So,

1. void foo(int* p) => argument is moved to foo(), caller can no longer use it

2. void foo(scope int* p) => argument is copied to foo(), caller retains ownership


If we change the annotations to:

1. void foo(owner int* p) => argument is moved to foo()

2. void foo(borrow int* p) => argument is copied to foo()

it means the same thing. This is why dip1000 is foundational to implementing an ownership/borrowing system.

move == owner == notscope

copy == borrow == scope

If I was smarter, scope would have been spelled "borrow" :-/
October 24, 2022
On Monday, 24 October 2022 at 18:18:52 UTC, Walter Bright wrote:
> There's a misunderstanding here. @live *does* work in @safe code, and confers benefits.
>
[...]
>
> 1. void foo(int* p) => argument is moved to foo(), caller can no longer use it
>
> 2. void foo(scope int* p) => argument is copied to foo(), caller retains ownership

The problem with using @live and @safe together is that (a) you cannot *safely* call a @live function from a non-@live function, or vice-versa (because non-@live functions will not honor the above rules), and (b) as a consequence, changing a function from @safe to @safe @live is a breaking API change.

This means that existing @safe D projects will not be able to adopt @live, and the community will have to build an entirely new @safe @live ecosystem from the ground up in order to see any benefit in practice. The more likely outcome is that D users will stick with their existing @safe codebases (which they've invested time and money in) and ignore @live altogether.

It's a Python 2/Python 3 situation--exactly the kind of thing D wants to avoid.

(Of course, projects written in @system D will be free to adopt @live--but why would they? If they wanted automatic safety checking, they'd already be using @safe.)
October 25, 2022
On 25/10/2022 8:12 AM, Paul Backus wrote:
> This means that existing @safe D projects will not be able to adopt @live, and the community will have to build an entirely new @safe @live ecosystem from the ground up in order to see any benefit in practice. The more likely outcome is that D users will stick with their existing @safe codebases (which they've invested time and money in) and ignore @live altogether.

Right now I'm building up my library infrastructure using @safe and DIP1000.

@live on a memory object sounds very attractive to ensuring memory owned in a data structure/nullable ext. stays alive and won't be deallocated.

But not on a function, that asks far too much of people, so I'm 100% in agreement with Paul over this.
October 24, 2022

On Monday, 24 October 2022 at 01:01:03 UTC, Steven Schveighoffer wrote:

>

Is this a bug? Because I can't do this from @trusted code:

void foo() @trusted
{
    static struct T
    {
        Exception ex;
        ubyte[] buf;
    }

    scope buffer = new ubyte[100];
    T t;

    t.ex = new Exception("hello");
    t.buf = buffer;
    throw t.ex;
}

void main() @safe
{
    foo();
}

Hmm, this looks like it probably should work because of having the @trusted attribute. In a @safe function it'd be right to fail because T t is inferred as scope due to the statement t.buf = buffer;.

However, using @trusted just to accomplish this is asking for trouble. Instead, you should make the function checkably safe:

void foo() @safe
{
    static struct T
    {
        Exception ex;
        ubyte[] buf;
    }

    scope buffer = new ubyte[100];
    T t;

    auto helloEx = new Exception("hello");
    t.ex = helloEx;
    t.buf = buffer;
    throw helloEx;
}

Well, in this example anyway. I understand this is just a simplified example, and @trusted may be necessary with your real problem.

October 24, 2022
On 10/24/2022 12:12 PM, Paul Backus wrote:
> The problem with using @live and @safe together is that (a) you cannot *safely* call a @live function from a non-@live function, or vice-versa (because non-@live functions will not honor the above rules), and (b) as a consequence, changing a function from @safe to @safe @live is a breaking API change.
> 
> This means that existing @safe D projects will not be able to adopt @live, and the community will have to build an entirely new @safe @live ecosystem from the ground up in order to see any benefit in practice. The more likely outcome is that D users will stick with their existing @safe codebases (which they've invested time and money in) and ignore @live altogether.

@live does indeed allow for incremental, function by function use of @live. This is inevitable as using an ownership/borrowing system requires restructuring the algorithms and data structures.

October 24, 2022
On 10/24/2022 12:26 PM, rikki cattermole wrote:
> On 25/10/2022 8:12 AM, Paul Backus wrote:
>> This means that existing @safe D projects will not be able to adopt @live, and the community will have to build an entirely new @safe @live ecosystem from the ground up in order to see any benefit in practice. The more likely outcome is that D users will stick with their existing @safe codebases (which they've invested time and money in) and ignore @live altogether.
> 
> Right now I'm building up my library infrastructure using @safe and DIP1000.
> 
> @live on a memory object sounds very attractive to ensuring memory owned in a data structure/nullable ext. stays alive and won't be deallocated.
> 
> But not on a function, that asks far too much of people, so I'm 100% in agreement with Paul over this.

@live doesn't actually add any *new* semantic behavior to a function. All it does is add checking. This means it can be mixed and matched with non-@live functions as the user sees fit. This is on purpose.

It seems you're suggesting attaching this behavior to the pointer, rather than the function. That means multiple pointer types.

Multiple pointer types have been tried many times. They are attractive in theory, but work out poorly in practice. For example, take:

    char* strcpy(char* dst, char* src);

With two pointer types, now you have 4 implementations of strcpy rather than one. It does not scale.
October 24, 2022
On Monday, 24 October 2022 at 18:18:52 UTC, Walter Bright wrote:
> There's a misunderstanding here. @live *does* work in @safe code, and confers benefits.
>
> I oversimplified things by talking about `free`. Of course, `free()` is @system and is not callable from @safe code. But what I am *really* talking about is when a pointer is passed as an argument to a function, is it being "moved" or "copied"?
>
> If it is "copied", that means the caller retains ownership of the pointer. If it is "moved", the caller transfers ownership to the callee. What the callee does with the pointer that was transferred to it is not relevant to the caller.
>
> So,
>
> 1. void foo(int* p) => argument is moved to foo(), caller can no longer use it
>
> 2. void foo(scope int* p) => argument is copied to foo(), caller retains ownership
>
>
> If we change the annotations to:
>
> 1. void foo(owner int* p) => argument is moved to foo()
>
> 2. void foo(borrow int* p) => argument is copied to foo()
>
> it means the same thing. This is why dip1000 is foundational to implementing an ownership/borrowing system.
>
> move == owner == notscope
>
> copy == borrow == scope
>
> If I was smarter, scope would have been spelled "borrow" :-/

It's never too late, dmd could have a mechanism to fix/convert code automatically
October 24, 2022
On Monday, 24 October 2022 at 20:29:55 UTC, Walter Bright wrote:
> On 10/24/2022 12:12 PM, Paul Backus wrote:
>> The problem with using @live and @safe together is that (a) you cannot *safely* call a @live function from a non-@live function, or vice-versa (because non-@live functions will not honor the above rules), and (b) as a consequence, changing a function from @safe to @safe @live is a breaking API change.
>> 
>> This means that existing @safe D projects will not be able to adopt @live, and the community will have to build an entirely new @safe @live ecosystem from the ground up in order to see any benefit in practice. The more likely outcome is that D users will stick with their existing @safe codebases (which they've invested time and money in) and ignore @live altogether.
>
> @live does indeed allow for incremental, function by function use of @live. This is inevitable as using an ownership/borrowing system requires restructuring the algorithms and data structures.

It is impossible for both of the following statements to be true simultaneously:

1. Existing @safe code can incrementally adopt @live without breaking API changes.
2. @live allows code to be made @safe or @trusted that could previously only be @system.

If (1) is true, then allowing @live functions to do anything a @safe function could not already do would make it possible for memory corruption to occur in @safe code. Therefore, (2) must be false.

If (2) is true, then the argument in my previous message applies, which means that (1) must be false.

Note that DIP 1000 satisfies both (1) and (2)--it can be (and has been!) incrementally adopted without breaking existing APIs, and it allows some previously-@system code to be made @safe or @trusted.