Specifically, we expanded an undefined variable foo to a function call foo(),
warned about the expansion, then reported a compile-time error about the
missing function, instead.
On Wednesday, June 28, 2023 at 11:13:18 PM UTC-5 Christopher Keele wrote:
> The above is how we dealt with undefined variable references until
> recently (I think 1.15?): warn about the problematic expansion, error on
> the expanded syntax.
>
> On Wednesday, June 28, 2023 at 11:05:00 PM UTC-5 Christopher Keele wrote:
>
>> An alternative would be to prepend compiler issues with a depiction of
>> the how the sugar expands. Something like:
>>
>> %{$:foo, "fizz" => "buzz", $"bar", fizz: :buzz, $:baz}
>> # !> warning: expanding %{$:foo, "fizz" => "buzz", $"bar", fizz: :buzz, $
>> :baz} into a syntactically invalid construct:
>> # !> %{:foo => foo, "fizz" => "buzz", "bar" => bar, fizz: :buzz, :baz =>
>> baz}
>> # !> iex:12:47
>> # !> # !> ** (SyntaxError) invalid syntax found on iex:12:47:
>> # !> ┌─ error: iex:12:47
>> # !> 12 │ %{:foo => foo, "fizz" => "buzz", "bar" => bar, fizz: :buzz,
>> :baz => baz}
>> # !> │ ^
>> # !> │
>> # !> unexpected expression after keyword list. Keyword lists must
>> always come last in lists and maps.
>> # !>
>> # !> Syntax error after: ','
>>
>> On Wednesday, June 28, 2023 at 10:56:13 PM UTC-5 Christopher Keele wrote:
>>
>>> %{$:foo, "fizz" => "buzz", $"bar", fizz: :buzz, $:baz}
>>>
>>> Personally, my preference would be to disallow this usage, but perhaps
>>> with an even more instructive compiler error message.
>>>
>>> In fact, I think that we could leverage most existing errors/warnings
>>> today, as long as things like the compiler error reporter desugar this
>>> feature before reporting, to make it clearer upon error what is actually
>>> going on in a variety of circumstances. This would give us something more
>>> like:
>>>
>>> %{$:foo, "fizz" => "buzz", $"bar", fizz: :buzz, $:baz} # !> **
>>> (SyntaxError) invalid syntax found on iex:12:47:
>>> # !> ┌─ error: iex:12:47
>>> # !> │
>>> # !> 12 │ %{:foo => foo, "fizz" => "buzz", "bar" => bar, fizz: :buzz,
>>> :baz => baz}
>>> # !> │ ^
>>> # !> │
>>> # !> unexpected expression after keyword list. Keyword lists must
>>> always come last in lists and maps.
>>> # !>
>>> # !> Syntax error after: ','
>>> On Wednesday, June 28, 2023 at 10:44:44 PM UTC-5 Christopher Keele wrote:
>>>
>>>> Posted that last reply early. continued:
>>>>
>>>> Part of the elegance in of making $:foo and &"bar" expand to a valid
>>>> pair, right before Map expansion handles pairs as {:%{}, [], [...
>>>> pairs]}, is that it *could* easily allow us to support mixing tagged
>>>> variable captures anywhere in the existing syntax constructs: This is not
>>>> true of my prototype today, though, it would need more work based on how
>>>> we
>>>> decide to handle it:
>>>>
>>>> {foo, bar, baz} = {1, 2, 3}
>>>>
>>>> %{$:foo, "fizz" => "buzz", $"bar", fizz: :buzz}
>>>> # => %{:fizz => :buzz, :foo => 1, "bar" => 2, "fizz" => "buzz"}
>>>>
>>>> %{$:foo, "fizz" => "buzz", $"bar", fizz: :buzz, $:baz} # !> **
>>>> (SyntaxError) invalid syntax found on iex:12:47:
>>>> # !> ┌─ error: iex:12:47
>>>> # !> │
>>>> # !> 12 │ %{$:foo, "fizz" => "buzz", $"bar", fizz: :buzz, $:baz}
>>>> # !> │ ^
>>>> # !> │
>>>> # !> unexpected expression after keyword list. Keyword lists must
>>>> always come last in lists and maps. Therefore, this is not allowed:
>>>> # !>
>>>> # !> [some: :value, :another]
>>>> # !> %{some: :value, another => value}
>>>> # !>
>>>> # !> Instead, reorder it to be the last entry:
>>>> # !>
>>>> # !> [:another, some: :value]
>>>> # !> %{another => value, some: :value}
>>>> # !>
>>>> # !> Syntax error after: ','
>>>>
>>>>
>>>>
>>>> On Wednesday, June 28, 2023 at 10:32:20 PM UTC-5 Christopher Keele
>>>> wrote:
>>>>
>>>>> > Alternatively, the `$` symbol could be used at the beginning of the
>>>>> data structure to indicate that it is performing capture destructuring
>>>>> (e.g., `$%{key1:, key2:}` or `$%{"key1", "key2"}`, but then it starts
>>>>> feeling a little more line-noisy.
>>>>>
>>>>> I agree that'd be noisy. Also, it might make mixing tagged variable
>>>>> literals, literal => pairs, and trailing keyword pairs even more
>>>>> confusing.
>>>>>
>>>>> Consider today that we support:
>>>>> %{"fizz" => "buzz", foo: :bar}
>>>>> # => %{:foo => :bar, "fizz" => "buzz"}
>>>>>
>>>>> But do not support:
>>>>> %{foo: :bar, "fizz" => "buzz"}
>>>>> # !> ** (SyntaxError) invalid syntax found on iex:5:12:
>>>>> # !> ┌─ error: iex:5:12
>>>>> # !> │
>>>>> # !> 5 │ %{foo: :bar, "fizz" => "buzz"}
>>>>> # !> │ ^
>>>>> # !> │
>>>>> # !> unexpected expression after keyword list. Keyword lists must
>>>>> always come last in lists and maps. Therefore, this is not allowed:
>>>>> # !>
>>>>> # !> [some: :value, :another]
>>>>> # !> %{some: :value, another => value}
>>>>> # !>
>>>>> # !> Instead, reorder it to be the last entry:
>>>>> # !>
>>>>> # !> [:another, some: :value]
>>>>> # !> %{another => value, some: :value}
>>>>> # !>
>>>>> # !> Syntax error after: ','
>>>>>
>>>>> Supporting $%{key1:, key2:} or $%{"key1", "key2"} obfuscates this
>>>>> situation even further.
>>>>> On Wednesday, June 28, 2023 at 10:16:10 PM UTC-5 halos...@gmail.com
>>>>> wrote:
>>>>>
>>>>>> On Wed, Jun 28, 2023 at 8:41 PM Paul Schoenfelder <
>>>>>> paulscho...@fastmail.com> wrote:
>>>>>>
>>>>>>> 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.
>>>>>>>
>>>>>>
>>>>>> JavaScript *only* supports string keys. Ruby’s pattern matching
>>>>>> which can lead to field punning only supports symbol keys, but since
>>>>>> ~2.2
>>>>>> Ruby can garbage collect symbols, making it *somewhat* less
>>>>>> dangerous to do `JSON.parse!(data, keys: :symbol)` than it was
>>>>>> previously.
>>>>>>
>>>>>> As far as I know, the BEAM does not do any atom garbage collection,
>>>>>> and supporting *only* symbols will lead to a greater chance of atom
>>>>>> exhaustion because a non-flagged mechanism here that only works on atom
>>>>>> keys will lead to `Jason.parse(data, keys: :atom)` (and not
>>>>>> `Jason.parse(data, keys: :atom!)`). I do not think that any
>>>>>> destructuring
>>>>>> syntax which works on maps with symbol keys but not string keys will be
>>>>>> acceptable, although if it is constrained to *only* work on structs,
>>>>>> then
>>>>>> it does not matter (as that is the same restriction that it appears that
>>>>>> OCaml and Haskell have).
>>>>>>
>>>>>> I think that either `&:key` / `&"key"` or `$:key` / `$"key"` will
>>>>>> work very nicely for this feature, although it would be nice to have
>>>>>> `&key:` or `$key:` work the same as the former version. Alternatively,
>>>>>> the
>>>>>> `$` symbol could be used at the beginning of the data structure to
>>>>>> indicate
>>>>>> that it is performing capture destructuring (e.g., `$%{key1:, key2:}` or
>>>>>> `$%{"key1", "key2"}`, but then it starts feeling a little more
>>>>>> line-noisy.
>>>>>>
>>>>>> I think that the proposal here — either using `&` or `$` — is
>>>>>> entirely workable and IMO extends the concept nicely.
>>>>>>
>>>>>> -a
>>>>>>
>>>>>> 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/4ee25f02-f27e-47a8-b4b5-b8520c1c9b05%40app.fastmail.com
>>>>>>>
>>>>>>> <https://groups.google.com/d/msgid/elixir-lang-core/4ee25f02-f27e-47a8-b4b5-b8520c1c9b05%40app.fastmail.com?utm_medium=email&utm_source=footer>
>>>>>>> .
>>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Austin Ziegler • halos...@gmail.com • aus...@halostatue.ca
>>>>>> http://www.halostatue.ca/ • http://twitter.com/halostatue
>>>>>>
>>>>>
--
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/c1b0a9e7-cdc4-44ec-b824-261f5ad3b131n%40googlegroups.com.