The Crystal Programming Language Forum

Why does this macro usage err?

I founded this case when working on today’s Advent of Code.

The gist of the problem is

macro m(i)
  array[{{i}}]
end

array = [0]
p m(0) # => 0
m(0) = 1 # => Error: unexpected token: =

I guess it might be something related to generating well-formed expressions (fine in p m(0)) plus the fact that the = there is syntactic sugar. Which is the actual explanation?

If I had to guess, the syntax is being checked before expanding the macro. The same thing happens if you do like.

def foo(val)
  val
end

foo(1) = 7

Since you can’t change the value of a method call. @asterite can probably speak more on the internals.

Yeah, that’s the reason. You can’t assign to something returned by a method, and I never thought of using a macro like that.

It could be an enhancement, though… but it’ll have to be discussed to see whether it makes sense as an entire feature.

Maybe the reason is that on the left-hand side of an assignment you can have very specific things: a constant (Foo), an instance variable or a local variable. We could allow calls but then they’ll always have to resolve to a macro, and that macro should expand to those things above (or another macro, recursively).

Another problem:

Foo.bar = 1

That calls Foo.bar=(1). But what if bar is a macro? Should Foo.bar expand that macro and then assign 1 to it? I think this is where it can become really confusing and the syntax is already clashing.

So I’d say because of all of the above there’s a very little chance that we’ll end up implementing this.

Gotcha, thanks!