2016-07-31 18:29 GMT+03:00 Bram Moolenaar <[email protected]>:
>
> 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).

>
> 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 rest of the ARMY stand around looking at a loss.]
> INSPECTOR END OF FILM: (picks up megaphone) All right!  Clear off!  Go on!
>                  "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
>
>  /// 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