> My personal suggestion on the proposal would be to use `$` as you've said.
> It is a new operator, but it feels expressive to me, and the $ currently has no use in mainstream elixir syntax (its used in ets match specs as a value, not as an operator). I actually am selfishly rooting for this, because then I might be able to do tricky things to allow literal $1 and $$ Elixir syntax in my elixir-to-matchspec compiler <https://github.com/christhekeele/matcha/discussions/61>. On Wednesday, June 28, 2023 at 8:10:37 PM UTC-5 Christopher Keele wrote: > > My personal suggestion on the proposal would be to use `$` as you've > said, and to remove the need for `:` for the case of atoms. > > > Perhaps removing the `:` is a bad idea actually? I see now it removes > the consistency on values. > > I chose to preserve it not only because it is consistent with atom > literals and works well with syntax highlighting today, but also because > leaving the bareword identifier behaviour open would allow extensions to > this functionality down the line. I'm thinking specifically of a struct > field access syntax like: > > uri = URI.parse( > "postgresql://username:password@host:5432/database_name?schema=public") > [$uri.host, $uri.port] > #=> [host: "host", port: 5432] > > However, I wanted to keep the initial proposal simple and focused on the > most commonly desired functionality. > On Wednesday, June 28, 2023 at 8:02:01 PM UTC-5 Christopher Keele wrote: > >> > My personal suggestion on the proposal would be to use `$` as you've >> said >> >> > Either way, let's not lose the momentum on this! >> >> I'm working on a prototype and proposal for exactly that as we speak, but >> for the sake of momentum of the prototype, repurposed the capture operator >> in my initial experimentation. Perhaps I should have framed this as "new >> feature: tagged-variable captures" *first*, and mentioned "overloading >> the capture operator" *as a followup* extension of the proposal *second*, >> instead of the other way around. I got excited by having a working >> prototype with the existing operator I suppose:D >> On Wednesday, June 28, 2023 at 7:50:59 PM UTC-5 zachary....@gmail.com >> wrote: >> >>> Perhaps removing the `:` is a bad idea actually? I see now it removes >>> the consistency on values. Either way, let's not lose the momentum on this! >>> I feel like we can get this over the line (or put the last nails in its >>> coffin for good ) >>> >>> >>> On Wed, Jun 28, 2023 at 8:45 PM, Zach Daniel <zachary....@gmail.com> >>> wrote: >>> >>>> I agree with Paul on the specific operator, however I feel like you've >>>> just done a great thing laying out most if not all of the considerations >>>> we've had on this conversation to date. I know that these conversations >>>> can >>>> get long and sometimes not produce fruit, but I feel like we should try to >>>> chase this down and come to a conclusion on the matter if at all possible. >>>> >>>> My personal suggestion on the proposal would be to use `$` as you've >>>> said, and to remove the need for `:` for the case of atoms. >>>> >>>> %{$foo, $bar} = %{foo: 10, bar: 10} >>>> >>>> %{$"foo", $"bar"} = map >>>> >>>> It is a new operator, but it feels expressive to me, and the $ >>>> currently has no use in mainstream elixir syntax (its used in ets match >>>> specs as a value, not as an operator). That seems like a good solution to >>>> me. >>>> >>>> >>>> On Wed, Jun 28, 2023 at 8:45 PM, Christopher Keele <christ...@gmail.com >>>> > wrote: >>>> >>> > My thoughts on the proposal itself aside, I’d just like to say that I >>>>> think you’ve set a great example of what proposals on this list should >>>>> look >>>>> like. Well done! >>>>> >>>>> Much appreciated! >>>>> >>>>> > I have an almost visceral reaction to the use of capture syntax for >>>>> this though. >>>>> >>>>> > I think calling the `&…` syntax “capture syntax” is actually >>>>> misleading, and only has that name because it can be used to construct >>>>> closures by “capturing” a function name, but it is more accurate to >>>>> consider it closure syntax, in my opinion. >>>>> >>>>> This is a very salient point. How do you feel about introducing a new >>>>> operator for this sugar, such as $:foo? >>>>> On Wednesday, June 28, 2023 at 7:41:05 PM UTC-5 Paul Schoenfelder >>>>> wrote: >>>>> >>>>>> My thoughts on the proposal itself aside, I’d just like to say that I >>>>>> think you’ve set a great example of what proposals on this list should >>>>>> look >>>>>> like. Well done! >>>>>> >>>>>> I have an almost visceral reaction to the use of capture syntax for >>>>>> this though, and I don’t believe any of the languages you mentioned that >>>>>> support field punning do so in this fashion. They all use a similar >>>>>> intuitive syntax where the variable matches the field name, and they >>>>>> don’t >>>>>> make any effort to support string keys. >>>>>> >>>>>> If Elixir is to ever support field punning, I strongly believe it >>>>>> should follow their example. However, there are reasons why Elixir >>>>>> cannot >>>>>> do so due to syntax ambiguities (IIRC). In my mind, that makes any >>>>>> effort >>>>>> to introduce this feature a non-starter, because code should be first >>>>>> and >>>>>> foremost easy to read, and I have yet to see a proposal for this that >>>>>> doesn’t make the code harder to read and understand, including this one. >>>>>> >>>>>> I’d like to have field punning, but by addressing, if possible, the >>>>>> core issue that is blocking it. If that can’t be done, I just don’t >>>>>> think >>>>>> the cost of overloading unrelated syntax is worth it. I think calling >>>>>> the >>>>>> `&…` syntax “capture syntax” is actually misleading, and only has that >>>>>> name >>>>>> because it can be used to construct closures by “capturing” a function >>>>>> name, but it is more accurate to consider it closure syntax, in my >>>>>> opinion. >>>>>> Overloading it to mean capturing things in a more general sense will be >>>>>> confusing for everyone, and would only work in a few restricted forms, >>>>>> which makes it more difficult to teach and learn. >>>>>> >>>>>> That’s my two cents anyway, I think you did a great job with the >>>>>> proposal, but I’m very solidly against it as the solution to the problem >>>>>> being solved. >>>>>> >>>>>> Paul >>>>>> >>>>>> >>>>>> >>>>>> On Wed, Jun 28, 2023, at 7:56 PM, Christopher Keele wrote: >>>>>> >>>>>> This is a formalization of my concept here >>>>>> <https://groups.google.com/g/elixir-lang-core/c/oFbaOT7rTeU/m/BWF24zoAAgAJ>, >>>>>> >>>>>> as a first-class proposal for explicit discussion/feedback, since I now >>>>>> have a working prototype >>>>>> <https://github.com/elixir-lang/elixir/compare/main...christhekeele:elixir:tagged-variable-capture> >>>>>> . >>>>>> >>>>>> *Goal* >>>>>> >>>>>> The aim of this proposal is to support a commonly-requested feature: >>>>>> *short-hand >>>>>> construction and pattern matching of key/value pairs of associative data >>>>>> structures, based on variable names* in the current scope. >>>>>> >>>>>> *Context* >>>>>> >>>>>> Similar shorthand syntax sugar exists in many programming languages >>>>>> today, known variously as: >>>>>> >>>>>> - Field Punning <https://dev.realworldocaml.org/records.html> — >>>>>> OCaml >>>>>> - Record Puns >>>>>> >>>>>> <https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/record_puns.html> >>>>>> >>>>>> — Haskell >>>>>> - Object Property Value Shorthand >>>>>> >>>>>> <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions> >>>>>> >>>>>> — ES6 Javascript >>>>>> >>>>>> This feature has been in discussion for a decade, on this mailing >>>>>> list (1 >>>>>> <https://groups.google.com/g/elixir-lang-core/c/4w9eOeLvt-8/m/WOkoPSMm6kEJ>, >>>>>> >>>>>> 2 >>>>>> <https://groups.google.com/g/elixir-lang-core/c/NoUo2gqQR3I/m/WTpArTGMKSIJ>, >>>>>> >>>>>> 3 >>>>>> <https://groups.google.com/g/elixir-lang-core/c/3XrVXEVSixc/m/NHU2M4QFAQAJ>, >>>>>> >>>>>> 4 >>>>>> <https://groups.google.com/g/elixir-lang-core/c/OvSQkvXxsmk/m/bKKHbBxiCwAJ>, >>>>>> >>>>>> 5 >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/1W-d_XAlBgAJ> >>>>>> , 6 <https://groups.google.com/g/elixir-lang-core/c/oFbaOT7rTeU>) >>>>>> and the Elixir forum (1 >>>>>> <https://elixirforum.com/t/proposal-add-field-puns-map-shorthand-to-elixir/15452>, >>>>>> >>>>>> 2 >>>>>> <https://elixirforum.com/t/shorthand-for-passing-variables-by-name/30583>, >>>>>> >>>>>> 3 >>>>>> <https://elixirforum.com/t/if-you-could-change-one-thing-in-elixir-language-what-you-would-change/19902/17>, >>>>>> >>>>>> 4 >>>>>> <https://elixirforum.com/t/has-map-shorthand-syntax-in-other-languages-caused-you-any-problems/15403>, >>>>>> >>>>>> 5 >>>>>> <https://elixirforum.com/t/es6-ish-property-value-shorthands-for-maps/1524>, >>>>>> >>>>>> 6 >>>>>> <https://elixirforum.com/t/struct-creation-pattern-matching-short-hand/7544>), >>>>>> >>>>>> and has motivated many libraries (1 >>>>>> <https://github.com/whatyouhide/short_maps>, 2 >>>>>> <https://github.com/meyercm/shorter_maps>, 3 >>>>>> <https://hex.pm/packages/shorthand>, 4 >>>>>> <https://hex.pm/packages/synex>). These narrow margins cannot fit >>>>>> the full history of possibilities, proposals, and problems with this >>>>>> feature, and I will not attempt to summarize them all. For context, I >>>>>> suggest reading this mailing list proposal >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/1W-d_XAlBgAJ> >>>>>> >>>>>> and this community discussion >>>>>> <https://elixirforum.com/t/proposal-add-field-puns-map-shorthand-to-elixir/15452> >>>>>> in >>>>>> particular. >>>>>> >>>>>> However, in summary, this particular proposal tries to solve a couple >>>>>> of past sticking points: >>>>>> >>>>>> 1. Atom vs String >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/NoUo2gqQR3I/m/IpZQHbZk4xEJ> >>>>>> >>>>>> key support >>>>>> 2. Visual clarity >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/NBkAVto0BAAJ> >>>>>> >>>>>> that atom/string matching is occurring >>>>>> 3. Limitations of string-based sigil parsing >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/TiZw6xM3BAAJ> >>>>>> 4. Easy confusion >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/WRhXxHDfBAAJ> >>>>>> >>>>>> with tuples >>>>>> >>>>>> I have a working fork of Elixir here >>>>>> <https://github.com/christhekeele/elixir/tree/tagged-variable-capture> >>>>>> where this proposed syntax can be experimented with. Be warned, it is >>>>>> buggy. >>>>>> >>>>>> *Proposal: Tagged Variable Captures* >>>>>> >>>>>> I propose we overload the unary capture operator (*&*) to accept >>>>>> compile-time atoms and strings as arguments, for example *&:foo* and >>>>>> *&"bar"*. This would *expand at compile time* into *a tagged tuple >>>>>> with the atom/string and a variable reference*. For now, I am >>>>>> calling this a *"tagged-variable capture"* to differentiate it from >>>>>> a function capture. >>>>>> >>>>>> For the purposes of this proposal, assume: >>>>>> >>>>>> {foo, bar} = {1, 2} >>>>>> >>>>>> Additionally, >>>>>> >>>>>> - Lines beginning with *# == * indicate what the compiler expands >>>>>> an expression to. >>>>>> - Lines beginning with *# => * represent the result of evaluating >>>>>> that expression. >>>>>> - Lines beginning with *# !> * represent an exception. >>>>>> >>>>>> *Bare Captures* >>>>>> >>>>>> I'm not sure if we should support *bare* tagged-variable capture, >>>>>> but it is illustrative for this proposal, so I left it in my prototype. >>>>>> It >>>>>> would look like: >>>>>> >>>>>> &:foo >>>>>> *# == **{:foo, foo}* >>>>>> *# => *{:foo, 1} >>>>>> &"foo" >>>>>> *# == **{"foo", foo}* >>>>>> *# => *{"foo", 1} >>>>>> >>>>>> If bare usage is supported, this expansion would work as expected in >>>>>> match and guard contexts as well, since it expands before variable >>>>>> references are resolved: >>>>>> >>>>>> {:foo, baz} = &:foo >>>>>> *# == {:foo, baz} = {:foo, foo}* >>>>>> *# => *{:foo, 1} >>>>>> baz >>>>>> *# => *1 >>>>>> >>>>>> *List Captures* >>>>>> >>>>>> Since capture expressions are allowed in lists, this can be used to >>>>>> construct Keyword lists from the local variable scope elegantly: >>>>>> >>>>>> list = [&:foo, &:bar] >>>>>> *# == **list = [{:foo, foo}, {:bar, bar}]* >>>>>> *# => *[foo: 1, bar: 2] >>>>>> >>>>>> This would work with other list operators like *|*: >>>>>> >>>>>> baz = 3 >>>>>> list = [&:baz | list] >>>>>> *# == **list = [**{:baz, baz} **| **list**]* >>>>>> *# => *[baz: 3, foo: 1, bar: 2] >>>>>> >>>>>> And list destructuring: >>>>>> >>>>>> {foo, bar, baz} = {nil, nil, nil} >>>>>> [&:baz, &:foo, &:bar] = list >>>>>> *# == [{:baz, baz}, {:foo, foo}, {:bar, bar}] = list* >>>>>> *# => *[baz: 3, foo: 1, bar: 2] >>>>>> {foo, bar, baz} >>>>>> *# => *{1, 2, 3} >>>>>> >>>>>> *Map Captures* >>>>>> >>>>>> With a small change to the parser, >>>>>> <https://github.com/elixir-lang/elixir/commit/0a4f5376c0f9b4db7d71514d05df6b8b6abc96a9> >>>>>> >>>>>> we can allow this expression inside map literals. Because this >>>>>> expression >>>>>> individually gets expanded into a tagged-tuple before the map >>>>>> associations >>>>>> list as a whole are processed, it allow this syntax to work in all >>>>>> existing >>>>>> map/struct constructs, like map construction: >>>>>> >>>>>> map = %{&:foo, &"bar"} >>>>>> *# == %{:foo => foo, "bar" => bar}* >>>>>> *# => *%{:foo => 1, "bar" => 2} >>>>>> >>>>>> Map updates: >>>>>> >>>>>> foo = 3 >>>>>> map = %{map | &:foo} >>>>>> *# == %{map | :foo => foo}* >>>>>> *# => *%{:foo => 3, "bar" => 2} >>>>>> >>>>>> And map destructuring: >>>>>> >>>>>> {foo, bar} = {nil, nil} >>>>>> %{&:foo, &"bar"} = map >>>>>> *# == %{:foo => foo, "bar" => bar} = map* >>>>>> *# => *%{:foo => 3, "bar" => 2} >>>>>> {foo, bar} >>>>>> *# => *{3, 2} >>>>>> >>>>>> *Considerations* >>>>>> >>>>>> Though just based on an errant thought >>>>>> <https://groups.google.com/g/elixir-lang-core/c/oFbaOT7rTeU/m/BWF24zoAAgAJ> >>>>>> >>>>>> that popped into my head yesterday, I'm unreasonably pleased with how >>>>>> well >>>>>> this works and reads in practice. I will present my thoughts here, >>>>>> though >>>>>> again I encourage you to grab my branch >>>>>> <https://github.com/christhekeele/elixir/tree/tagged-variable-capture>, >>>>>> compile it from source >>>>>> <https://github.com/christhekeele/elixir/tree/tagged-variable-capture#compiling-from-source>, >>>>>> and >>>>>> play with it yourself! >>>>>> >>>>>> *Pro: solves existing pain points* >>>>>> >>>>>> As mentioned, this solves flaws previous proposals suffer from: >>>>>> >>>>>> 1. Atom vs String >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/NoUo2gqQR3I/m/IpZQHbZk4xEJ> >>>>>> key >>>>>> support >>>>>> This supports both. >>>>>> 2. Visual clarity >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/NBkAVto0BAAJ> >>>>>> that >>>>>> atom/string matching is occurring >>>>>> This leverages the appropriate literal in question within the >>>>>> syntax sugar. >>>>>> 3. Limitations of string-based sigil parsing >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/TiZw6xM3BAAJ> >>>>>> This is compiler-expansion-native. >>>>>> 4. Easy confusion >>>>>> >>>>>> <https://groups.google.com/g/elixir-lang-core/c/XxnrGgZsyVc/m/WRhXxHDfBAAJ> >>>>>> with >>>>>> tuples >>>>>> %{&:foo, &"bar"} is very different from {foo, bar}, instead of >>>>>> 1-character different. >>>>>> >>>>>> Additionally, it solves my main complaint with historical proposals: >>>>>> syntax to combine a variable identifier with a literal must either >>>>>> obscure >>>>>> that we are building an identifier, or obscure the key/string typing of >>>>>> the >>>>>> literal. >>>>>> >>>>>> I'm proposing overloading the capture operator rather than >>>>>> introducing a new operator because the capture operator already has a >>>>>> semantic association with messing with variable scope, via the nested >>>>>> integer-based positional function argument syntax (ex *& &1*). >>>>>> >>>>>> By using the capture operator we indicate that we are messing with an >>>>>> identifier in scope, but via a literal atom/string we want to associate >>>>>> with, to get the best of both worlds. >>>>>> >>>>>> *Pro: works with existing code* >>>>>> >>>>>> The capture today operator has well-defined compile-time-error >>>>>> semantics if you try to pass it an atom or a string. All compiling >>>>>> Elixir >>>>>> code today will continue to compile as before. >>>>>> >>>>>> *Pro: works with existing tooling* >>>>>> >>>>>> By overloading an existing operator, this approach works seamlessly >>>>>> for me with the syntax highlighters I have tried it with so far, and >>>>>> reasonable with the formatter. >>>>>> >>>>>> In my experimentation I've found that the formatter wants to rewrite >>>>>> *&:baz >>>>>> *to *(&:baz)* pretty often. That's good, because there are several >>>>>> edge cases in my prototype where not doing so causes it to behave >>>>>> strangely; I'm sure it's resolving ambiguities that would occur in >>>>>> function >>>>>> captures that impact my proposal in ways I have yet fully anticipated. >>>>>> >>>>>> *Pros: minimizes surface area of the language* >>>>>> >>>>>> By overriding the capture operator instead of introducing a new >>>>>> operator or sigil, we are able to keep the surface area of this feature >>>>>> slim. >>>>>> >>>>>> *Cons: overloads the capture operator* >>>>>> >>>>>> Of course, much of the virtues of this proposal comes from >>>>>> overloading the capture operator. But it is an already semantically >>>>>> fraught >>>>>> syntactic sugar construct that causes confusion to newcomers, and this >>>>>> would place more strain on it. >>>>>> >>>>>> We would need to augment it with more than the meager error message >>>>>> modification >>>>>> <https://github.com/elixir-lang/elixir/commit/3d83d21ada860d03cece8c6f90dbcf7bf9e737ec#diff-92b98063d1e86837fae15261896c265ab502b8d556141aaf1c34e67a3ef3717cL199-R207> >>>>>> in >>>>>> my prototype, as well as documentation and anticipate a new wave of >>>>>> questions from the community upon release. >>>>>> >>>>>> This inelegance really shows when considering embedding a tagged >>>>>> variable capture inside an anonymous function capture, ex *& &1 = >>>>>> &:foo*. In my prototype I've chosen to allow this rather than error >>>>>> on "nested captures not allowed" (would probably become: "nested >>>>>> *function* captures not allowed"), but I'm not sure I found all the >>>>>> edge-cases of mixing them in all possible constructions. >>>>>> >>>>>> Additionally, since my proposal now allows the capture operator as an >>>>>> associative element inside map literal parsing, that would change the >>>>>> syntax error reported by providing a function capture as an associative >>>>>> element to be generated during expansion rather than during parsing. I >>>>>> am >>>>>> not fluent enough in leex to have have updated the parser to preserve >>>>>> the >>>>>> exact old error, but serendipitously what it reports in my prototype >>>>>> today is pretty good regardless, but I prefer the old behaviour: >>>>>> >>>>>> Old: >>>>>> %{& &1} >>>>>> *# !> **** (SyntaxError) syntax error before '}'* >>>>>> *# !> * | >>>>>> *# !> * 1 | %{& &1} >>>>>> *# !> * | ^ >>>>>> New: >>>>>> %{& &1} >>>>>> *# => error: expected key-value pairs in a map, got: & &1* >>>>>> *# => ** (CompileError) cannot compile code (errors have been logged)* >>>>>> >>>>>> *Cons: here there be dragons I cannot see* >>>>>> >>>>>> I'm quite sure a full implementation would require a lot more >>>>>> knowledge of the compiler than I am able to provide. For example, *&:foo >>>>>> = &:foo *raises an exception where *(&:foo) = &:foo* behaves as >>>>>> expected. I also find the variable/context/binding environment >>>>>> implementation in the erlang part of the compiler during expansion to be >>>>>> impenetrable, and I'm sure my prototype fails on edge cases there. >>>>>> >>>>>> *Open Question: the pin operator* >>>>>> >>>>>> As this feature constructs a variable ref for you, it is not clear >>>>>> if/how we should support attempts to pin the generated variable to avoid >>>>>> new bindings. In my prototype, I have tried to support the pin operator >>>>>> via >>>>>> the *&^:atom *syntax, though I'm pretty sure it's super buggy on >>>>>> bare out-of-data-structure cases and I only got it far enough to work in >>>>>> function heads for basic function head map pattern matching. >>>>>> >>>>>> *Open Question: charlists* >>>>>> >>>>>> I did not add support for charlist tagged variable captures in my >>>>>> prototype, as it would be more involved to differentiate a capture of >>>>>> list >>>>>> mean to become a tagged tuple from a list representing the AST of a >>>>>> function capture. I would not lose a lot of sleep over this. >>>>>> >>>>>> *Open Question: allowed contexts* >>>>>> >>>>>> Would we even want to allow this syntax construct outside of map >>>>>> literals? Or list literals? >>>>>> >>>>>> I can certainly see people abusing the >>>>>> bare-outside-of-associative-datastructure syntax to make some neigh >>>>>> impenetrable code where it's really unclear where assignment and pattern >>>>>> matching is occuring, and relatedly this is where I see a lot of odd >>>>>> edge-case behaviour in my prototype. I allowed it to speed up the >>>>>> implementation, but it merits more discussion. >>>>>> >>>>>> On the other hand, this does seem like an... interesting use-case: >>>>>> >>>>>> error = "rate limit exceeded" >>>>>> &:error *# return error tuple* >>>>>> >>>>>> *Thanks for reading! What do you think?* >>>>>> >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "elixir-lang-core" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to elixir-lang-co...@googlegroups.com. >>>>>> To view this discussion on the web visit >>>>>> https://groups.google.com/d/msgid/elixir-lang-core/ad7e0313-4207-4cb7-a5f3-d824735830abn%40googlegroups.com >>>>>> >>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/ad7e0313-4207-4cb7-a5f3-d824735830abn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>> . >>>>>> >>>>>> >>>>>> -- >>>>> You received this message because you are subscribed to the Google >>>>> Groups "elixir-lang-core" group. >>>>> To unsubscribe from this group and stop receiving emails from it, send >>>>> an email to elixir-lang-co...@googlegroups.com. >>>>> >>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/elixir-lang-core/2b46232e-04f1-4b21-87e6-9c098741cd36n%40googlegroups.com >>>>> >>>>> <https://groups.google.com/d/msgid/elixir-lang-core/2b46232e-04f1-4b21-87e6-9c098741cd36n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>> . >>>>> >>>> -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/888e360e-cb75-471d-bc0e-e8f0ca11f935n%40googlegroups.com.