Changelog for Elixir v1.4
April 28, 2018 · View on GitHub
Elixir v1.4 brings new features, enhancements and bug fixes into Elixir. The most notable changes are the addition of the Registry module and the Task.async_stream/3 and Task.async_stream/5 which aid developers in writing concurrent software. Those two features and a couple other improvements are described in detail below followed by the complete list of changes.
Registry
The registry is a local, decentralized and scalable key-value process storage:
- Local because keys and values are only accessible to the current node (opposite to distributed)
- Decentralized because there is no single entity responsible for managing the registry
- Scalable because performance scales linearly with the addition of more cores upon partitioning
A registry is chosen upon start to have unique or duplicate keys. Every key-value pair is associated to the process registering the key. Keys are automatically removed once the owner process terminates.
iex> Registry.start_link(:unique, MyRegistry)
iex> {:ok, _} = Registry.register(MyRegistry, "hello", 1)
iex> Registry.lookup(MyRegistry, "hello")
[{self(), 1}]
With the registry, developers can provide dynamic process names, module-function dispatch or even a local pubsub system. See the Registry documentation for more information.
Syntax coloring
Elixir v1.4 introduces the ability to syntax color inspected data structures:
iex> IO.puts inspect([hello: 1, world: "!"], syntax_colors: [atom: :cyan])
[hello: 1, world: "!"]
Coloring is done with ANSI colors as specified in the IO.ANSI module.
IEx automatically relies on this feature to provide syntax coloring for evaluated shell results. This behaviour can be configured via the :syntax_colors coloring option:
IEx.configure [colors: [syntax_colors: [atom: :cyan, string: :green]]]
To disable coloring altogether, pass an empty list to :syntax_colors.
Calendar
Elixir v1.3 introduced new calendar types. This release continues evolving the Calendar APIs by adding functions for comparing, adding and calculating the difference between types, retrieve the day_of_week/1, check if the current date is a leap_year?/1 and more.
Task.async_stream
When there is a need to traverse a collection of items concurrently, Elixir developers often resort to tasks:
collection
|> Enum.map(&Task.async(SomeMod, :function, [&1]))
|> Enum.map(&Task.await/1)
While the snippet above works fine in many occasions, for large collections it will spawn and run concurrently as many tasks as there are items in the collection.
Task.async_stream/3 and Task.async_stream/5 allows developers to process collections concurrently while controlling the maximum amount of concurrent tasks:
collection
|> Task.async_stream(SomeMod, :function, [], max_concurrency: System.schedulers_online)
The Task.async_stream functions are also lazy, allowing developers to partially consume the stream until a condition is reached. Furthermore, Task.Supervisor.async_stream/4 and Task.Supervisor.async_stream/6 can be used to ensure the concurrent tasks are spawned under a given supervisor.
Application inference
Mix v1.4 now automatically infers the list of applications that are required on runtime from your dependencies list.
In previous Mix versions, most of your dependencies had to be added both to your dependencies list and applications list. Here is how a mix.exs would look like:
def application do
[applications: [:logger, :plug, :postgrex]]
end
def deps do
[{:plug, "~> 1.2"},
{:postgrex, "~> 1.0"}]
end
This was error prone as many developers would not list their dependencies in their applications list.
Mix v1.4 now automatically infers your applications list as long as you leave the :applications key empty. The mix.exs above can be rewritten to:
def application do
[extra_applications: [:logger]]
end
def deps do
[{:plug, "~> 1.2"},
{:postgrex, "~> 1.0"}]
end
With the above, Mix will automatically build your application list based on your dependencies. Applications that are part of Erlang or Elixir that are required at runtime, such as :logger, must be added to the :extra_applications list. All extra applications will be included in the application list.
Finally, if there is a dependency you don't want to include in the application runtime list, you can do so by specifying the runtime: false option:
{:distillery, "> 0.0.0", runtime: false}
We hope this feature provides a more streamlined workflow for developers who are building releases for their Elixir projects.
Mix install from SCM
Mix v1.4 can now install escripts and archives from both Git and Hex, providing you with even more options for distributing Elixir code.
This makes it possible to distribute CLI applications written in Elixir by publishing a package which builds an escript to Hex. ex_doc has been updated to serve as an example of how to use this new functionality.
Simply running:
mix escript.install hex ex_doc
will fetch ex_doc and its dependencies, build them, and then install ex_doc to ~/.mix/escripts (by default). After adding ~/.mix/escripts to your PATH, running ex_doc is as simple as:
ex_doc
You can now also install archives from Hex in this way. Since they are fetched and built on the user's machine, they do not have the same limitations as pre-built archives. However, keep in mind archives run alongside every Mix project, which may lead to conflicts. For this reason, escripts is the preferred format.
It is also possible to install escripts and archives by providing a Git/GitHub repo. See mix help escript.install and mix help archive.install for more details.
v1.4.5 (2017-06-22)
This version includes changes that make Elixir fully compatible with Erlang/OTP 20.
1. Enhancements
Logger
- [Logger] Handle changes to crash reports in OTP 20
2. Bug fixes
Elixir
- [DateTime] Fix
DateTime.from_iso8601/2when offset has no colon - [Registry] Do not leak EXIT messages on
Registry.dispatch/3
v1.4.4 (2017-05-15)
This version includes changes that make Elixir fully compatible with Erlang/OTP 20-rc.1.
1. Bug fixes
Elixir
- [Map] Fix regression on struct update syntax
v1.4.3 (2017-05-15)
This version includes changes that make Elixir fully compatible with Erlang/OTP 20-rc.1.
1. Enhancements
Elixir
- [Kernel] Improve compilation time for modules with many clauses
- [Map] Warn when attempting to override
__struct__key - [Regex] Add
recompile/1andrecompile!/1to ease transition to OTP 20 for archives and stored regexes
Logger
- [Logger.Translator] Handle OTP 20 GenServer log messages
Mix
- [mix compile] Recompile projects if OTP version changes
2. Bug fixes
Elixir
- [Kernel] Fix code generation when non-binary bitstrings are in AST
- [Record] Properly escape fields passed to
defrecord - [Version] Reject leading zeros according to the SemVer spec
ExUnit
- [ExUnit.Diff] Do not fail when comparing maps with nil or boolean keys
IEx
- [IEx.Helpers] Do not log exits on
IEx.Helpers.c/2failures
Mix
- [mix archive.install] Detect proper path on URLs with query strings
- [mix loadpaths] Do not assume all paths in loadpaths exist
v1.4.2 (2017-02-16)
1. Bug fixes
EEx
- [EEx] Support middle expressions on trim mode
Elixir
- [Calendar] Correct typo on Calendar types
- [Kernel] Ensure redefined functions point to the proper source
- [OptionParser] Add
:allow_nonexistent_atomsto support unsafe behaviour prior to v1.4 - [Stream] Allow consuming multiple items from suspended enumerable in
Stream.transform/3 - [String] Incorporate new grapheme rules in Unicode 9
IEx
- [IEx.Autocomplete] Do not crash on aliases which are not known at compile time
Mix
- [Mix.Umbrella] Ensure umbrella projects can depend on other umbrella projects
- [Mix.Archive] Ensure previous archives with
.ezextension are deleted
v1.4.1 (2017-01-26)
1. Bug fixes
Elixir
- [Kernel] Remove warning when making private functions overridable
- [Path] Ensure
Path.join/1returns strings for lists of one element - [Regex] Ensure
Regex.escape/1also escapes-
IEx
- [IEx] Disable ANSI detection for powershell to avoid false positives
Mix
- [Mix.Make] Run
make cleanforerlang.mk - [Mix.Rebar] Support all of rebar3 dependency package declaration
- [Mix.Rebar] Only pass overrides from parent to child in Rebar dep
v1.4.0 (2017-01-05)
1. Enhancements
Elixir
- [Calendar] Add
Date.compare/2,Time.compare/2,NaiveDateTime.compare/2andDateTime.compare/2 - [Calendar] Support
NaiveDateTime.add/3andNaiveDateTime.diff/3for adding seconds (up to microseconds) as well as the difference between two NaiveDateTimes in seconds (up to microseconds) - [Calendar] Add
Date.leap_year?/1andDate.day_of_week/1 - [Calendar] Ensure
Date,TimeandNaiveDateTimeAPIs work with any struct that provides the same set of fields as their respective struct. For example, aNaiveDateTimecan be given toDatesince it contains a superset of the fields in theDatestruct - [Calendar] Add
Time.utc_now/0andNaiveDateTime.utc_now/0 - [Enum] Add
Enum.map_every/2that invokes the given function with every nth item - [Enum] Add
min/2,max/2,min_max/2,min_by/3,max_by/3, andmin_max_by/3that allow a function specifying the default value when the enumerable is empty - [Enum] Introduce
Enum.zip/1to zip multiple entries at once - [Float] Introduce
Float.ratio/1that returns a tuple with the numerator and denominator as integers to retrieve the given float - [GenServer] Log warn on default
handle_info/2implementation - [Inspect] Support syntax coloring via the
:syntax_coloroption - [Integer]
Integer.digits/2now accepts negative integers - [Integer] Add
Integer.mod/2andInteger.floor_div/2 - [IO] Add
:labeloption toIO.inspect/2to help distinguish multipleIO.inspect/2calls. - [Kernel] Recognize merge conflict markers in source and provide a readable error message
- [Kernel] Warn on unused module attributes
- [Kernel] Improve compiler message on unexpected end of line
- [Kernel] Raise
BadBooleanErrorwhen a non-boolean is given on the left-hand side ofand/or - [List] Add
List.pop_at/3 - [List] Add
List.myers_difference/2 - [OptionParser] Expand multi-letter aliases in
OptionParser - [Process] Add
Process.send_after/4 - [Process] Improve error messages on
Process.register/2errors - [Registry] Add a local, decentralized and scalable key-value process storage
- [Stream] Add
Stream.map_every/2that invokes the given function with every nth item - [Stream] Introduce
Stream.zip/1to lazily zip multiple entries at once - [String] Update to Unicode 9.0.0
- [Task] Add
Task.async_stream/3andTask.async_stream/5as well as the supervised versionsTask.Supervisor.async_stream/4andTask.Supervisor.async_stream/6 - [URI] Allow 0 as URI scheme default port
ExUnit
- [ExUnit.Diff] Use red or green background for whitespace-only diffs
- [ExUnit.Doctest] Allow inspected structures with multiples lines and unicode characters in the doctest result
- [ExUnit.Formatter] Replace lhs/rhs with left/right in the formatter for clarity
IEx
- [IEx.Autocomplete] Stop appending a trailing dot when autocompleting modules in IEx
- [IEx.Autocomplete] Support autocompletion for structs
- [IEx.Autocomplete] Improve IEx autocomplete to support navigating map atom keys
- [IEx.Helpers]
c/1now compiles in memory by default to avoid common issue where.beamfiles remain at projects root directory - [IEx.Helpers] Add info about protocols in
i/1 - [IEx.Server] Support interrupting IEx evaluation through the Ctrl+G prompt
Mix
- [mix archive] Compress archive files built by
mix archiveas they are now unzipped during installation - [mix archive] Install from SCM
- [mix compile] Automatically infer the list of applications for Mix projects
- [mix cmd] Add the ability to specify one or more apps in
mix cmd - [mix deps] Warn if there are non-applications in the
appsdirectory for umbrella projects - [mix deps] Add warning for invalid paths on
mix deps.clean - [mix deps] Add
Mix.Project.apps_pathsthat returns the paths to children applications in umbrella projects - [mix deps] Add
MIX_REBARenvironment variable for overriding local rebar - [mix escript] Install from SCM
- [mix new] Check directory existence in
mix newand ask how to proceed if one exists - [mix new] Applications built with the
--supflag now have an individual module to work as application callback - [mix test] Add
--formatteroption tomix test - [mix xref] Provide "did you mean?" suggestions for
mix xref
2. Bug fixes
Elixir
- [Access] Do not accept nils in
Access.key/1andAccess.key/2in favor of explicit default values (or Access.key!/1 if you expect the key to always be available) - [Float] Avoid multiple roundings in
Float.ceil/2,Float.floor/2andFloat.round/2 - [Kernel] Don't crash in
macro_exported?/3when dealing with Erlang modules - [Kernel] Ensure locals calls are rewritten when calling a local function or macro from inside a module
- [Kernel] Annotate the context for variables as zero-arity funs in quotes
- [Kernel.SpecialForms] Ensure comprehensions with guards and filters keep proper ordering,
- [Kernel.SpecialForms] Produce meaningful warning when with's else clauses have no effect
- [Macro] Wrap fn calls in parens in
Macro.to_string/2 - [Macro] Do not print aliases as keys inside keyword lists in
Macro.to_string/2 - [OptionParser] Support options in
OptionParser.to_argv/2to ensure:countswitches are correctly encoded - [Stream] Ensure
Stream.take/2does not consume next element on:suspend - [String] Fix infinite recursion in
String.replace_leading/3andString.replace_trailing/3when given an empty string - [Task] Fix
Task.shutdown/1,2infinite block when task has no monitor - [Task] Ensure task cannot link after parents unlinks
ExUnit
- [ExUnit] Fix a race condition in
assert_receivewhere we would assert a message was not received but show it in the list of messages when the message is delivered right after the timeout value
IEx
- [IEx.Helpers] Purge consolidated protocols before and after
recompile/0
Mix
- [Mix.Dep] Use
gmakeon FreeBSD instead ofmakewhen compiling make dependencies - [Mix.Project] Only copy files from source when they're newer than destination (for Windows machines)
- [Mix.Task] Ensure non-recursive tasks inside umbrella are reenabled
3. Soft deprecations (no warnings emitted)
Elixir
- [Enum]
Enum.partition/2has been deprecated in favor ofEnum.split_with/2 - [System] Deprecate plural time units in favor of singular ones to align with future Erlang releases
ExUnit
- [ExUnit] Using GenEvent to implement ExUnit formatters is deprecated. Please use the new
GenServerbased formatters instead
4. Deprecations
Elixir
- [Access]
Access.key/1is deprecated due to erratic behaviour for missing keys, please useAccess.key/2instead with proper default values - [Behaviour] The
Behaviourmodule is deprecated. Callbacks may now be defined directly via the@callbackattribute - [Enum] Deprecate
Enum.uniq/2in favor ofEnum.uniq_by/2 - [Float]
Float.to_char_list/2andFloat.to_string/2are deprecated (use the:erlang.float_to_list/2and:erlang.float_to_binary/2functions if such conversions are desired) * [HashDict] TheHashDictmodule is deprecated, in favour of theMap* [HashSet] TheHashDictmodule is deprecated, in favour of theMapSet
* [Kernel] Deprecate support for making private functions overridable. Overridable functions must always be public as they must be contracts - [Kernel] Anonymous functions with no expression after
->, in favor of using an expression or returningnil - [Kernel] Warn if variable is used as a function call
- [OptionParser] Deprecate aliases with multiple letters, such as
-abc - [Set] Deprecation of the
Setmodule in favor ofMapSet - [Stream] Deprecate
Stream.uniq/2in favor ofStream.uniq_by/2
IEx
- [IEx.Helpers]
import_file/2is deprecated in favor ofimport_file_if_available/1
Mix
- [Mix.Utils]
underscore/1andcamelize/1are deprecated in favor ofMacro.underscore/1andMacro.camelize/1
v1.3
The CHANGELOG for v1.3 releases can be found in the v1.3 branch.