Ken Takata wrote:

> 2016/7/31 Sun 4:17:46 UTC+9 Bram Moolenaar wrote:
> > Ken Takata wrote:
> > 
> > > 2016/7/30 Sat 5:38:42 UTC+9 Bram Moolenaar wrote:
> > > > Patch 7.4.2120
> > > > Problem:    User defined functions can't be a closure.
> > > > Solution:   Add the "closure" argument. Allow using :unlet on a bound
> > > >             variable. (Yasuhiro Matsumoto, Ken Takata)
> > > > Files:      runtime/doc/eval.txt, src/testdir/test_lambda.vim, 
> > > > src/userfunc.c,
> > > >             src/eval.c src/proto/userfunc.pro
> > > 
> > > I had a report that this patch doesn't work as expected:
> > > 
> > >   function! Foo()
> > >     let x = 0
> > >     function! Bar() closure
> > >       let x += 1
> > >       return x
> > >     endfunction
> > >     return function('Bar')
> > >   endfunction
> > >   
> > >   let Count = Foo()
> > >   echo Count() " => 1
> > >   echo Count() " => 2
> > >   echo Count() " => 3
> > >   
> > >   let Count2 = Foo()
> > >   echo Count() " => 1  (Should be 4)
> 
> I found another problem. The following causes an error:
> 
>       function! Foo()
>         let x = 0
>         function! Bar() closure
>           let x += 1
>           return x
>         endfunction
>         return function('Bar')
>       endfunction
>       
>       let Count = Foo()
>       call test_garbagecollect_now()
>       echo Count() " Cannot access x
> 
> Reference counting was wrong. The following patch fixes the problem:
> https://bitbucket.org/k_takata/vim-ktakata-mq/src/7685fd93bf6a1ea0079d7c7da537dc062a67bc9f/fix-closure-refcount.patch?at=default

I had trouble reproducing this problem.  Looks like Foo() needs to be
called twice.  But then your patch doesn't fix it...

While trying to write a test I also noticed memory access errors when
using :delfunction.

> > Calling Foo() creates a new context in which "x" is set to zero.
> > And a new Bar() is created that uses this "x".  It should not re-use the
> > existing Bar(), it is still in use, being referenced.
> > 
> > Thus where it says:  /* redefine existing function */
> > It should leave that function alone and create a new one.  But the new
> > Bar() must be the one that's found in the global scope.  Thus it's a mix
> > of defining a new function and replacing an existing one.
> 
> Hmm, do you say that this is expected behavior?
> 
> I think Bar() should be an unnamed function like a lambda, and it should not
> overwrite existing Bar().  Bar() should be a local function inside Foo().

Hmm, thus adding "closure" changes how the function is defined?  I don't
think that is a good idea.  It is not what one expects.  If we want
local-scope functions I don't think that adding "closure" is the way to
do that.

> I wrote a patch to fix this:
> https://bitbucket.org/k_takata/vim-ktakata-mq/src/7685fd93bf6a1ea0079d7c7da537dc062a67bc9f/fix-closure.patch?at=default
> 
> Please apply the following patch before the above patch:
> https://groups.google.com/d/msg/vim_dev/xSCXQ0cmnzo/UUfR81o0BgAJ
> 
> fix-closure-refcount.patch is also needed.
> 
> With these patches, "function! Bar() closure" creates an unnamed function
> (internal name: "<closure>N"), and set the Funcref to a local variable "Bar".
> This is a little bit tricky by the counter example works fine.
> What do you think?

I'll have a closer look at the code.

-- 
"I love deadlines.  I especially like the whooshing sound they
make as they go flying by."
                         -- Douglas Adams

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui