bugGNU Octave - Bugs: bug #55523, default argument of anonymous...

 
 

bug #55523: default argument of anonymous function is not bound to value of local variable

Submitted by:  None
Submitted on:  Sun 20 Jan 2019 08:25:07 AM UTC  
 
Category:  Interpreter Severity:  1 - Wish
Priority:  3 - Low Item Group:  Feature Request
Status:  Confirmed Assigned to:  None
Originator Name:  Originator Email:  -email is unavailable-
Open/Closed:  Open Release:  dev
Operating System:  GNU/Linux

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

( Jump to the original submission)

Sat 16 May 2020 03:51:33 AM UTC, comment #9: 

The bug submitter is here.

I think I was wrong in reporting this behavior as bug and I apologize in advance!

The function definition:

function foo (a = b)
  disp (a)
end

When called as foo () is translated to:

function foo ()
  a = b;
  disp (a)
end

It means that the default value expression is evaluated in the context of the function that I think it is compatible with the MATLAB's new argument validation syntax:
https://www.mathworks.com/help/matlab/matlab_prog/function-argument-validation-1.html

In the argument validation syntax we can define a default value and it is evaluated in the context of the function and it can be any "constant" or "expression".

In the case of nested function:

function bar ()
  a = 1;
  k = 7;

  function foo (a = a)
  end

  foo ()
end

It is evaluated as:

function bar ()
a = 1;
k = 7;

function foo ()
  - "a" and "k" are/can be captured from the nesting scope
  - define local variable "a" (it gets undefined value)
     and it hides the "a" that is in the nesting scope
  - "a = a" now should be no-op operation but because we
     assigning undefined value to a variable an error
     message is shown.
end

foo ()
end

However for some unknown reasons the MATLAB's argument validation syntax is disallowed in nested functions (should the default value in nested functions be prohibited?).

So I think this bug can be closed as it seems that the current  behavior of Octave is OK.

Anonymous
Fri 15 May 2020 08:25:29 PM UTC, comment #8: 

In C++, the initialization value can be the result of a function call or a global variable.  But, of course, global variables have much different semantics in C++.

https://en.cppreference.com/w/cpp/language/default_arguments:

The names used in the default arguments are looked up, checked for accessibility, and bound at the point of declaration, but are executed at the point of the function call...

In any case, I agree that it is probably best to be conservative here and only accept constants as initialization values.

John W. Eaton <jwe>
Project Administrator
Fri 15 May 2020 08:02:05 PM UTC, comment #7: 

FWIW, I wouldn't expect default initialization to work if the RHS was not a constant.

Also, it wouldn't make much sense.  If there is a default assignment such as "foo (a = b)" and you want to change the value that the function foo is called with, then just call foo() with that value.  There is no reason to change the value of b, to in turn change the value of a, to in turn call the function foo() with the specific value.

Rik <rik5>
Project Administrator
Thu 14 May 2020 09:21:33 PM UTC, comment #6: 

I think the problem with default argument values is a problem with the way functions are called and is not specific to anonymous functions.  For example, I see the same problem with an ordinary function:

octave> function foo (a = b) disp (a), end
octave> b = 1
b = 1
octave> foo ()
error: 'b' undefined near line 1, column 1
error: called from
    foo

If we use a constant or a function call to initialize the argument, then it works:

octave> function foo (a = 13) disp (a), end
octave> foo ()
13

octave> function foo (a = ones(2)) disp (a), end
octave> foo ()
   1   1
   1   1

Maybe I'm wrong about this, but I don't expect the function to capture the default argument values at the time it is parsed.  Instead, I expect the initialization expression to be evaluated at the point of the function call.  Where should the initialization values come from?  I don't think they should be values in the scope of the function itself.

So should we look to find them in the scope where the function call happens?  That makes the evaluation a bit complicated, looking for values in the calling stack frame and storing them in the function stack frame.

Maybe it would be better to limit the initialization values to be either constants or functions?

John W. Eaton <jwe>
Project Administrator
Tue 25 Feb 2020 07:23:40 PM UTC, comment #5: 

Since the segmentation fault is fixed in what will soon be released as version 6.1, I've lowered the severity and retitled the summary to the primary remaining missing feature, that anonymous functions with default arguments don't correctly capture the values of local variables.

Mike Miller <mtmiller>
Project Administrator
Sun 03 Feb 2019 03:32:18 PM UTC, comment #4: 

Adding jwe to the CC list.

The new refactoring of the symbol table and how functions are stored has stopped the segfaults reportedi in this bug report.  However, that is on the development branch which won't become Octave 6.1 for another year.  If there was an easy patch for 5.1 that would be nice.  Otherwise, I have dropped the priority to low since this is a

However, I still think the results of this example are incorrect

octave:11> a = 1;
octave:12> b = 2;
octave:13> %Segmentation fault
octave:13> fb_disp = @(a = b) disp(a);
octave:14> fb_disp();
error: 'b' undefined near line 2 column 17
error: called from
    @<anonymous>

I would have thought that the variable 'b' would have been replaced with the value 2 when the anonymous function was defined.

In terms of compatibility, we don't need to worry.  Matlab doesn't even allow default arguments to anonymous functions.

Rik <rik5>
Project Administrator
Tue 22 Jan 2019 02:09:03 AM UTC, comment #3: 

Confirmed.  It is a corner case so this is unlikely to be fixed in time for the 5.0 release, but hopefully in the first bug fix release that follows it.

Rik <rik5>
Project Administrator
Sun 20 Jan 2019 08:36:10 AM UTC, comment #2: 

I attached a file containing test cases.

(file #46037)

Anonymous
Sun 20 Jan 2019 08:32:56 AM UTC, comment #1: 

Also printing a default argument results in segmentation fault:


a = 1;
b = 2;
%Segmentation fault
fb_disp = @(a = b) disp(a);
fb_disp();


a = 1;
b = 2;
%Segmentation fault
fa_disp = @(a = 3) disp(a);
fa_disp();


a = 1;
b = 2;
%Segmentation fault
fb_pr = @(a = b) printf("%d\n",a);
fb_pr();

Anonymous
Sun 20 Jan 2019 08:25:07 AM UTC, original submission:  

When a default argument of an anonymous handle function is assigned a variable with the same name an error is shown. For example:


a = 1;
b = 2;

%Good
fb = @(a = b) a;
disp(fb());

%Error
fa = @(a = a) a;
disp(fa());

This behavior can be seen in nested functions:


function testfunction()

        a = 1;
        b = 2;

        function ret = fb(a = b)
                ret = a;
        end

        function ret = fa(a = a)
                ret = a;
        end

        disp(fb()); %Good
        disp(fa());        % error: 'a' undefined

end

Anonymous

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #46037:  bug55523.m added by None (1KiB - application/octet-stream - Test cases for the reported bug)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by jwe (Posted a comment)
  • -email is unavailable- added by rik5
  • -email is unavailable- added by rik5 (Posted a comment)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only project members can vote.

     

     

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2020-02-25 mtmiller Severity3 - Normal => 1 - Wish
        Item GroupSegfault, Bus Error, etc. => Feature Request
        Summarysegfault when default argument of anonymous/nested function is the same name as argument => default argument of anonymous function is not bound to value of local variable
    2019-02-03 rik5 Priority5 - Normal => 3 - Low
        Carbon-Copy- => Added jwe
    2019-01-22 rik5 SummaryDefault argument of anonymous/nested function can't be assigned a variable with the same name => segfault when default argument of anonymous/nested function is the same name as argument
    2019-01-22 rik5 StatusNone => Confirmed
        Release4.4.0 => dev
    2019-01-20 None Attached File- => Added bug55523.m, #46037

    Back to the top


    Powered by Savane 3.5