Skip to content
/ ion Public

Lightweight utility library for efficient IO data and chardata handling in Elixir

License

Notifications You must be signed in to change notification settings

sabiwara/ion

Repository files navigation

Ion

Ion

Hex Version docs CI

Lightweight utility library for efficient IO data and chardata handling.

TLDR

Interpolation:

# plain string
"#{name}: #{count}."
# IO data (using Ion)
~i"#{name}: #{count}."
# IO data (manual)
[name, " ", to_string(count), ?.]

Joining:

# plain string
Enum.join(integers, "+")
# IO data (using Ion)
Ion.join(integers, "+")
# IO data (manual)
Enum.map_intersperse(integers, "+", &to_string/1)

Map joining:

# plain string
Enum.map_join(users, ", ", fn user -> "#{user.first}.#{user.last}@passione.org" end)
# IO data (using Ion)
Ion.map_join(users, ", ", fn user -> ~i"#{user.first}.#{user.last}@passione.org" end)
# IO data (manual)
Enum.map_intersperse(users, ", ", fn user -> [user.first, ?., user.last, "@passione.org"] end)

Why Ion?

IO data and chardata are one of the secret weapons behind Elixir and Erlang performance when it comes to string processing and IO. Turns out the fastest way to concatenate strings is: avoiding concatenation in the first place!

While it is perfectly possible to handcraft IO data with just the standard library, it can sometimes be tedious, cryptic and error prone. Ion provides a few common recipes which:

  • are drop-in replacements, with APIs consistent with the standard way of building strings
  • reduce the cognitive overhead and make the intent explicit
  • are implemented in an optimal fashion (Ion is fast!)
  • help reducing bugs through better typing (see below)

The examples above illustrate how easy it is to migrate from building strings to building IO data or chardata.

Increased safety

Building IO lists manually or through interspersing is error prone: we need to be careful to cast things that are neither strings nor nested IO data or will end up with invalid data:

iex> as_bytes = Enum.intersperse(100..105, "+")
[100, "+", 101, "+", 102, "+", 103, "+", 104, "+", 105]
iex> IO.iodata_to_binary(as_bytes)
"d+e+f+g+h+i"
# need to make sure we have strings:
iex> Enum.map_intersperse(100..105, "+", &to_string/1) |> IO.iodata_to_binary()
# works just like Enum.join/2:
iex> Ion.join(100..105, "+") |> IO.iodata_to_binary()
"100+101+102+103+104+105"

Performance

Because they are specialized, the join functions should also be faster than interspersing (~1.5x, see the benchmarks folder).

Installation

Ion can be installed by adding Ion to your list of dependencies in mix.exs:

def deps do
  [
    {:ion, "~> 0.1.0"}
  ]
end

Or you can just try it out from iex or an .exs script:

iex> Mix.install([:ion])
:ok
iex> Ion.join(["Hello", :world], ",")
["Hello", ",", "world"]

Documentation can be found at https://hexdocs.pm/ion.

Copyright and License

Ion is licensed under the MIT License.

About

Lightweight utility library for efficient IO data and chardata handling in Elixir

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages