Skip to content

Instantly share code, notes, and snippets.

@tyru
Last active March 3, 2020 05:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tyru/2e7c9f7b68259bb0f3aaa364370c22bd to your computer and use it in GitHub Desktop.
Save tyru/2e7c9f7b68259bb0f3aaa364370c22bd to your computer and use it in GitHub Desktop.
fold() and flatmap() implementation in Vim script
function! s:fold(list, f, init) abort
let ref = {'result': a:init}
return map(copy(a:list), {_,v -> extend(ref, {'result': a:f(ref.result, v)})})[-1].result
endfunction
function! s:fold2(list, f, init) abort
let l = a:list + [a:init]
let end = len(a:list)
return map(l, {i,v -> i is# end ? l[i-1] : a:f(l[i-1], v)})[-1]
endfunction
function! s:flatmap(list, f) abort
let result = []
return map(copy(a:list), {_,v -> extend(result, a:f(v))})[-1]
endfunction
function! s:flatten_dict(dict, value_func) abort
return s:fold(values(a:dict), function('extend'), {})->map({_,v -> a:value_func(v)})
endfunction
let v:errors = []
" s:fold()
for s:f in [funcref('s:fold'), funcref('s:fold2')]
call assert_equal(6, s:f([1,2,3], {acc,v -> acc + v}, 0))
call assert_equal(6, s:f([1,2,3], {acc,v -> acc * v}, 1))
call assert_equal([1,2,3], s:f([1,2,3], {acc,v -> acc + [v]}, []))
call assert_equal([3,2,1], s:f([1,2,3], {acc,v -> [v] + acc}, []))
endfor
" s:flatmap()
call assert_equal([1,2,3,4,5,6], s:flatmap([1,[2,3],4,[5,6]], {v -> type(v) is# v:t_list ? v : [v]}))
call assert_equal([1,3,5], s:flatmap([1,2,3,4,5,6], {v -> v % 2 ? [v] : []}))
" s:flatten_dict()
" https://htsign.hateblo.jp/entry/2020/03/02/122508#comment-26006613529486177
call assert_equal(
\ {'1': '(10)', '2': '(20)', 'bbb': '(BBB)', 'aaa': '(AAA)'},
\ {'a': {'aaa': 'AAA', 'bbb': 'BBB'}, '1':{'1': 10, '2': 20} }->s:flatten_dict({ x -> printf('(%s)', x) })
\)
if !empty(v:errors)
echo v:errors
let v:errors = []
endif
@tyru
Copy link
Author

tyru commented Mar 3, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment