Thread overview
Syntax ideas for `ref` returning delegate and FP parameters
Apr 10, 2021
Q. Schroll
Apr 10, 2021
Nick Treleaven
Apr 10, 2021
Nick Treleaven
Apr 10, 2021
MoonlightSentinel
Apr 14, 2021
Kagamin
Apr 11, 2021
user1234
Apr 11, 2021
Q. Schroll
Apr 11, 2021
Boris Carvajal
Apr 13, 2021
Dukc
April 10, 2021

Currently in D, one cannot directly express that a function parameter's type is a delegate or function pointer that returns by ref. If you write

void f(ref int delegate() dg) { .. }

then dg will be bound by reference which is probably not what the user likely intended. It is equivalent to:

alias DG = int delegate();
void f(ref DG dg) { .. }

I guess it should be possible to express

alias refDG = ref int delegate();
void f(refDG dg) { .. }

without an alias. The obvious idea is allowing

void f(int delegate() ref dg)

but I really dislike not having ref next to the return type. I guess most users read ref int as a pseudo type, so having them separated is misleading.

Another was a breaking change making ref part of the delegate type when spelled out:

void f(ref int delegate() dg) { .. }

would take dg by copy and typeof(dg) would be ref int delegate(). If you want to take the delegate by reference, use an alias.

A third one that is a little obscure is allowing ref(int) as a syntax for delegate and function pointer return types. Then it would be akin to const int* method() being different from const(int*) method().

Do you guys have any better ideas? I don't really like mine.

April 10, 2021

On Saturday, 10 April 2021 at 14:27:31 UTC, Q. Schroll wrote:

>
alias refDG = ref int delegate();
void f(refDG dg) { .. }

without an alias. The obvious idea is allowing

void f(int delegate() ref dg)

but I really dislike not having ref next to the return type.

I don't mind that. Also this (particularly if std.meta.Alias was in object.d) is a workaround:

void f(Alias!(ref int delegate()) dg);

April 10, 2021

On Saturday, 10 April 2021 at 15:26:16 UTC, Nick Treleaven wrote:

>

void f(Alias!(ref int delegate()) dg);

Actually that doesn't work :-/

April 10, 2021

On Saturday, 10 April 2021 at 14:27:31 UTC, Q. Schroll wrote:

>

A third one that is a little obscure is allowing ref(int) as a syntax for delegate and function pointer return types. Then it would be akin to const int* method() being different from const(int*) method().

That's the best option IMO because it adapts a well known pattern.

>

Do you guys have any better ideas? I don't really like mine.

Maybe allow ref as a postfix?

void foo(int ref delegate() dg) {}

Allthough that looks kinda weird.

April 11, 2021

On Saturday, 10 April 2021 at 14:27:31 UTC, Q. Schroll wrote:

>

Currently in D, one cannot directly express that a function parameter's type is a delegate or function pointer that returns by ref. If you write

void f(ref int delegate() dg) { .. }

then dg will be bound by reference which is probably not what the user likely intended. It is equivalent to:

alias DG = int delegate();
void f(ref DG dg) { .. }

Slightly off topic but very curiously auto ref seems to have for effect to set the function pointer type return as ref rather than the parameter itself

void f(DG/* = int function()*/)(auto ref DG dg) {
    dg()++;
}

ref int a() {
    static int b;
    return b;
}

void main() {
    f(&a);
    assert(a == 1); // passes
}

a bug certainly.

April 11, 2021

On Saturday, 10 April 2021 at 14:27:31 UTC, Q. Schroll wrote:

>

Do you guys have any better ideas? I don't really like mine.

https://github.com/dlang/dmd/pull/10018#issuecomment-504347888

In short, allow putting function/delegate keyword at the beginning like function literals do:

// declaration
function int(char c) fp = function int(char c) { ... };

// also function literal syntax already accepts 'ref' returns
function ref int(char c) fp = function ref int(char c) { ... };

// as parameter
void fun(ref function ref int(char c) fp);
April 11, 2021

On Sunday, 11 April 2021 at 05:44:58 UTC, user1234 wrote:

>

On Saturday, 10 April 2021 at 14:27:31 UTC, Q. Schroll wrote:

>

Currently in D, one cannot directly express that a function parameter's type is a delegate or function pointer that returns by ref. If you write

void f(ref int delegate() dg) { .. }

then dg will be bound by reference which is probably not what the user likely intended. It is equivalent to:

alias DG = int delegate();
void f(ref DG dg) { .. }

Slightly off topic but very curiously auto ref seems to have for effect to set the function pointer type return as ref rather than the parameter itself

void f(DG/* = int function()*/)(auto ref DG dg) {
    dg()++;
}

ref int a() {
    static int b;
    return b;
}

void main() {
    f(&a);
    assert(a == 1); // passes
}

a bug certainly.

No. When doing f(&a), the auto ref boils down to by copy (i.e. no ref) and DG is inferred by IFTI to be int function() ref which can easily be observed using pragma(msg, DG) in f. You can remove auto ref no problem. If you replace the comment by : int function(), you get a compile error, because ref return and value return are incompatible.

April 13, 2021

On Saturday, 10 April 2021 at 14:27:31 UTC, Q. Schroll wrote:

>

Currently in D, one cannot directly express that a function parameter's type is a delegate or function pointer that returns by ref. If you write

void f(ref int delegate() dg) { .. }

then dg will be bound by reference which is probably not what the user likely intended. It is equivalent to:

alias DG = int delegate();
void f(ref DG dg) { .. }

Question to somebody more familiar with grammar specs: is this behaviour enforced by the spec, or is it implementation-defined behaviour?

April 14, 2021

On Saturday, 10 April 2021 at 21:25:07 UTC, MoonlightSentinel wrote:

>

Maybe allow ref as a postfix?

void foo(int ref delegate() dg) {}

Allthough that looks kinda weird.

An obvious solution.
It's composable too:

void foo(int ref delegate() ref delegate() dg) {}