On 19/10/13 12:01, Nikolay Pavlov wrote:

On Oct 19, 2013 10:05 AM, "Tony Mechelynck"
<[email protected] <mailto:[email protected]>> wrote:
 >
 > On 14/10/13 22:09, ZyX wrote:
 >>
 >> Since request for comments in thread with extended-funcref branch
patches has gone unnoticed I will repost it here. I currently have
somewhat working implementation of lambda functions in this branch and
want to discuss where to move on since any implementation I can imagine
has its downsides. “Somewhat working” implementation I have was done in
one of the easiest ways possible. Here is the doc I have written for new
lambdas:
 >>
 >>
 >>
============================================================================================
 >> lambda                                                  *expr-lambda*
 >> ------
 >> \arg1, ...: expr1       lambda function
 >>
 >> Lambda functions are the lightweight variant of |user-functions|.
Differences
 >> between them are:
 >>
 >> 1. Body of the lambda function is an |expr1| and not a sequence of |Ex|
 >>     commands.
 >> 2. Lambda function does not have its own scope dictionary. It does
have scope
 >>     dictionary for |a:var| though. |l:| scope dictionary is
inherited from the
 >>     place where lambda was defined (thus it is either |g:| scope
dictionary or
 >>     |l:| dictionary of the function that defined the lambda).
 >>     You see, it is poor man closure.
 >> 3. If |a:var| is not found in lambda own scope dictionary it is
searched in
 >>     |a:| scope dictionary of the function where lambda was defined
(if any).
 >>     This does not apply to |a:000|, |a:0|, |a:1|, ... variables.
 >> 4. There are no dictionary lambdas.
 >> 5. Lambda is not globally recorded anywhere like |anonymous-function|.
 >>
 >> NOTE: lambda function records the whole scope dictionary in its body
and also
 >>        |a:| dictionary. That means that extensive generation of
lambdas and
 >>        exporting them outside of generator function may lead to a
huge memory
 >>        overhead.
 >>
============================================================================================
 >>
 >> This is one of the easiest implementation. Commit with this
implementation was pushed to https://bitbucket.org/ZyX_I/vim, branch
extended-funcref-lambdas, but not to the mailing list (implementation is
mostly untested and definitely experimental). I have a few other
suggestion for lambdas:
 >>
 >> 0. Current state.
 >>
 >> Pros:
 >>    1. Simplicity of implementation.
 >>    2. No allocations for l: variables for lambdas.
 >>    3. Has access to a: of the caller.
 >> Cons:
 >>    1. Lambda disallows freeing funccal structure until lambda is
deleted.
 >>    2. No access to a:N variables. Requires modification of
find_var_in_ht to work. This likely may be worked around.
 >>    3. No local variables. Though if one is using expressions it is
hard to manipulate with them.
 >>
 >> 1. Make lambdas have exactly one local dictionary allocated once at
creation. Modify eval7 to copy all used variables to this dictionary on
creation. Arguments still go to a: dictionary allocated on each lambda call.
 >>
 >> Pros:
 >>    1. Does not hold funccal structure.
 >>    2. Only those variables that are actually used will be recorded.
 >>    3. It is a python-like closure.
 >>    4. One less hash allocation compared to calling user function.
 >> Cons:
 >>    1. Requires likely not so trivial modifications of eval7 and also
modification of other eval* to pass down the reference to l: dictionary.
 >>    2. One l: dictionary for all calls. Though if one is using … (see
cons 3. from p. 0.).
 >>    3. No access to a: of the caller (or we will get cons 1. from p. 0.).
 >>
 >> 2. Like above, but arguments go to local dictionary. Dictionary
itself is copied on lambda invocation.
 >>
 >> Pros:
 >>    Same as above.
 >>    4. Copying dictionary should probably be faster then creating and
populating a new one. Needs some profiling.
 >> Cons:
 >>    Same as above.
 >>
 >> 3. Like the current state (0.), but also has its own l: dictionary.
 >>
 >> Pros:
 >>    Same as 0., except for 2.
 >>    4. Own scope where you can place something.
 >>    5. Adds a facility to create user functions that are real
closures (likely, but not necessary, limited to 2 nesting level; no
limit on nesting is a bit harder to implement, but it seems far from hard).
 >> Cons:
 >>    Same as 0., except for 3.
 >>
 >>
 >> // Note about the doc excerpt: anonymous functions are not recorded
anywhere *in extended-funcref branch*.
 >>
 >
 > I don't understand the fundamental difference with setting a variable
to an expression in string form, so that it can later be :execute'd, as
is already done for several options: ":help expr'<Ctrl-D>" shows me ten
of those (not necessarily all different).

Expressions are invalid for :execute. I do not understand how &*expr
options are related.

:execute "let x =" lambda


Note that no string expressions take variable values with them. I am not
much fond of the workaround where expression accesses them from some
global variable.

Why not? I don't see this as a workaround: Write your expression as using an argument with a predetermined name; then

        :let lambda_arg = 123 * 456
        :exe "let result =" lambda
        :unlet lambda_arg " unless it has a persistent meaning
        " one reason to omit the :unlet would be if you want to use
        " the expression several times (possibly from different places)
        " with the same argument (or one that changes less often than
        " the expression is used); or else if the expression
        " modifies its own argument (but the latter would be
        " more appropriate for a full-fledged user function).

or for a number of arguments, the "argument" variable could be a List or a Dictionary instead.

It is bad for GC: generally you cannot know when
expression and attached variables are no longer needed. Globals are
always bad for threading, if this will ever go into vim. It adds a bunch
of unneeded code: generate global name, record value there, put name
into the expression.

What is currently done for 'indentexpr' et al.? Even 'statusline' could be regarded as a kind of "expression" with a peculiar syntax; but of course it needs neither unletting nor garbage collection.

Best regards,
Tony.
--
<joost> Do you mean to say that I can read mail with vi too? ;-)
<Joey> Didn't you know that?
<Joey> :r /var/spool/mail/jk
                -- Seen on #debian-mentors

--
--
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/groups/opt_out.

Raspunde prin e-mail lui