The Elixir 1.16 release candidate is out now, and it comes with some compelling improvements to diagnostics, documentation, and a few other enhancements that make Elixir an even better choice for developers.
We'll dive into some of these changes and highlight Elixir's continued focus on developer happiness and community building.
Let's get started!
Better Diagnostics for Compiler Errors in Elixir
We'll begin with the improvements to compiler diagnostics provided in Elixir 1.16. Now, your mix compile
errors come with detailed code snippets that tell you exactly where your code goes wrong.
You'll benefit from these improvements when you have syntax errors, mismatched delimiter errors, and generic compiler errors.
Syntax Errors
First up, you can see below that syntax errors now come with a pointer to exactly where the error happened. Let's say we have the following code:
If you run mix compile
, you'll see a syntax error with an associated code snippet, like this:
Note the ^
pointer to the exact location of the syntax error. With this, it's even easier to quickly spot and correct such errors.
Mismatched Delimiter Errors
Another diagnostic improvement comes with the code snippet representation for MismatchedDelimiterError
occurrences. Given the following code with a mismatched delimiter:
Running mix compile
will now show you the following:
This error includes a display of the code snippet that is causing it, and even highlights the unclosed and mismatched delimiters associated to the MismatchedDelimiterError
.
Other Errors
You'll now see similarly detailed code snippets for all kinds of compiler errors, including errors that describe undefined variables. Let's look at an example of that now.
Given the following code:
Running mix compile
will display the following error:
These improved diagnostics make it even easier for Elixir developers to understand compilation errors, catch and remedy basic mistakes, and write clean and functioning code. These improvements show Elixir's continued focus on developer experience.
ExDoc Content Matures with Elixir
Some of the most exciting changes coming in Elixir 1.16 are the improvements to official Elixir language docs, offered through ExDoc. The "Getting Started" guide from elixir-lang.org has been incorporated into the official Elixir documentation on Hex docs.
While this may not seem too exciting on the surface, it represents a concerted effort to refine and unify official guidance on the Elixir programming language. The language and the community have matured to such a stage that we can better align on official guides like this and provide the best agreed-upon direction for new developers.
Anti-Patterns
In this same vein, the official Elixir docs now include robust content on Elixir anti-patterns. This content is divided into four separate sections, covering code, design, processes, and metaprogramming.
Once again, this content is made possible by the maturity of the Elixir language. As Elixir has grown up, and as adoption and the community have grown, we're at a point where Elixir developers can align on what good and bad Elixir code looks like.
With this extensive guidance in the official docs, including framing context and code samples, Elixir developers have the resources they need to ship clean code that meets generally agreed-upon standards. It will be even easier for experienced and novice Elixir developers alike to write and maintain clean code in various scenarios.
And that's not it for docs enhancements.
ExDoc Cheatsheets In the Official Elixir Docs
The official docs now include an ExDoc cheatsheet for the first time. ExDoc cheatsheets allow developers to author quick, summary-type guides to modules and libraries.
The official Elixir docs now include an Enum module cheatsheet, and that's just the beginning.
Elixir maintainers are looking for more community members to contribute cheatsheets to the official docs. This is a great way for first-timers to get an Elixir language contribution! Get started by opening an issue that outlines what cheatsheet you'd like to add.
Taken together, these docs improvements all point to the maturity of the Elixir language and community and the continued focus on education and support for Elixir newcomers. The official introduction docs, the anti-pattern docs, and the inclusion of cheatsheets provide clear and accessible guidance to Elixir developers at every level. This kind of alignment and clarity makes Elixir even more accessible to novices. At the same time, it empowers experienced Elixir devs to deliver clean, standardized Elixir code that performs well.
More Enhancements
You might be interested in taking advantage of some of the smaller enhancements from this release in your upgraded Elixir apps. Let's explore them briefly now.
The String.replace_invalid/2
Function
First up, there is a new String.replace_invalid/2
function that (you guessed it) lets you replace invalid characters in a string. Let's take a look at an example:
The default behavior is to replace the invalid character with a �
, but you can replace it with any character you like:
This will come in handy if you find yourself processing strings of text from external sources. Such text may contain invalid characters, and identifying and replacing such characters just got a lot easier.
New Functionality for Task.yield_many/2
Next up, let's take a look at the new option you can pass to Task.yield_many
. Previously, you could tell Task.yield_many
to timeout and stop waiting for tasks if a certain time limit was exceeded. Now, you can provoke that same behavior if a certain number of tasks has been reached. You can do so by providing the limit
option.
Let's say you have the following code to spawn ten tasks. Each task will sleep for i
number of seconds and then return a message indicating what happened. Then, we yield each task with its result, and iterate over those {task, result}
tuples to operate on the result by IO.inspect
-ing them:
This code will continue to yield tasks and their results until all the tasks are done or the timeout is exceeded. Now, you can use the limit: task_num
option instead of timeout
, like this:
If we execute our function in IEx, you'll see that the code stops waiting for tasks after just one task is yielded:
If the limit is reached before the default timeout (5000
), or before all the tasks are done, then Task.yield_many
returns immediately without triggering the :on_timeout
behaviour. You can dig further into this functionality in the docs.
This new functionality gives you even more fine-grained control over how your program orchestrates async tasks.
The Logger.levels/0
Function
The last enhancement I'll highlight here is the new Logger.levels/0
function. This function returns the list of all available log levels:
This provides a quick reminder of the levels you can use to configure your logger.
Wrap Up
With the 1.16 release, Elixir continues to be a compelling choice for developers looking for:
- An excellent developer experience
- A welcoming and supportive community
- Strong and opinionated development guidelines
- Powerful language capabilities to meet the needs of various programming scenarios.
The new developments in diagnostics, documentation, and language functionality continue to make Elixir a pleasure to work with. Better, more detailed diagnostic messages for compiler errors show Elixir's emphasis on developer experience, making it easier than ever before to identify and fix these errors.
Improved docs and the addition of the anti-patterns guide empowers both experienced and newbie Elixir devs to write clean and standardized code. And minor language improvements, like the functions we explored above, show Elixir's continued commitment to language excellence.
Happy coding!
P.S. If you'd like to read Elixir Alchemy posts as soon as they get off the press, subscribe to our Elixir Alchemy newsletter and never miss a single post!