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.