Nikolay Pavlov wrote:

> >> 2016-07-30 22:17 GMT+03:00 Bram Moolenaar <[email protected]>:
> >> >
> >> > 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)
> >> >
> >> > 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.
> >>
> >> The main problem is that “funcrefs” are not a funcrefs, they are
> >> string keys that will be looked up in a hash with all functions.
> >> extended-funcref was fixing this and a bit more: l̶a̶m̶b̶d̶a̶s̶
> > ̶a̶n̶d̶ anonymous functions were no longer recorded in any global
> >> hash, also allowed using Python callable objects as funcrefs. Do not
> >> remember how I coped/planned to cope with using :function or something
> >> else to print anonymous functions’ body, now I would simply suggest
> >> `get(Fref, 'code')` which will return a list of strings or zero (e.g.
> >> for Python functions), also `get(Fref, 'sid')`, `get(Fref, 'slnum')`
> >> and `scriptpath(sid)` (last one has other use-cases, so `get(Fref,
> >> 'sid')`+`scriptpath(sid)` and not `get(Fref, 'sfile')`).
> >>
> >> If interested, I can try and resurrect this patch in Neovim for
> >> somebody else to port it to Vim. I am not planning to write such big
> >> patches for Vim any more.
> >
> >
> > Yes, the old funcrefs are a bit weird.  Unfortunately we can't just
> > simply switch to references.  I haven't checked your patch recently, but
> > I was wondering if there are any backwards compatibility problems.
> >
> > E.g., currently if a funcref refers to "Bar" it will find the function
> > by that name.  If we would instead have an actual reference, and "Bar"
> > gets redefined, how does it get to point to the new "Bar"?  Well, when
> > redefining it does re-use the function struct, thus it might just work.
> >
> > The problem that brought us here is the opposite, we actually want a
> > reference, even when the function gets redefined.
> 
> It does not and should not get to point to the new Bar. I explicitly
> stated this in the message with the patch, there was a list of
> intentional incompatibilities there (and it is basically what I was
> talking about in the previous my message). extended-funcref can be
> changed to still use function names in most cases, but it limits its
> usefullness to only allowing funcrefs from external (e.g. Python)
> objects (lambdas or partials could’ve been implemented on top of that
> more easily, but since they are already implemented extended-funcref
> gives no advantage).

I'm afraid that changing the behavior of function() will lead to
mysterious bugs.  The way the function is looked up by name is weird and
complex.  I don't really want to touch that, it's unpredictable what
script might break.

> > In the Partial type instead of a function name we could use a pointer to
> > the function.  That saves a lookup by name at least.  Could do this
> > always for lambdas, perhaps also for numbered functions.  Not sure about
> > actual named functions.  We get the problem when "Bar" is redefined, as
> > mentioned above.
> 
> I would consider *current* behaviour a bug:
> 
>     function Bar()
>         return 1
>     endfunction
>     let F = function('Bar')
>     delfunction Bar
>     echo F()  " Error in place of 1
>     function Bar()
>         return 2
>     endfunction
>     echo F()  " 2 in place of 1
> 
> When I reference a function I have specific function in mind and
> “function” here means the whole object and not “whatever happens to
> live in the global hashtab under that name when funcref is called”.
> Actually anybody coming from any language with first-class functions
> would not expect current behaviour of the funcref: function objects
> are immutable in most languages I know (you rarely can use hacks to
> break this, but most of time language provides no possibilities for
> such hacks at all, VimL is one of the exceptions).
> 
> Most of time people see no differences because functions do not get
> redefined or deleted and thus there are no complaints, but in the
> example with closure posted above you see that current behaviour is
> rather unexpected.

The good old function() does not use a real reference, it stores a
function name.  That's all.  Only with the new partial type we can use
an actual reference.  But then the backwards compatibility problems
appear.  I started working on this and already had several tests break.

I think the only way is to add funcref(), which creates a real function
reference.  That's already difficult to make work, because named
functions were not yet reference counted, and now they need to be.

Let me have a go at it, then we can see if some of your patch can still
be used.

-- 
Communication is one of the most compli..., eh, well, it's hard.
You know what I mean.  Not?

 /// 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