https://github.com/kzemek/es6_maps Skip to content Navigation Menu Toggle navigation Sign in * Product + Actions Automate any workflow + Packages Host and manage packages + Security Find and fix vulnerabilities + Codespaces Instant dev environments + Copilot Write better code with AI + Code review Manage code changes + Issues Plan and track work + Discussions Collaborate outside of code Explore + All features + Documentation + GitHub Skills + Blog * Solutions For + Enterprise + Teams + Startups + Education By Solution + CI/CD & Automation + DevOps + DevSecOps Resources + Learning Pathways + White papers, Ebooks, Webinars + Customer Stories + Partners * Open Source + GitHub Sponsors Fund open source developers + The ReadME Project GitHub community articles Repositories + Topics + Trending + Collections * Pricing Search or jump to... Search code, repositories, users, issues, pull requests... Search [ ] Clear Search syntax tips Provide feedback We read every piece of feedback, and take your input very seriously. [ ] [ ] Include my email address so I can be contacted Cancel Submit feedback Saved searches Use saved searches to filter your results more quickly Name [ ] Query [ ] To see all available qualifiers, see our documentation. Cancel Create saved search Sign in Sign up You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session. Dismiss alert {{ message }} kzemek / es6_maps Public * Notifications * Fork 1 * Star 33 * ES6-like shorthand syntax for Elixir maps: `%{foo, bar} = map; IO.puts(foo)` License Apache-2.0 license 33 stars 1 fork Branches Tags Activity Star Notifications * Code * Issues 0 * Pull requests 0 * Actions * Projects 0 * Security * Insights Additional navigation options * Code * Issues * Pull requests * Actions * Projects * Security * Insights kzemek/es6_maps This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository. main BranchesTags Go to file Code Folders and files Name Name Last commit message Last commit date Latest commit History 20 Commits .github .github lib lib test test .formatter.exs .formatter.exs .gitignore .gitignore LICENSE LICENSE NOTICE NOTICE README.md README.md mix.exs mix.exs mix.lock mix.lock View all files Repository files navigation * README * Apache-2.0 license es6_maps CI Module Version Hex Docs License Enables ES6-like shorthand usage of Elixir maps. Why? When writing code that heavily utilizes structures and passes complex objects through multiple layers, it's common to frequently use map literals. This often results in repetitive code patterns such as ctx = %{variable: variable, user: user, ...} or %{variable: variable, user: user, ...} = ctx. I believe that introducing a shorthand form of object creation to Elixir enhances the language's ergonomics and is a natural extension of its existing map literals syntax. This feature will be immediately familiar to JavaScript and Rust developers, and similar shorthands are present in other languages such as Go. Is there any runtime overhead? No; the shorthand map keys compile down to exactly the same bytecode as the "vanilla-style" maps. Installation The package can be installed by adding es6_maps to your list of dependencies and compilers in mix.exs: # mix.exs def project do [ compilers: [:es6_maps | Mix.compilers()], deps: deps() ] end def deps do [ {:es6_maps, "~> 0.2.2", runtime: false} ] end Usage Creating maps iex> {hello, foo, bar} = {"world", 1, 2} iex> %{hello, foo, bar: bar} %{hello: "world", foo: 1, bar: 2} Destructuring maps iex> %{hello, foo} = %{hello: "world", foo: 1, bar: 2} iex> hello "world" iex> foo 1 Updating maps iex> map = %{hello: "world", foo: 1, bar: 2} iex> foo = :baz iex> %{map | foo, bar: :bong} %{hello: "world", foo: :baz, bar: :bong} Structs All of the above work for structs as well: defmodule MyStruct do defstruct [:hello, :foo, :bar] end iex> {foo, bar} = {1, 2} iex> %MyStruct{foo, bar, hello: "world"} %MyStruct{foo: 1, bar: 2, hello: "world"} iex> struct = %MyStruct{foo: 1, bar: 2} iex> hello = "world" iex> %MyStruct{struct | hello} %MyStruct{foo: 1, bar: 2, hello: "world"} iex> %MyStruct{hello} = %MyStruct{hello: "world", foo: 1} iex> hello "world" Converting existing code to use ES6-style maps es6_maps includes a formatting plugin that will convert your existing map and struct literals into the shorthand style. Add the plugin to .formatter.exs, then call mix format to reformat your code: # .formatter.exs [ plugins: [Es6Maps.Formatter], inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] ] The plugin manipulates the AST, not raw strings, so it's precise and will only change your code by: 1. changing map keys into the shorthand form; 2. reordering map keys so the shorthand form comes first; 3. formatting the results like mix format would. Reverting to the vanilla-style maps The formatting plugin can also be used to revert all of the ES6-style map shorthand uses back to the "vanilla" style. Set the es6_maps: [map_style: :vanilla] option in .formatter.exs, then call mix format to reformat your code: # .formatter.exs [ plugins: [Es6Maps.Formatter], inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], es6_maps: [map_style: :vanilla] ] Formatting pragmas The plugin supports pragmas in the comments to control the formatting. The pragma must be in the form # es6_maps: [map_style: :es6] and can be placed anywhere in the file. The map_style option can be set to :es6 to convert to shorthand form or :vanilla to revert to the vanilla-style maps. The pragma takes effect only on the line following the comment. For example in the code below, the first map will be formatted to the shorthand form, while the second map will be left as is: %{foo, bar: 1} = var # es6_maps: [map_style: :vanilla] %{hello: hello, foo: foo, bar: 1} = var es6_maps: [map_style: :vanilla] option in .formatter.exs can be combined with # es6_maps: [map_style: :es6] comment pragmas. How does it work? es6_maps replaces in runtime the Elixir compiler's elixir_map module. The module's expand_map/4 function is wrapped with a function that replaces map keys %{k} as if they were %{k: k}. After es6_maps runs as one of the Mix compilers, the Elixir compiler will use the replaced functions to compile the rest of the code. Important By the nature of this solution it's tightly coupled to the internal Elixir implementation. The current version of es6_maps should work for Elixir 1.15, 1.16 and the upcoming 1.17 version, but may break in the future. About ES6-like shorthand syntax for Elixir maps: `%{foo, bar} = map; IO.puts(foo)` Topics map syntax elixir es6 shorthand Resources Readme License Apache-2.0 license Activity Stars 33 stars Watchers 3 watching Forks 1 fork Report repository Releases 4 v0.2.2 Latest May 1, 2024 + 3 releases Packages 0 No packages published Languages * Elixir 100.0% Footer (c) 2024 GitHub, Inc. Footer navigation * Terms * Privacy * Security * Status * Docs * Contact * Manage cookies * Do not share my personal information You can't perform that action at this time.