Understanding variable assignment within function arguments

First, sorry for the confusing topic title. I’m a bit confused and don’t really know how to describe the problem in english.

Here’s, the code I’m wondering about: assert_reply(ref, :ok, %{subscriptionId: subscription_id})

subscription_id is not defined yet. I would expect the code to fail to compile just like if ref would not be defined. Yet it compiles fine and I can access subscription_id in the following code.

I’m failing to understand what concept this is. Could somebody educate me? Thanks!

1 Like

Your answer is in the Phoenix docs: Phoenix.ChannelTest — Phoenix v1.7.10

Notice status and payload are patterns.

Then your %{subscriptionId: subscription_id} is just some pattern that assert_reply will use against the payload.
For example, it could mean:
%{subscriptionId: subscription_id} = %{subscriptionId: 4}

1 Like

This is why macros are usually a bad idea: they are made in hopes of making syntax easier, but they break assumptions and behave differently to normal code, resulting in confusion.

Ok, I just realized that assert_receive is a macro itself. I was looking at the assert_reply macro and failed to realize that.

Thanks @domvas, I read that but looking at the code for assert_reply I wasn’t able to understand how this is done in the language.

This is why macros are usually a bad idea: they are made in hopes of making syntax easier, but they break assumptions and behave differently to normal code, resulting in confusion.

I agree to some extend. I guess after one knows about a certain macro it makes the code way easier to read and reason about, so it’s a tradeoff.

1 Like