Yes, and to be more precise : each time the G'MIC interpreter encounters a custom command call, it actually generates a 'temporary' version of the command source code, where all arguments
$1,$2,... have been substituted by their current values. It ends up with a possibly long string without
$1,$2,... anymore, then start to interpret it.
That is also why the arguments
$1,... do not exactly behave like other variables
$foo for instance, because the latter are substituted during the custom command evaluation, not during its instantiation.
This becomes a bit technical though, and I'm not sure this is of any interest for the casual reader