That's a bug in how the capture of keyword operators work. It has also been fixed in master. Thank you for the report!
*José Valim* www.plataformatec.com.br Skype: jv.ptec Founder and Director of R&D On Sun, May 14, 2017 at 6:52 PM, Luke Imhoff <[email protected]> wrote: > I don't know if this effects your planned change to the grammar, but as a > side-effect of `not` being treated as a normal function instead of a > keyword, `not` when captured allows any arity (you may have already > realized this, I did not). > > For uncaptured, `not` with a different arity than 1 is a syntax error > > iex> Code.string_to_quoted("not 1") > {:ok, {:not, [line: 1], [1]}} > iex> Code.string_to_quoted("not 1, 2") > {:error, {1, "syntax error before: ", "','"}} > > While captured it doesn't care > > iex> Code.string_to_quoted("¬ 1") > {:ok, {:&, [line: 1], [{:not, [line: 1], [1]}]}} > iex> Code.string_to_quoted("¬ 1, 2") > {:ok, {:&, [line: 1], [{:not, [line: 1], [1, 2]}]}} > > This may count as a separated bug just a related depending on how it's > fixed. > > On Sunday, May 14, 2017 at 2:41:53 AM UTC-5, José Valim wrote: >> >> Thank you Luke for the detailed bug report. >> >> I think we should fix this by making "!" behave like "not" and remove >> this special case from the grammar. The only unary operator that will bind >> tightly to numbers then will be &, which is already behaves differently >> from the others as it has very low precedence. >> >> Note that @ will still bind tightly to numbers but that's rather because >> it has very high precedence and not a special case. >> >> I will push a commit to master later today. >> >> >> *José Valim* >> www.plataformatec.com.br >> Skype: jv.ptec >> Founder and Director of R&D >> >> On Sun, May 14, 2017 at 4:18 AM, Luke Imhoff <[email protected]> wrote: >> >>> I noticed this when splitting `not` from the other unary operators in >>> IntelliJ Elixir's lexer grammar (because I can only do spacing rules on >>> lexer tokens, so I need NOT_OPERATOR separate from UNARY_OPERATOR for >>> https://github.com/KronicDeth/intellij-elixir/issues/98 so I can have >>> no space between the symbolic operators, but require the space after `not` >>> as it will blend into the argument otherwise). I'm not sure this is really >>> a problem or not. It's just a weird edge-case that I produced since I test >>> unary numeric and unary non-numeric operators. >>> >>> `not` is part of `unary_op_eol` (https://github.com/elixir-lan >>> g/elixir/blob/39dd31c7d96f302986579bb6938d23c9db101661/lib/ >>> elixir/src/elixir_parser.yrl#L73), which also contains `+`, `-`, `!`, >>> `^`, `~~~`. >>> >>> Let's start with unary numeric at the top-level >>> >>> iex> Code.string_to_quoted("not 1") >>> {:ok, {:not, [line: 1], [1]}} >>> iex> Code.string_to_quoted("! 1") >>> {:ok, {:!, [line: 1], [1]}} >>> >>> Next, let's do something weird and make the `1` act something you can do >>> dot calls on. This is gibberish semantically in current Elixir, but >>> something the syntax allows. >>> >>> iex> Code.string_to_quoted("not 1.(2)") >>> {:ok, {{:., [line: 1], [{:not, [line: 1], [1]}]}, [line: 1], [2]}} >>> iex> Code.string_to_quoted("! 1.(2)") >>> {:ok, {{:., [line: 1], [{:!, [line: 1], [1]}]}, [line: 1], [2]}} >>> >>> So, the precedence of the AST is the same: (1) `not`/`!` on `1`; (2) dot >>> call with `2` on the result of (1). >>> >>> Finally, let's try to capture the weird syntax >>> >>> iex> Code.string_to_quoted("¬ 1.(2)") >>> {:ok, {:&, [line: 1], [{:not, [line: 1], [{{:., [line: 1], [1]}, [line: >>> 1], [2]}]}]}} >>> iex> Code.string_to_quoted("&! 1.(2)") >>> {:ok, {:&, [line: 1], [{{:., [line: 1], [{:!, [line: 1], [1]}]}, [line: >>> 1], [2]}]}} >>> >>> So the precedence of the symbolic `!` and word `not` is no longer the >>> same. >>> For `not`: (1) `1.(2)` is called; (2) `not` the result of (1)`; (3) >>> capture >>> For `!`: `!1` is called; (2) `.(2)` is called on the result of (1); (3) >>> capture >>> >>> What has happened is that `not` has lost it's "keywordness" and is >>> moving the position of a normal function name (like `foo` below) >>> >>> iex> Code.string_to_quoted("&foo 1.(2)") >>> {:ok, {:&, [line: 1], [{:foo, [line: 1], [{{:., [line: 1], [1]}, [line: >>> 1], [2]}]}]}} >>> >>> So, this example is gibberish. Does it apply to non-numeric unary >>> operations? >>> >>> iex> Code.string_to_quoted("&! a.(2)") >>> {:ok, {:&, [line: 1], [{:!, [line: 1], [{{:., [line: 1], [{:a, [line: >>> 1], nil}]}, [line: 1], [2]}]}]}} >>> iex> Code.string_to_quoted("¬ a.(2)") >>> {:ok, {:&, [line: 1], [{:not, [line: 1], [{{:., [line: 1], [{:a, [line: >>> 1], nil}]}, [line: 1], [2]}]}]}} >>> iex(56)> Code.string_to_quoted("&foo a.(2)") >>> {:ok, {:&, [line: 1], [{:foo, [line: 1], [{{:., [line: 1], [{:a, [line: >>> 1], nil}]}, [line: 1], [2]}]}]}} >>> >>> So, it's all consistent there: (1) `a.(2)` is evaluated; (2) the >>> operator/function call; and (3) it's all captured. >>> >>> So, is the inconsistency in unary numeric `not` a bug in the native >>> grammar or something to be expected? If the unary operators should bind >>> more tightly to numerics than non-numerics (as is my understanding of the >>> current grammar) then `{:ok, {:&, [line: 1], [{{:., [line: 1], [{:!, [line: >>> 1], [1]}]}, [line: 1], [2]}]}}` is correct and `not` should be `{:ok, {:&, >>> [line: 1], [{{:., [line: 1], [{:not, [line: 1], [1]}]}, [line: 1], [2]}]}}`. >>> >>> The unary numeric operations in current language semantics seem to be >>> there for positional captures, like `&1`, so this is mostly me bringing it >>> up because I have to change IntelliJ Elixir's grammar to take this >>> behaviour for unary numeric `not` into account separately from symbolic >>> unary numerics. >>> >>> -- >>> 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 [email protected]. >>> To view this discussion on the web visit https://groups.google.com/d/ms >>> gid/elixir-lang-core/f5f75451-93dc-4163-bd9a-7055dab69d62% >>> 40googlegroups.com >>> <https://groups.google.com/d/msgid/elixir-lang-core/f5f75451-93dc-4163-bd9a-7055dab69d62%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> For more options, visit https://groups.google.com/d/optout. >>> >> >> -- 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4L8_NjAkcGp%3Df2u%2B2kcSSj6fZX0fvfT8icqMr7pyi3Kcw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.
