Vim documentation: vital/Data/Optional
main help file
vital/Data/Optional.txt Provide optional value
Maintainer: rhysd <lin90162@yahoo.co.jp>
==============================================================================
CONTENTS Vital.Data.Optional-contents
INTRODUCTION Vital.Data.Optional-introduction
TERM Vital.Data.Optional-term
INTERFACE Vital.Data.Optional-interface
FUNCTIONS Vital.Data.Optional-functions
==============================================================================
INTRODUCTION Vital.Data.Optional-introduction
Vital.Data.Optional represents an optional value. An optional value can be a
valid state (some) or invalid state (none). This is like a Maybe in Haskell,
Option in Scala, std::optional in C++ and so on. An optional value is usually
used as a result of process which may cause an error or as a cache of some
results.
Vim script doesn't have a way to treat a value which may be invalid. Goal of
this library is to provide the way to treat an optional value in a good way.
The implementation of optional value is a List. Empty list means an invalid
value and 1-element list means a valid value. So, some functions for List
like empty() or map() or filter() and so on are also available for an
optional value.
let s:cache = O.none()
function! GetData()
if O.exists(s:cache)
return O.get(s:cache)
endif
let data = DoHeavyProcess()
let s:cache = O.some(data)
return data
endfunction
function! GetInput()
" Returns O.some(an input),
" or returns O.none() if <C-c>
endfunction
function! GetCommandIfExists(arg)
" Returns the detail if `arg` is an existent command
endfunction
" Show the command detail with an input
O.map(GetInput(), { input ->
\ O.map(GetCommandIfExists(input), { command ->
\ execute('echo ' . command)
\ }
\ })
==============================================================================
TERM Vital.Data.Optional-term
{optional} Vital.Data.Optional-term-optional
{optional} is an optional value. It is a List of 0 or 1 element
actually.
{none} Vital.Data.Optional-term-none
An optional value as invalid value.
{some} Vital.Data.Optional-term-some
An optional value which contains a value as valid value.
==============================================================================
INTERFACE Vital.Data.Optional-interface
------------------------------------------------------------------------------
FUNCTIONS Vital.Data.Optional-functions
none() Vital.Data.Optional.none()
Returns an optional value as invalid value ({none}).
some({value}) Vital.Data.Optional.some()
Returns an optional value which contains {value} as valid value
({some}).
new({value}, [{null}]) Vital.Data.Optional.new()
Same as some({value}) usually. If the given {value} is v:null, it
returns none().
Old vim does not have v:null unfortunately. In that case, provide
any values at {null}. It's used instead of v:null.
new(1) == some(1)
new(0) == some(0)
new(v:true) == some(v:true)
new(v:null) == none()
new('hello', 'null') == some(1)
new('null', 'null') == none()
new(v:null, 'null') == none() " v:null is always none
is_optional({value}) Vital.Data.Optional.is_optional()
Returns {value} is an optional value. It actually checks that {value}
is a List of 0 or 1 element.
empty({optional}) Vital.Data.Optional.empty()
Returns whether {optional} has an invalid value or not. If {optional}
has an invalid value, it returns 1.
exists({optional}) Vital.Data.Optional.exists()
Returns whether {optional} has a valid value or not. If {optional}
has a valid value, it returns 1.
set({optional}, {value}) Vital.Data.Optional.set()
Updates {optional} with {value}. The result is a valid optional value
which contains {value}.
unset({optional}, {value}) Vital.Data.Optional.unset()
Removes value which {optional} contains and makes {optional} invalid
value. If {optional} is already invalid, it does nothing.
get({optional}) Vital.Data.Optional.get()
Returns a contained value in {optional}. If {optional} is an invalid
value, it throws an exception. You can catch it by the prefix
"vital: Data.Optional: "
get_or({optional}, {alternative}) Vital.Data.Optional.get_or()
Returns a contained value in {optional}. If {optional} is an invalid
value, it returns the {alternative}'s value instead.
echo O.get_or(O.new(10), { -> -1 }) " 10
echo O.get_or(O.none(), { -> -1 }) " -1
get_unsafe({optional}) Vital.Data.Optional.get_unsafe()
Returns a contained value in {optional}. If {optional} is an invalid
value, the behavior is undefined.
has({optional}, {type}) Vital.Data.Optional.has()
Returns a type of {optional} is {type}. It is expected that {type} is
a result of type(). If {optional} is an invalid value, it always
returns 0.
apply({func}, {args}...) Vital.Data.Optional.apply()
Applies {args} to {func} if all of {args} are valid optional value.
Then it returns the result wrapped as valid optional value.
If any of {args} is an invalid optional value, it doesn't call
{func} and returns an invalid optional value.
This is like Applicative in Haskell.
When any of {args} is not an optional value, it throws an exception.
For example, below is an example to update data in cache.
let s:cache = O.none()
...
function! Update(data, new_value)
" Update a:data with a:new_value
" This function doesn't consider the case when a:data is invalid
endfunction
...
" Update cache only if s:cache has a valid value.
" Below invokes Update(O.get(cache), O.get(new_value)) if s:cache has
" a valid value.
call O.apply(function('Update'), s:cache, O.some(new_value))
map({optional}, {func}) Vital.Data.Optional.map()
Maps content of {optional} by predicate {func}. If content of
{optional} is none, then {func} won't be invoked and none will be
returned.
function! Succ(x)
return a:x + 1
endfunction
echo O.map(O.some(1), function('Succ')) " returns O.some(2)
echo O.map(O.none(), function('Succ')) " returns O.none()
bind({func}, {args}...) Vital.Data.Optional.bind()
Applies {args} to {func} if all of {args} are valid optional value.
Then it returns the result directly. This assumes that {func}'s
arguments doesn't care about an optional value and {func} returns an
optional value.
When any of {args} is not an optional value, it throws an exception.
For example, division with safe way is like below:
function! Div(a, b)
if a:b == 0
return O.none()
endif
return O.some(a:a / a:b)
endfunction
function! Sub(a, b)
return O.some(a:a - a:b)
endfunction
let f = function('Div')
let f2 = function('Sub')
" Below invokes 10 / (2 - 2)
let result = O.bind(f, O.some(10), O.bind(f2, O.some(2), O.some(2)))
echo O.empty(result) " returns 1 because 10 / 0 occurs an error
flat_map({func}, {arg}) vital.Data.Optional.flat_map()
Similar to vital.Data.Optional.bind() for the single argument.
flatten({optional}, [{limit}]) Vital.Data.Optional.flatten()
Flattens a nested from optional values by default.
echo O.flatten(O.some(O.some(10)))
\ == O.some(10)
echo O.flatten(O.some(O.none()))
\ == O.none()
echo O.flatten(O.none())
\ == O.none()
echo O.flatten(O.some(O.some(O.some(10))))
\ == O.some(O.some(10))
Or flattens nests with a specified limit.
echo O.flatten(O.some(O.some(O.some(42))), 2)
\ == O.some(42)
Or fully flattens nests if 0 is specified for the limit.
echo O.flatten(O.none(), 0)
\ == O.none()
echo O.flatten(O.some(O.some(O.some(10))), 0)
\ == O.some(O.some(10))
echo O.flatten(O.some(O.none()), 0)
\ == O.none()
optional({optional}, {if_some}, {if_none})
vital.Data.Optional.optional()
Extracts {optional}. if the {optional} is a {some}, this maps {if_some}
to the {some}. if the {optional} is a {none}, this returns {if_none}'s
result.
echo O.optional(O.some(10),
\ { x -> string(x) },
\ { -> "=)" }
\ )
" 10
echo O.optional(O.none(),
\ { x -> string(x) },
\ { -> "=)" }
\ )
" =)
first({optional_list}) Vital.Data.Optional.first()
Finds a first {some}, or {none} if no {some} is found.
echo O.first([O.none(), O.some('sugar'), O.some('sweat'), O.none()])
" O.some('sugar')
echo O.first([O.none()])
" O.none()
echo O.first([])
" O.none()
last({optional_list}) Vital.Data.Optional.last()
Finds a last {some}, or {none} if no {some} is found.
echo O.last([O.none(), O.some('sugar'), O.some('sweat'), O.none()])
" O.some('sweat')
echo O.last([O.none()])
" O.none()
echo O.last([])
" O.none()
echo({optional}, [{highlight-group}]) Vital.Data.Optional.echo()
Displays an optional value like :echo. The format is "Some(...)" or
"None". If {highlight-group} is specified, it displays a value
with the highlight group. When {optional} is not an optional value,
it throws an exception.
==============================================================================
vim:tw=78:fo=tcq2mM:ts=8:ft=help:norl:noet
top - main help file - tag index