View Source Ion (Ion v0.1.1)
Lightweight utility library for efficient IO data and chardata handling.
Why Ion
?
See README
.
Examples
IO data and chardata can be easily be built using:
a. interpolation with the ~i
sigil:
iex> import Ion, only: :sigils
iex> ~i"atom: #{:foo}, number: #{12 + 2.35}\n"
["atom: ", "foo", ", number: ", "14.35", 10]
b. joining using join/2
or map_join/3
:
iex> Ion.join(100..103, ",")
[[["100", "," | "101"], "," | "102"], "," | "103"]
iex> Ion.map_join(1..4, ",", & &1 + 100)
[[["101", "," | "102"], "," | "103"], "," | "104"]
Dialyzer
Unfortunately, dialyzer might warn about the use improper lists, which is intentional when building IO data:
List construction (cons) will produce an improper list, because its second argument is binary().
To disable these warnings:
# in the whole module
@dialyzer :no_improper_lists
# specifying function/arity pairs returning IO-data:
@dialyzer {:no_improper_lists, [my_fun: 2, another_one: 1]}
Summary
Functions
@spec iodata_empty?(iodata() | IO.chardata()) :: boolean()
Returns true
if iodata_or_chardata
is empty.
Unlike IO.iodata_length(iodata) == 0
which needs to walk the complete tree,
it will bail early as soon as it finds at least one byte or codepoint.
It should be constant time for most typical outputs, with the exception of atypical cases where the head is a deep nested tree.
Even if IO.iodata_length/1
is a very efficient BIF implemented in C, it has a linear
algorithmic complexity and can become slow on bigger trees.
Examples
iex> Ion.iodata_empty?(["", []])
true
iex> Ion.iodata_empty?(~c"a")
false
iex> Ion.iodata_empty?(["a"])
false
iex> Ion.iodata_empty?(["", [], ["" | "c"]])
false
@spec join(Enumerable.t(data | String.Chars.t()), binary()) :: data when data: iodata() | IO.chardata()
Joins the given enumerable
into IO data or chardata using joiner
as separator.
It is a fast equivalent to Enum.join/2
.
Examples
iex> iodata = Ion.join(1..3)
iex> IO.iodata_to_binary(iodata)
"123"
iex> iodata = Ion.join(1..3, " + ")
iex> IO.iodata_to_binary(iodata)
"1 + 2 + 3"
@spec map_join(Enumerable.t(element), binary(), (element -> data | String.Chars.t())) :: data when data: iodata() | IO.chardata(), element: term()
Maps and joins the given enumerable
as IO data or chardata, in one pass.
It is a fast equivalent to Enum.map_join/3
.
Examples
iex> iodata = Ion.map_join(1..3, &(&1 * 2))
iex> IO.iodata_to_binary(iodata)
"246"
iex> iodata = Ion.map_join(1..3, " + ", &(&1 * 2))
iex> IO.iodata_to_binary(iodata)
"2 + 4 + 6"
A sigil to build IO data or chardata and avoid string concatenation.
Use import Ion
to use it, or import Ion, only: :sigils
.
This sigil provides a faster version of string interpolation which:
- will build a list with all chunks instead of concatenating them as a string
- will keep interpolated lists and binaries untouched, without any validation or transformation
- will cast anything else using
to_string/1
Works with both IO data and Chardata. See their respective documentation or this guide for more information.
Examples
iex> ~i"atom: #{:foo}, number: #{12 + 2.35}\n"
["atom: ", "foo", ", number: ", "14.35", 10]
The data produced corresponds to the binary that a regular string interpolation would have produced:
iex> IO.iodata_to_binary(~i"atom: #{:foo}, number: #{12 + 2.35}\n")
"atom: foo, number: 14.35\n"
iex> "atom: #{:foo}, number: #{12 + 2.35}\n"
"atom: foo, number: 14.35\n"
Can be used to build chardata too:
iex> chardata = ~i"charlist: #{~c(ジョルノ)}!"
["charlist: ", [12472, 12519, 12523, 12494], 33]
iex> IO.chardata_to_string(chardata)
"charlist: ジョルノ!"