bugGNU Octave - Bugs: bug #57255, "+=" in anonymous...

 
 

bug #57255: "+=" in anonymous function within cell array context should emit an error

Submitter:  Tasos Papastylianou <tpapastylianou>
Submitted:  Mon 18 Nov 2019 10:54:53 AM UTC
   
 
Category:  Interpreter Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Missed Error or Warning
Status:  Fixed Assigned to:  None
Originator Name:  tpapastylianou Open/Closed:  * Closed
Release:  * dev Operating System:  * Any
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Mon 23 Dec 2019 11:16:31 AM UTC, comment #14: 

I added a note about this change to the NEWS file:
http://hg.savannah.gnu.org/hgweb/octave/rev/da3c6aef85fe

Markus Mützel <mmuetzel>
Group administrator
Sat 23 Nov 2019 06:08:29 PM UTC, comment #13: 

Works like a charm now.  Closing report.

Rik <rik5>
Group administrator
Fri 22 Nov 2019 10:40:13 PM UTC, comment #12: 

I pushed the following additional change.

http://hg.savannah.gnu.org/hgweb/octave/rev/bd80e14f268a

John W. Eaton <jwe>
Group administrator
Fri 22 Nov 2019 08:04:19 PM UTC, comment #11: 

The expressions you mentioned in comment #10 are not parsed by Matlab.

The functional versions, however, are accepted.


af = @(x) who (x)
af = @() dir ('some-file')


Even though there is no parse error, the first example doesn't work if you try to invoke the created anonymous function.

Rik <rik5>
Group administrator
Fri 22 Nov 2019 07:40:54 PM UTC, comment #10: 

OK, the problem was that the "x += ..." thing was being recognized as a word list command.  But I don't think Matlab allows those in anonymous functions.  If someone can test, try something like


af = @(x) who x
af = @() dir some-file


If expressions like that are not allowed, then I have a fix in mind, but it is not quite ready to commit.



John W. Eaton <jwe>
Group administrator
Fri 22 Nov 2019 05:44:04 PM UTC, comment #9: 

I misunderstood and must not have tested the correct things.

The parse error messages should all point to the =, OP=, ++, or -- expressions being invalid now and not just say "syntax error".  I'll try to fix that.

John W. Eaton <jwe>
Group administrator
Thu 21 Nov 2019 07:49:50 PM UTC, comment #8: 

I suppose that's fine.  It's odd to me that my second example,


clear all
counter = @() {x += 1 ; }


produces the error about use of an operator in an anonymous function when, in fact, the problem is that x is undefined.  Whereas,


clear all
counter = @() x += 1;


produces only a syntax error.

If it was trivial to fix, I would have them both do the same thing.

Also, just presenting the interpreter with


clear all
x += 1
error: 'x' undefined near line 1, column 1


gives a more meaningful error message.  Is it possible to throw the message from the underlying parse error rather than just "syntax error"?


Rik <rik5>
Group administrator
Thu 21 Nov 2019 06:50:01 PM UTC, comment #7: 

Here is what I see with both changesets from comment #5:


-octave:1> x = 1; f = @() x += 1
error: parse error:

  invalid use of operator += in anonymous function

>>> x = 1; f = @() x += 1
                     ^
verbatim-

John W. Eaton <jwe>
Group administrator
Thu 21 Nov 2019 03:55:28 PM UTC, comment #6: 

This is much better.  See below for the transcript of a testing session in Octave.


octave:1> counter = @() x += 1 ;
error: parse error:

  syntax error

>>> counter = @() x += 1 ;
                      ^
octave:1> counter = @() {x += 1 ; }
error: parse error:

  invalid use of operator += in anonymous function

>>> counter = @() {x += 1 ; }
                     ^


If I could have everything I wanted, it would be that the very clear error message "invalid use of operator" would also be emitted in the first example rather than the vaguer "syntax error".


Rik <rik5>
Group administrator
Thu 21 Nov 2019 01:53:03 AM UTC, comment #5: 

The following changeset should disallow all lvalue references (increment, decrement, and all assignment operators) inside anonymous function expressions:

  http://hg.savannah.gnu.org/hgweb/octave/rev/5e92bff668d6

I also pushed the following additional changeset to improve the error message displayed for '=' used in anonymous functions and make it consistent with the other new error messages:

  http://hg.savannah.gnu.org/hgweb/octave/rev/718845eb3c7a

John W. Eaton <jwe>
Group administrator
Tue 19 Nov 2019 10:36:05 PM UTC, comment #4: 

I think it's fine to have this behavior produce an error.  It is worse to accept, but modify the syntax, without giving the programmer any indication.

Also, as mentioned the motivation was a workaround to handles to nested functions which has already been resolved.

Rik <rik5>
Group administrator
Tue 19 Nov 2019 09:55:22 PM UTC, comment #3: 

In Matlab, assignment is a statemnet, not an expression, and only expressions are allowed in anonymous functions.

Although the error message is not as informative as it could be, we already disallow assignment expressions in anonymous functions.  It seems more of an oversight that the parser accepts expressions that use compound assignment and increment/decremnent operators.

Sorry, but I don't think we should attempt to do anything more here except also generate errors for increment/decrement and compound assignment operators and improve the error message.

John W. Eaton <jwe>
Group administrator
Tue 19 Nov 2019 05:20:16 PM UTC, comment #2: 

Marking as confirmed, and changing the release to "dev" since this will have to be fixed there.

For the original reporter, I would suggest moving up to the development code where handles to nested functions are now supported.  The development branch will become Octave version 6.1 near the end of 2019 / start of 2020 so waiting might also be a possibility.

Incidentally, a bare '+=' fails


octave:15> counter = @() x += 1 ;
error: parse error:

  syntax error

>>> counter = @() x += 1 ;


This seems to be because any variables which are not passed to the anonymous function are substituted with their constant values at the time of the anonymous function creation.  However, one can't substitute a constant for 'x' in the above expression because '+=' does assignment and changes the value of 'x'.

There might be a clue there as to why the interpreter is behaving the way it is when the expression is further wrapped in a cell array.

Adding jwe to the CC list since it will probably require his thinking.

Rik <rik5>
Group administrator
Mon 18 Nov 2019 06:48:12 PM UTC, comment #1: 

Yes, I think this is related to open bug #47676 (which bug #53871 is a duplicate of).

It's very easy to see that the parser is dropping the '+' when it parses the contents of the anonymous function:


>> counter = @() {x += 1;}{end};
>> counter
counter =

@() {x = 1} {end}


Mike Miller <mtmiller>
Group Member
Mon 18 Nov 2019 10:54:53 AM UTC, original submission:  

When evaluating statements with side effects in the context of a cell array, the += operator seems to treat scope differently to the ++ operator and manual incrementation.

E.g. consider the following function:


%%% In file makecounter.m
function counter = makecounter ( StartIndex )
  if nargin == 0; StartIndex = 0; endif
  Index = StartIndex;

  counter = @() {
%   Index = Index + 1;  % Version 1
%   ++Index             % Version 2
%   Index += 1          % Version 3
  }{end};
endfunction
%%% End of file makecounter.m


and suppose you call it at the terminal like so:


counter = makecounter (10);
C = cell (1, 5); for i = 1:5; C{i} = counter(); endfor; C


The three versions output as follows:


  C = { 11, 12, 13, 14, 15 }   # Version 1 - correct
  C = { 11, 12, 13, 14, 15 }   # Version 2 - correct
  C = {  1,  1,  1,  1,  1 }   # Version 3 - incorrect!


This bug may relate to the underlying cause for bugs #52363 and #53871, but here the focus is on anonymous functions / cell scope, so it may be more involved.

Context: I was trying mechanisms to produce closures, which work around octave's current lack of support for handles to nested functions (which is how one would typically produce a closure in matlab). Thankfully, octave supports a) cell arrays whose cells can contain statements with side-effects, and b) chained operations. This allows one to return a valid closure from a 'factory' function, by returning an anonymous function, which: creates a cell, evaluates statements with side effects as consecutive cells in a cell array, and indexes the final cell on the spot as a chained operation, thereby effectively treating it as the return value of the anonymous function.

At first I thought the bug was a side-effect of the fact that the 'Index' variable did not appear on the right hand side explicitly, and therefore did not get to be inherited from its parent scope. The more I think about this now though, even if this is the case, there is no excuse for += returning a different result from the other two versions; therefore I would classify this as a bug.

Tasos Papastylianou <tpapastylianou>

 

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

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mmuetzel (Posted a comment)
  • -email is unavailable- added by jwe (Posted a comment)
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by rik5
  • -email is unavailable- added by tpapastylianou (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 13 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2019-11-23 rik5 StatusReady For Test Fixed
        Open/ClosedOpen Closed
    2019-11-22 jwe StatusIn Progress Ready For Test
    2019-11-22 rik5 StatusReady For Test In Progress
    2019-11-21 jwe Priority2 5 - Normal
        Item GroupIncorrect Result Missed Error or Warning
        StatusConfirmed Ready For Test
    2019-11-19 rik5 Summary&quot;+=&quot; not parsed correctly in anonymous function within cell array context "+=" in anonymous function within cell array context should emit an error
    2019-11-19 rik5 Priority5 - Normal 2
        StatusNone Confirmed
        Release5.1.0 dev
        Summary+= operator behaves differently to manual increment and ++ operator "+=" not parsed correctly in anonymous function within cell array context
        Carbon-Copy- Added jwe

    Back to the top

    Powered by Savane 3.13-02a9.
    Corresponding source code