patch 7.4.2044
Problem:    filter() and map() either require a string or defining a function.
Solution:   Support lambda, a short way to define a function that evaluates an
            expression. (Yasuhiro Matsumoto, Ken Takata)
diff --git a/src/testdir/test_alot.vim b/src/testdir/test_alot.vim
index 3074a5c..e9c8439 100644
--- a/src/testdir/test_alot.vim
+++ b/src/testdir/test_alot.vim
@@ -19,6 +19,7 @@
 source test_help_tagjump.vim
 source test_join.vim
 source test_jumps.vim
+source test_lambda.vim
 source test_lispwords.vim
 source test_matchstrpos.vim
 source test_menu.vim
diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim
index b86ca13..ea7abd4 100644
--- a/src/testdir/test_channel.vim
+++ b/src/testdir/test_channel.vim
@@ -95,6 +95,18 @@
   endif
   call assert_equal('got it', g:Ch_responseMsg)
 
+  " Using lambda.
+  let g:Ch_responseMsg = ''
+  call ch_sendexpr(handle, 'hello!', {'callback': {a, b -> Ch_requestHandler(a, b)}})
+  call WaitFor('exists("g:Ch_responseHandle")')
+  if !exists('g:Ch_responseHandle')
+    call assert_false(1, 'g:Ch_responseHandle was not set')
+  else
+    call assert_equal(handle, g:Ch_responseHandle)
+    unlet g:Ch_responseHandle
+  endif
+  call assert_equal('got it', g:Ch_responseMsg)
+
   " Collect garbage, tests that our handle isn't collected.
   call test_garbagecollect_now()
 
@@ -1069,6 +1081,32 @@
   endtry
 endfunc
 
+func Test_out_cb_lambda()
+  if !has('job')
+    return
+  endif
+  call ch_log('Test_out_cb_lambda()')
+
+  let job = job_start(s:python . " test_channel_pipe.py",
+  \ {'out_cb': {ch, msg -> execute("let g:Ch_outmsg = 'lambda: ' . msg")},
+  \ 'out_mode': 'json',
+  \ 'err_cb': {ch, msg -> execute(":let g:Ch_errmsg = 'lambda: ' . msg")},
+  \ 'err_mode': 'json'})
+  call assert_equal("run", job_status(job))
+  try
+    let g:Ch_outmsg = ''
+    let g:Ch_errmsg = ''
+    call ch_sendraw(job, "echo [0, \"hello\"]\n")
+    call ch_sendraw(job, "echoerr [0, \"there\"]\n")
+    call WaitFor('g:Ch_outmsg != ""')
+    call assert_equal("lambda: hello", g:Ch_outmsg)
+    call WaitFor('g:Ch_errmsg != ""')
+    call assert_equal("lambda: there", g:Ch_errmsg)
+  finally
+    call job_stop(job)
+  endtry
+endfunc
+
 """"""""""
 
 let g:Ch_unletResponse = ''
@@ -1285,6 +1323,24 @@
   bwipe!
 endfunc
 
+function Ch_test_close_lambda(port)
+  let handle = ch_open('localhost:' . a:port, s:chopt)
+  if ch_status(handle) == "fail"
+    call assert_false(1, "Can't open channel")
+    return
+  endif
+  let g:Ch_close_ret = ''
+  call ch_setoptions(handle, {'close_cb': {ch -> execute("let g:Ch_close_ret = 'closed'")}})
+
+  call assert_equal('', ch_evalexpr(handle, 'close me'))
+  call WaitFor('"closed" == g:Ch_close_ret')
+  call assert_equal('closed', g:Ch_close_ret)
+endfunc
+
+func Test_close_lambda()
+  call ch_log('Test_close_lambda()')
+  call s:run_server('Ch_test_close_lambda')
+endfunc
 
 " Uncomment this to see what happens, output is in src/testdir/channellog.
  call ch_logfile('channellog', 'w')
diff --git a/src/testdir/test_lambda.vim b/src/testdir/test_lambda.vim
new file mode 100644
index 0000000..9e9979b
--- /dev/null
+++ b/src/testdir/test_lambda.vim
@@ -0,0 +1,48 @@
+function! Test_lambda_with_filter()
+  let s:x = 2
+  call assert_equal([2, 3], filter([1, 2, 3], {i, v -> v >= s:x}))
+endfunction
+
+function! Test_lambda_with_map()
+  let s:x = 1
+  call assert_equal([2, 3, 4], map([1, 2, 3], {i, v -> v + s:x}))
+endfunction
+
+function! Test_lambda_with_sort()
+  call assert_equal([1, 2, 3, 4, 7], sort([3,7,2,1,4], {a, b -> a - b}))
+endfunction
+
+function! Test_lambda_with_timer()
+  if !has('timers')
+    return
+  endif
+
+  let s:n = 0
+  let s:timer_id = 0
+  function! s:Foo()
+    "let n = 0
+    let s:timer_id = timer_start(50, {-> execute("let s:n += 1 | echo s:n")}, {"repeat": -1})
+  endfunction
+
+  call s:Foo()
+  sleep 200ms
+  " do not collect lambda
+  call test_garbagecollect_now()
+  let m = s:n
+  sleep 200ms
+  call timer_stop(s:timer_id)
+  call assert_true(m > 1)
+  call assert_true(s:n > m + 1)
+  call assert_true(s:n < 9)
+endfunction
+
+function! Test_lambda_with_partial()
+  let l:Cb = function({... -> ['zero', a:1, a:2, a:3]}, ['one', 'two'])
+  call assert_equal(['zero', 'one', 'two', 'three'], l:Cb('three'))
+endfunction
+
+function Test_lambda_fails()
+  call assert_equal(3, {a, b -> a + b}(1, 2))
+  call assert_fails('echo {a, a -> a + a}(1, 2)', 'E15:')
+  call assert_fails('echo {a, b -> a + b)}(1, 2)', 'E15:')
+endfunc