www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Feedback Thread: DIP 1032--Function pointers and Delegate

reply Mike Parker <aldacron gmail.com> writes:
This is the feedback thread for the first round of Communnity 
Review of DIP 1032, "Function pointers and Delegate Parameters 
Inherit Attributes from Function".

===================================
**THIS IS NOT A DISCUSSION THREAD**

Posts in this thread must adhere to the feedback thread rules 
outlined in the Reviewer Guidelines (and listed at the bottom of 
this post).

https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

That document also provides guidelines on contributing feedback 
to a DIP review. Please read it before posting here. If you would 
like to discuss this DIP, please do so in the discussion thread:

https://forum.dlang.org/post/ovllntpiebixbtrbiuxj forum.dlang.org

==================================

You can find DIP 1032 here:

https://github.com/dlang/DIPs/blob/0c99bd854302ade3e6833080410e9050fddec346/DIPs/DIP1032.md

The review period will end at 11:59 PM ET on April 17, or when I 
make a post declaring it complete. Feedback posted to this thread 
after that point may be ignored.

At the end of this review round, the DIP will be moved into the 
Post-Community Round 1 state. Significant revisions resulting 
from this review round may cause the DIP manager to require 
another round of Community Review, otherwise the DIP will be 
queued for the Final Review.

==================================
Posts in this thread that do not adhere to the following rules 
will be deleted at the DIP author's discretion:

* All posts must be a direct reply to the DIP manager's initial 
post, with only two exceptions:

     - Any commenter may reply to their own posts to retract 
feedback contained in the original post

     - The DIP author may (and is encouraged to) reply to any 
feedback solely to acknowledge the feedback with agreement or 
disagreement (preferably with supporting reasons in the latter 
case)

* Feedback must be actionable, i.e., there must be some action 
the DIP author can choose to take in response to the feedback, 
such as changing details, adding new information, or even 
retracting the proposal.

* Feedback related to the merits of the proposal rather than to 
the contents of the DIP (e.g., "I'm against this DIP.") is 
allowed in Community Review (not Final Review), but must be 
backed by supporting arguments (e.g., "I'm against this DIP 
because..."). The supporting arguments must be reasonable. 
Obviously frivolous arguments waste everyone's time.

* Feedback should be clear and concise, preferably listed as 
bullet points (those who take the time to do an in-depth review 
and provide feedback in the form of answers to the questions in 
this document will receive much gratitude). Information 
irrelevant to the DIP or is not provided in service of clarifying 
the feedback is unwelcome.
Apr 03 2020
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
This is a significant breaking change.

This is very common:
struct S
{
    private int delegate() _dg;
     property void dg(int delegate() newdg)  safe pure nothrow { _dg = 
newdg; }
     property auto dg()  safe pure nothrow inout { return _dg; }
}

The breaking changes and deprecations seems to downplay this scenario, 
reporting a very obscure "save these to a global" scenario.

The D world is full of types that store delegates, with setters and getters.

I would recommend having an opt-in attribute for this. Something like auto:

 safe pure nothrow  nogc
int foo(int delegate() auto dg, int function() auto fp)

There is also no discussion of templates, which infer attributes. What 
happens there? It's more complicated than at first glance, as the 
delegates passed can currently influence the template attribute detection.

e.g.:

T foo(T)(T delegate() dg, T function()) { return dg() + fp(); }

 system nothrow  nogc
{
   int delegate() dg1;
   int function() fp1;
}

 safe pure
{
   int delegate() dg2;
   int function() fp2;
}

foo(dg1, fp1);
foo(dg2, fp2);

Are these different template instantiations? If not, then you can 
ironically turn off delegate/function-pointer inferred attributes by 
making something a template.

-Steve
Apr 03 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 4/3/20 9:08 AM, Steven Schveighoffer wrote:
 T foo(T)(T delegate() dg, T function()) { return dg() + fp(); }
I should clarify this. Since the delegates are provided not as template parameters but with a templated return value, the attributes can be inferred as normal. So this actually isn't an issue. It's more when the template doesn't actually call the delegate or function, e.g.: struct S(T) { T delegate() _dg; void foo(T delegate() dg) { _dg = dg; } } foo can be inferred as safe, nogc, nothrow, pure. What happens to dg? -Steve
Apr 03 2020
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/3/2020 7:01 AM, Steven Schveighoffer wrote:
 On 4/3/20 9:08 AM, Steven Schveighoffer wrote:
 T foo(T)(T delegate() dg, T function()) { return dg() + fp(); }
I should clarify this. Since the delegates are provided not as template parameters but with a templated return value, the attributes can be inferred as normal. So this actually isn't an issue. It's more when the template doesn't actually call the delegate or function, e.g.: struct S(T) {     T delegate() _dg;     void foo(T delegate() dg) { _dg = dg; } } foo can be inferred as safe, nogc, nothrow, pure. What happens to dg? -Steve
Delegate/functionpointer parameters do not infer safe/nogc/pure/nothrow from their use inside the function. They don't do it now, and the dip does not suggest changing that.
Apr 03 2020
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Friday, 3 April 2020 at 10:31:12 UTC, Mike Parker wrote:
 [snip]
I completely disagree with the notion that delegates with conventional syntax should inherit the attributes of the function. First, the code breakage is going to be high relative to the benefit. Second, we are talking about adding a special case to the language semantics, that is likely going to be hard to understand and thus, to learn and remember. If this proposal is changed to only propose this change to `lazy` parameters, it might just be worth considering. `lazy` is already kind of "special" in it's behaviour so I could see the special casing pshycologically easier to accept there. But even there I'm sceptical. What I'm saying next will be off the scope of the DIP, but I say it because of the possibility that the DIP is unintentionally trying to solve the wrong problem. The biggest problem with delegates in attributes is not that they don't infer the attributes from the called function -vice versa! In the ideal world, the called function would infer it's attributes from the delegate, not unlike how `inout` function infers it's return value constness from constness of the `inout` parameter.
Apr 03 2020
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/3/2020 3:23 PM, Dukc wrote:
 I completely disagree with the notion that delegates with conventional syntax 
 should inherit the attributes of the function. First, the code breakage is
going 
 to be high relative to the benefit.
That would only be true if the function never calls the delegate (i.e. it only stores the delegate elsewhere), which does happen but is not the usual use.
 Second, we are talking about adding a 
 special case to the language semantics, that is likely going to be hard to 
 understand and thus, to learn and remember.
On the contrary, it will likely not even be noticed. For example, it only makes sense that a pure function would need its delegate parameters to also be pure so it can call them. It's annoying to have to specify `pure` twice.
 If this proposal is changed to only propose this change to `lazy` parameters,
it 
 might just be worth considering. `lazy` is already kind of "special" in it's 
 behaviour so I could see the special casing pshycologically easier to accept 
 there. But even there I'm sceptical.
The idea is to get rid of the special cases of lazy.
 What I'm saying next will be off the scope of the DIP, but I say it because of 
 the possibility that the DIP is unintentionally trying to solve the wrong 
 problem. The biggest problem with delegates in attributes is not that they
don't 
 infer the attributes from the called function -vice versa! In the ideal world, 
 the called function would infer it's attributes from the delegate, not unlike 
 how `inout` function infers it's return value constness from constness of the 
 `inout` parameter.
Inferring function attributes from the delegate argument is impractical. For example, many delegates are trivial lambda functions, often inferred as pure. But the functions that call those delegates can rarely be pure. In effect, the function would have to be compilable with the *tightest* combination of attributes every time.
May 19 2020
prev sibling next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 3 April 2020 at 10:31:12 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Communnity 
 Review of DIP 1032, "Function pointers and Delegate Parameters 
 Inherit Attributes from Function".

 ===================================
 **THIS IS NOT A DISCUSSION THREAD**

 Posts in this thread must adhere to the feedback thread rules 
 outlined in the Reviewer Guidelines (and listed at the bottom 
 of this post).

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 That document also provides guidelines on contributing feedback 
 to a DIP review. Please read it before posting here. If you 
 would like to discuss this DIP, please do so in the discussion 
 thread:

 https://forum.dlang.org/post/ovllntpiebixbtrbiuxj forum.dlang.org

 ==================================

 You can find DIP 1032 here:

 https://github.com/dlang/DIPs/blob/0c99bd854302ade3e6833080410e9050fddec346/DIPs/DIP1032.md

 The review period will end at 11:59 PM ET on April 17, or when 
 I make a post declaring it complete. Feedback posted to this 
 thread after that point may be ignored.

 At the end of this review round, the DIP will be moved into the 
 Post-Community Round 1 state. Significant revisions resulting 
 from this review round may cause the DIP manager to require 
 another round of Community Review, otherwise the DIP will be 
 queued for the Final Review.

 ==================================
 Posts in this thread that do not adhere to the following rules 
 will be deleted at the DIP author's discretion:

 * All posts must be a direct reply to the DIP manager's initial 
 post, with only two exceptions:

     - Any commenter may reply to their own posts to retract 
 feedback contained in the original post

     - The DIP author may (and is encouraged to) reply to any 
 feedback solely to acknowledge the feedback with agreement or 
 disagreement (preferably with supporting reasons in the latter 
 case)

 * Feedback must be actionable, i.e., there must be some action 
 the DIP author can choose to take in response to the feedback, 
 such as changing details, adding new information, or even 
 retracting the proposal.

 * Feedback related to the merits of the proposal rather than to 
 the contents of the DIP (e.g., "I'm against this DIP.") is 
 allowed in Community Review (not Final Review), but must be 
 backed by supporting arguments (e.g., "I'm against this DIP 
 because..."). The supporting arguments must be reasonable. 
 Obviously frivolous arguments waste everyone's time.

 * Feedback should be clear and concise, preferably listed as 
 bullet points (those who take the time to do an in-depth review 
 and provide feedback in the form of answers to the questions in 
 this document will receive much gratitude). Information 
 irrelevant to the DIP or is not provided in service of 
 clarifying the feedback is unwelcome.
Instead of delegate/function pointer parameters implicitly inheriting all the attributes of the containing function, what if we made it "opt-in" with a single attribute? i.e. safe pure nothrow nogc int foo(int delegate() inherit dg, int function() inherit fp) { return dg() + fp(); } Advantages: 1. No code breakage 2. The developer sees inherit and knows the function/delegate pointer it will contain extra attributes inherited from somewhere else. 3. You can still support the case where you don't want any attributes. Example cases of this would be if you're not calling the pointer yourself, or, maybe the function itself is nothrow but it allows the function/delegate pointers to throw and catches/handles their exceptions without propogating them.
Apr 03 2020
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/3/2020 3:39 PM, Jonathan Marler wrote:
 Instead of delegate/function pointer parameters implicitly inheriting all the 
 attributes of the containing function, what if we made it "opt-in" with a
single 
 attribute? i.e.
 
  safe pure nothrow  nogc
 int foo(int delegate()  inherit dg, int function()  inherit fp)
 {
      return dg() + fp();
 }
 
 Advantages:
 
 1. No code breakage
 2. The developer sees  inherit and knows the function/delegate pointer it will 
 contain extra attributes inherited from somewhere else.
 3. You can still support the case where you don't want any attributes. 
Example 
 cases of this would be if you're not calling the pointer yourself, or, maybe
the 
 function itself is nothrow but it allows the function/delegate pointers to
throw 
 and catches/handles their exceptions without propogating them.
All problems can be solved by adding another attribute. Unfortunately, this winds up with an incomprehensible "attribute soup". The idea is to try to work things out without needing extra attributes. As mentioned in DIP1032, delegates can "opt out" by being declared with an alias type.
May 19 2020
prev sibling next sibling parent reply Jonathan Marler <johnnymarler gmail.com> writes:
On Friday, 3 April 2020 at 10:31:12 UTC, Mike Parker wrote:
 This is the feedback thread for the first round of Communnity 
 Review of DIP 1032, "Function pointers and Delegate Parameters 
 Inherit Attributes from Function".

 ===================================
 **THIS IS NOT A DISCUSSION THREAD**

 Posts in this thread must adhere to the feedback thread rules 
 outlined in the Reviewer Guidelines (and listed at the bottom 
 of this post).

 https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md

 That document also provides guidelines on contributing feedback 
 to a DIP review. Please read it before posting here. If you 
 would like to discuss this DIP, please do so in the discussion 
 thread:

 https://forum.dlang.org/post/ovllntpiebixbtrbiuxj forum.dlang.org

 ==================================

 You can find DIP 1032 here:

 https://github.com/dlang/DIPs/blob/0c99bd854302ade3e6833080410e9050fddec346/DIPs/DIP1032.md

 The review period will end at 11:59 PM ET on April 17, or when 
 I make a post declaring it complete. Feedback posted to this 
 thread after that point may be ignored.

 At the end of this review round, the DIP will be moved into the 
 Post-Community Round 1 state. Significant revisions resulting 
 from this review round may cause the DIP manager to require 
 another round of Community Review, otherwise the DIP will be 
 queued for the Final Review.

 ==================================
 Posts in this thread that do not adhere to the following rules 
 will be deleted at the DIP author's discretion:

 * All posts must be a direct reply to the DIP manager's initial 
 post, with only two exceptions:

     - Any commenter may reply to their own posts to retract 
 feedback contained in the original post

     - The DIP author may (and is encouraged to) reply to any 
 feedback solely to acknowledge the feedback with agreement or 
 disagreement (preferably with supporting reasons in the latter 
 case)

 * Feedback must be actionable, i.e., there must be some action 
 the DIP author can choose to take in response to the feedback, 
 such as changing details, adding new information, or even 
 retracting the proposal.

 * Feedback related to the merits of the proposal rather than to 
 the contents of the DIP (e.g., "I'm against this DIP.") is 
 allowed in Community Review (not Final Review), but must be 
 backed by supporting arguments (e.g., "I'm against this DIP 
 because..."). The supporting arguments must be reasonable. 
 Obviously frivolous arguments waste everyone's time.

 * Feedback should be clear and concise, preferably listed as 
 bullet points (those who take the time to do an in-depth review 
 and provide feedback in the form of answers to the questions in 
 this document will receive much gratitude). Information 
 irrelevant to the DIP or is not provided in service of 
 clarifying the feedback is unwelcome.
I also want to point out that the "Breaking Changes and Deprecations" section is incorrect. > It is possible that a parameter declaration may require that a delegate or function pointer parameter have fewer attributes than the function itself. This would only be possible if the delegate or function pointer was never called, but was ignored or simply stored elsewhere. It's possible that you want the function or delegate pointer to have fewer attributes even when you are calling it. In my other comment I gave the "nothrow" example, where the function itself is nothrow but the function/delegate points can throw. So I wanted to make sure that this use case is also addressed in this section. Another use case off the top of my head is "pure". You could be a pure function yourself, and call non-pure function/delegate pointers so long as they are inside debug blocks. I'm sure there are other cases, the author has oversimplified the breaking changes here.
Apr 03 2020
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/3/2020 3:51 PM, Jonathan Marler wrote:
 I also want to point out that the "Breaking Changes and Deprecations" section
is 
 incorrect.
 
     > It is possible that a parameter declaration may require that a
delegate or 
 function pointer parameter have fewer attributes than the function itself.
This 
 would only be possible if the delegate or function pointer was never called,
but 
 was ignored or simply stored elsewhere.
 
 It's possible that you want the function or delegate pointer to have fewer 
 attributes even when you are calling it.
 
 In my other comment I gave the "nothrow" example, where the function itself is 
 nothrow but the function/delegate points can throw.  So I wanted to make sure 
 that this use case is also addressed in this section.
You are correct.
 Another use case off the top of my head is "pure".  You could be a pure
function 
 yourself, and call non-pure function/delegate pointers so long as they are 
 inside debug blocks.
Yes again.
May 19 2020
prev sibling next sibling parent reply Piotr Mitana <piotr.mitana gmail.com> writes:
In some cases i may want to pass a  system delegate to a  safe 
function (or - more likely - method). The first case that comes 
into my mind is a constructor or setter.

import std;

struct C {
     void delegate() runner;

     this(void delegate() func) pure nothrow  safe  nogc {
         runner = func;
     }

     void run() {
         runner();
     }
}

void main() {
     C c = C(() { writeln("I am not pure!"); });
     c.run();
}

In this case after this DIP constructor either could not be 
marked pure etc (and it definitely is!). or could not accept this 
function pointer.

That limitation could also surface after longer period if I used 
the constructor with pure functions in general, but at some point 
I would need to pass a impure function. I would then need to 
impurify the constructor and every place I've used it so far.

That's why in my opinion either opt-in (like the suggested 
 inherit - but is it a good enough reason to introduce a new 
 attribute and possibly break a specific of UDA with this name?) 
or not at all. I think I could live without this improvement and 
either just mark them all or use a type alias.
Apr 06 2020
parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/6/2020 11:57 PM, Piotr Mitana wrote:
 In some cases i may want to pass a  system delegate to a  safe function (or - 
 more likely - method).
Being able to do that is addressed in #DIP1032 by declaring the delegate type separately.
May 19 2020
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Friday, 3 April 2020 at 10:31:12 UTC, Mike Parker wrote:
 The review period will end at 11:59 PM ET on April 17, or when 
 I make a post declaring it complete. Feedback posted to this 
 thread after that point may be ignored.
This review round has ended. Thanks to everyone who provided feedback.
Apr 19 2020