Hi list. I know there was some discussions or implementation of lambda() from before. However, because the necessity is not clear, the discussions was stopped . I hope to make it clear here. Currently, we have two or three functions which is taking an argument to handle items
* sort * map * filter map() take an expr as value to replace items. filter() take an expr as a condition to remain items. We can call them in one liner. And it's verrrrrry useful. :echo map([10, 35, 24], 'v:val . "%"') => ['10%', '35%', '24%'] :echo filter([10, 35, 24], 'v:val < 30') => [10, 24] But sort() is not good. we must have user-defined-function to compare items. And I have frustration to call sort(). See: https://groups.google.com/forum/#!searchin/vim_dev/sort$20lambda/vim_dev/32Wk542f_cs/e4uyhYw_jO4J I suggested that sort() should take an expr string as a condition (or funcref). But discussion was stopped. Maybe, most of users want to use expr as condition like below: :echo sort([10,35,24], 'a:lhs - a:rhs') However, vim had already decided to take second argument as funcref or function name. Many programming languages have lambda()/clojure() to solve this problem. As you know, user-defined-function that called by sort() can't capture local variables in the scope. function! s:compare(lhs, rhs) " want to refer x in s:foo endfunction function! s:foo(arr) let x = 1 return sort(a:arr, function('s:compare')) endfunction If "s:compare" is defined outer of the running script, it can't references the variables at least. * I don't want to write s:complare function just for sort(). * I don't want to write Upper-case variable name to take funcref. * I don't want to call delfunction for needless-function. So I decided to implement lambda() function. This lambda()'s usage is below. :let F = lambda('return a:1 + a:2') :echo F(1, 2) => 3 This lambda() is possible to capture the local scope variables. function! s:foo(y) let x = 1 return lambda('return x + a:y + a:1') endfunction echo s:foo(1)(2) => 4 This lambda() can be taken also for map/filter. :echo map([1, 2, 3], lambda("return a:1 + 1")) => [2, 3, 4] :echo filter([1, 2, 3], lambda("return a:1 + 1")) => [1, 2] :echo sort([10,35,24], lambda("return a:1 - a:2") => [10, 24, 35] It's beautiful because interfaces are unified. As you noticed, this lambda() takes the statements instead of expression. Yes, it is possible to include several lines. let F = lambda(' \ let x = 1 \ return a:1 + x \') echo F(2) => 3 A function that is generated by lambda() have a scope. So you can make auto-increment counter function very easily without tainting s: scope. function! s:counter(x) let x = a:x return lambda(" \ let x += 1 \n \ return x \") endfunction let F = s:counter(0) echo F() => 1 echo F() => 2 echo F() => 3 A function object that is generated by lambda() is managed by GC. So if reference are removed, it will be corrected/deleted by next GC. Currently, lambda() is sandboxed function. But if it's not required, I'll remove the check. This's patch include * implementation * tests * doc (Sorry it's not good english) https://gist.github.com/mattn/50fa1dc854911d5cb797 How about this? - Yasuhiro Matsumoto -- -- 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.
