Compilation error: "cannot set attribute @word_mask48 inside function/macro" message

apparently “7 -1” is compiled the same as “7 - 1” but “@something -1” generates an error message from the compiler. Module B shows the error; module C has spaces around the minus sign, and module D is like B but uses a number instead of the attribute.

Is this a known bug? feature? just the way it is?

iex(4)> defmodule B do
...(4)> @mask 0o7
...(4)> 
...(4)> def decr(b), do: b - @mask -1
...(4)> end
** (ArgumentError) cannot set attribute @mask inside function/macro
    (elixir 1.15.5) lib/kernel.ex:3609: Kernel.do_at/5
    (elixir 1.15.5) expanding macro: Kernel.@/1
    iex:4: (file)
iex(4)> defmodule C do
...(4)> @mask 0o7
...(4)> def decr(b), do: b - @mask - 1
...(4)> end
{:module, C,
 <<70, 79, 82, 49, 0, 0, 5, 96, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 166,
   0, 0, 0, 18, 8, 69, 108, 105, 120, 105, 114, 46, 67, 8, 95, 95, 105, 110,
   102, 111, 95, 95, 10, 97, 116, 116, 114, ...>>, {:decr, 1}}
iex(5)> defmodule D do
...(5)> def decr(b), do: b - 0o7 -1
...(5)> end
{:module, D,
 <<70, 79, 82, 49, 0, 0, 5, 96, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 166,
   0, 0, 0, 18, 8, 69, 108, 105, 120, 105, 114, 46, 68, 8, 95, 95, 105, 110,
   102, 111, 95, 95, 10, 97, 116, 116, 114, ...>>, {:decr, 1}}
iex(6)> C.decr(5)
-3
iex(7)> D.decr(5)
-3

version (on MacBook Pro w/ M1 chip & MacOS Ventura 13.6):

heb@howards-mbp sds % iex --version
IEx 1.15.5 (compiled with Erlang/OTP 26)

heb@howards-mbp sds % elixir --version
Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]

Elixir 1.15.5 (compiled with Erlang/OTP 26)
heb@howards-mbp sds % 

Ya, spacing matters in Elixir. For example, you can’t do def foo (), do: "hello". In that case, it thinks you are trying to something along the lines of defining a function that takes an empty block as its first parameter.

-1 is the integer “negative 1” and module attributes don’t use any kind of assignment operator, so you’re doing what the error says: trying to assign negative one to the module attribute @mask.

EDIT: Sorry, I missed your third example. I actually didn’t realize 1-1 would compile, so TIL! I think it’s likely considered bad style, though? I dunno, I’m obviously out of my depth here now, lol.

I didn’t think this would compile without the spaces. I guess the lesson is to either use spaces or to not use them. Bad style, as you wrote, to be inconsistent.

iex(2)> defmodule E do
...(2)> @atr 5           
...(2)> def decr(x), do: x-@atr-1
...(2)> end
{:module, E,
 <<70, 79, 82, 49, 0, 0, 5, 96, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 166,
   0, 0, 0, 18, 8, 69, 108, 105, 120, 105, 114, 46, 69, 8, 95, 95, 105, 110,
   102, 111, 95, 95, 10, 97, 116, 116, 114, ...>>, {:decr, 1}}
iex(3)> E.decr(3)
-3

1--1 doesn’t compile because -- is interpreted as an operator.