Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

func-closure を使わない実装 #1

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions autoload/vital/__vital__/Data/List.vim
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ function! s:uniq_by(list, f) abort
call add(result, x)
call add(applied, y)
endif
unlet x y
endfor
return result
endfunction
Expand Down Expand Up @@ -136,10 +137,37 @@ endfunction
" s:sort_expr must be defined as the string expression of the binary function
" before this is called.
" a:a and a:b are used in s:sort_expr .
" @vimlint(EVL103, 1)
function! s:_compare_by_string_expr(a, b) abort
return eval(s:sort_expr)
endfunction
" @vimlint(EVL103, 0)

" Sorts a list using a set of keys generated by mapping the values in the list
" through the given {unary_f}.
function! s:sort_by(list, unary_f) abort
let list = s:zip(a:list, s:map(copy(a:list), a:unary_f))
return map(sort(list, 's:_compare_with'), 'v:val[0]')
endfunction

let s:__number_pair = [type(10), type(10)]
let s:__string_pair = [type(''), type('')]
let s:__list_pair = [type([]), type([])]
let s:__dict_pair = [type({}), type({})]
let s:__function_pair = [type(function('function')), type(function('function'))]
function! s:_compare_with(x, y) abort
let x = a:x[1]
let y = a:y[1]

let type_pair = [type(x), type(y)]
return type_pair ==# s:__number_pair ? s:_basic_comparator(x, y)
\ : type_pair ==# s:__string_pair ? s:_basic_comparator(x, y)
\ : type_pair ==# s:__list_pair ? s:_list_comparator(x, y)
\ : type_pair ==# s:__dict_pair ? 1
\ : type_pair ==# s:__function_pair
\ ? execute('throw "vital: Data.List: sort_by() cannot compare a function and a function"', 1)
\ : execute(printf("throw 'vital: Data.List: sort_by() cannot compare %s and %s'", string(x), string(y)), 1)
endfunction

" The basic comparator for Number and String
function! s:_basic_comparator(x, y) abort
Expand Down Expand Up @@ -310,7 +338,9 @@ function! s:foldl(f, init, xs) abort
let l:Call = s:_get_binary_caller(a:f)
let memo = a:init
for x in a:xs
let memo = l:Call(a:f, [memo, x])
let memo_new = l:Call(a:f, [memo, x])
unlet memo
let memo = memo_new
endfor
return memo
endfunction
Expand Down Expand Up @@ -488,8 +518,9 @@ function! s:group_by(xs, f) abort
let l:Call = s:_get_unary_caller(a:f)

for l:X in a:xs
let key = l:Call(a:f, [l:X])
let key = type(key) isnot type('') ? string(key) : key
let a_key = l:Call(a:f, [l:X])
let key = type(a_key) isnot type('') ? string(a_key) : a_key
unlet a_key

if has_key(result, key)
call add(result[key], l:X)
Expand Down
11 changes: 8 additions & 3 deletions test/Data/List.vimspec
Original file line number Diff line number Diff line change
Expand Up @@ -608,10 +608,15 @@ Describe Data.List
End

It sorts list with given the string expression
let list = ['pineapple', 'orange', 'banana', 'apple']

Assert Equals(List.sort([3, 1, 2], 'a:a - a:b'), [1, 2, 3])
Assert Equals(List.sort(copy(list), 'len(a:a)-len(a:b)'), ['apple', 'orange', 'banana', 'pineapple'])
if v:version > 704 || v:version == 704 && has('patch358')
" sort() is stable after 7.4.358
let list = ['pineapple', 'orange', 'banana', 'apple']
Assert Equals(List.sort(copy(list), 'len(a:a)-len(a:b)'), ['apple', 'orange', 'banana', 'pineapple'])
else
let list = ['pineapple', 'banana', 'apple']
Assert Equals(List.sort(copy(list), 'len(a:a)-len(a:b)'), ['apple', 'banana', 'pineapple'])
endif
End

It sorts list with given the funcref
Expand Down