kip
ex_cldr Core Team
Unicode libraries - Fun with Unicode (introspection, lookup, sets, guards, transforms...)
Following on from my CLDR lbraries I started work on Unicode transforms. But like everything related to CLDR there is a lot of yak-shaving and rabbit-hole travelling required.
The net result is a bunch of new libraries designed to make it easier to work with Unicode blocks, scripts, categories, properties and sets. These are:
- ex_unicode that introspects a string or code point and tells you a lot more than you probably want to know. Buts is a good building block for other libraries.
- unicode_set supports the Unicode Set syntax and provides the macro
Unicode.Set.match?/2that can be used to build clever guards to match on Unicode blocks, scripts, categories and properties. - unicode_guards uses
ex_unicodeandunicode_setto provide a set of prepackaged unicode-friendly guards. Such asis_upper/1,is_lower/1,is_currency_symbol/1,is_whitespace/1andis_digit/1. - unicode_transform is a work in progress to implement the unicode transform specification and to generate transformation modules.
- unicode_string will be the last part of this series that will provide functions to split and replace strings based upon unicode sets. Work hasn’t yet started but its going to be a fun project.
Unicode sets in particular allow some cool expressions. For example:
require Unicode.Set
# Is a given code point a digit? This is the
# digit `1` in the Thai script
iex> Unicode.Set.match?(?๓, "[[:digit:]]")
true
# What if we want to match on digits, but not Thai digits?
# Use set difference!
iex> Unicode.Set.match?(?๓, "[[:digit:]-[:thai:]]")
false
Since Unicode.Set.match?/2 is a macro, all the work of parsing, extracting code points, doing set operations and generating the guard code is done at compile time. The resulting code runs about 3 to 8 times faster than a regex case. (although of course regex has a much larger problem domain).
Trending in Announcing
You may know https://ui.shadcn.com/, a UI component library for React. I really love it’s design style and components. I’ve built some co...
New
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
The Chelekom project is a library of Phoenix and LiveView components generated via Mix tasks to fit developer needs seamlessly.
One of i...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve.
They are GUI (Emerge) and State management (S...
New
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
Introducing AshStorage! Attachment and file management that slots directly into your resources :smiling_face_with_sunglasses:
I had hope...
New
Other Trending Topics
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
We want to introduce a new native datatype to Erlang: native records. Although replacing all tuple records with native records is not our...
New
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
Introduction
Founded in 2017 by landscape ecologist and fire mitigation expert Harry Statter, Frontline developed the first fully integra...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #elixirconf-us
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #performance
- #security










First 10 of 31 Posts!
tmbb
You should think of renaming your modules so that
Unicode.SetbecomesUnicodeSetinstead, or at leastUnicode.UnicodeSetif you want to make it clear that everything is under theUnicodenamespace. The original name (Unicode.Set) doesn’t play well withaliasing.kip
Added two helpful functions in version 0.2.0 that:
String.split/3andString.replace/3:Generating compiled patterns for String matching
String.split/3andString.replace/3allow for patterns and compiled patterns to be used with compiled patterns being the more performant approach. Unicode Set supports the generation of patterns and compiled patterns:Generating NimbleParsec ranges
The parser generator nimble_parsec allows a list of codepoint ranges as parameters to several combinators. Unicode Set can generate such ranges:
This can be used as shown in the following example:
kip
Good suggestion and will do for the next version.
tmbb
This is very useful. I can use it to add proper support for unicode names in variable in my Elixir lexer
kip
The Unicode consortium today introduced Unicode version 13.0 that adds 5,390 characters, for a total of 143,859 characters. These additions include four new scripts, for a total of 154 scripts, as well as 55 new emoji characters. As a result there are some updates to ex_unicode and related packages.
ex_unicode version 1.4.0 adds support for Unicode 13. It also add some additional derived categories for detecting quote marks of varying kinds (left, right, double, single, ambidextrous, all). Changelog
unicode_set version 0.5.0 adds support for quote-related unicode sets such as
[[:quote_mark:]],[[:quote_mark_left:]],[[:quote_mark_double:]]and so on. Changelogunicode_guards version 0.2.0 adds guards for quote marks. Changelog
is_quote_mark/1is_quote_mark_left/1is_quote_mark_right/1is_quote_mark_ambidextrous/1is_quote_mark_single/1is_quote_mark_double/1Have fun with Unicode!
kip
ex_unicode_set version 0.6.0 is released today with a primary focus to underpin some upcoming basic
unicode regexcapabilities.Enhancements
Unicode sets are now a
%Unicode.Set{}structAdd
Unicode.Set.Sigilimplementingsigil_uAdd support for
String.CharsandInspectprotocolsBug Fixes
Fixes parsing sets to ignore non-encoded whitespace
Fixes intersection and difference set operations for sets that include string ranges like
{abc}kip
Introducing unicode_string which in this initial release implements the Unicode Case Folding algorithm and also provides a case insensitive string matching function.
Unicode.String.equals_ignoring_case?/2has the same performance as callingString.downcase/1on both arguments and comparing with the added benefit of being Unicode aware.Usage: Unicode.String.equals_ignoring_case?/2
Compares two strings in a case insensitive manner.
Case folding is applied to the two string arguments which are then compared with the
==operator.Arguments
string_aandstring_bare two strings to be comparedtypeis the case folding type to be applied. The alternatives are:full,:simpleand:turkic. The default is:full.Returns
trueorfalseNotes
This function applies the Unicode Case Folding algorithm
The algorithm does not apply any treatment to diacritical marks hence “compare strings without accents” is not part of this function.
Examples
kip
Introducing the
Unicode.Regexmodule that leverages all of the unicode sets supported by unicode_set. It is published on hex as unicode_set version 0.7.0.This means you can use the power of
unicode_setin a regular expressions in addition to guard clauses, compiled patterns and the nimble_parsec combinatorutf8_char/2.This works by pre-processing the regular expression and expanding any unicode sets in place before calling
Regex.compile/2.This functionality allows a developer to more fully use the power of the Unicode database, introspecting blocks, scripts, combining classes and a whole lot more.
Examples
Enhancements
Add
Unicode.Set.character_class/1which returns a string compatible withRegex.compile/2. This supports the idea of expanded Unicode Sets being used in standard Elixir/erlang regular expressions and will underpin implementation of Unicode Transforms in the packageunicode_transformAdd
Unicode.Regex.compile/2to pre-process a regex to expand Unicode Sets and the compile it withRegex.compile/2.Unicode.Regex.compile!/2is also added.Bug Fixes
Have fun with Unicode!
kip
Todays’ update is Unicode String version 0.2.0 which adds an implementation of the Unicode Segmentation Algorithm that support the detection of grapheme, word, line and sentence break boundaries.
Next steps
This work will support the next phase of the text library work on part-of-speech tagging which requires word segmentation as a precursor.
This work also marks another milestone. In order to implement the break algorithm I needed to implement Unicode Regular Expressions. That in turn required implementation of Unicode Sets which, finally, required the implementation of Unicode Properties. The standards are implemented across ex_unicode, unicode_set and unicode_string packages.
Its been a long road and, while not finished, the work is sufficiently advanced to be useful.
Examples
kip
Released today is Unicode Set version 0.11.0 which is primarily a bug fix release . The API, test coverage and overall stability is much improved. A version 1.0 can be expected before end of the year.
Two functional improvements may be useful:
Unicode sets for blank, graphic and print
From time-to-time on the forum there is the question “how can I detect if a string or character is printable”. In Unicode this is not a simple matter but Unicode Regular Expressions provide a portable definition of three unicode sets that may prove useful:
Unicode Regular Expressions
Unicode.Regex.compile/2is now largely compliant with the Unicode Regular Expression standard. It operates by expanding unicode sets before compiling in the usual manner withRegex.compile/2.Last Post!
kip
Lots of solid updates to several the Unicode libraries today. Overall they compile faster, run faster and are more conformant to their respective standards.
unicode2.0.0A major release of the base library.
~10x faster lookups, an order of magnitude faster compilation: Category/script/property lookups now use binary search over compact range tables instead of huge generated guard clauses.
unicode_guardslibrary is folded in. The separateunicode_guardspackage is no longer needed and will be retired, The guards (is_upper/1,is_lower/1,is_digit/1,is_whitespace/1, the quotation-mark guards and more) now ship withunicode.Correct derived categories:
:Assigned,:Graph,:Visibleand:Printableare now computed from the current character database rather than stale static tables.:Printablenow matchesString.printable?/1(it previously excluded most of the BMP, including Arabic, CJK and Hangul), and:Assignedpicked up ~16k codepoints.Unicode.CharacterName.to_codepoint/1resolves a character name to its codepoint (loose matching), backed by a compact sorted blob.Fixed UTF‑16/UTF‑32 validation in
Unicode.replace_invalid/3, which previously crashed on any input.unicode_set1.7.0A large correctness pass on UnicodeSet parsing and regex generation, closing many gaps against ICU/TR35. Tested against both standards suggest the implementation is now properly conforming.
Highlights:
\a–\v,\xH,\u{…}/\x{…}including astral, octal,\cX), single-quote quoting,\N{name}resolution (viaunicode2.0),[[^a][^b]]),Is/Inproperty prefixes,unicode_transform1.1.0The pure-Elixir CLDR transform engine now conforms to 99.99% of the official CLDR transform test data, up from ~81% — roughly twenty root-cause fixes across the parser, compiler, engine and resolver. The remaining gaps a real spec ambiguity issues in a few tests in 4 of the 290 transforms.
It also ships a strict CLDR conformance suite driven by ~297k vendored test cases — one test per transform — so the engine’s conformance is measured and guarded on every run.