Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic variables, CALLERS, Scalars, and assignment

I recently noticed that that re-initializing dynamic variables does not have the semantics I expected in most cases using assignment (binding works the way I expected it to, however).

Specifically, in this code:

sub g {
    my $*i  = CALLERS::<$*i>  // 0;
    my $*a1 = CALLERS::<$*a1> // Array.new;
    my @*a2 = CALLERS::<@*a2> // Array.new;
    $*i++;
    $*a1.push: 'v1';
    @*a2.push: 'v2';
    dd $*i;
    dd $*a1;
    dd @*a2;
}
sub f {
    my $*i = 0;
    my $*a1 = Array.new;
    my @*a2 = Array.new;
    g; g; g;
}
f

I expected output of 3, ["v1", "v1", "v1"], and ["v2", "v2", "v2"] but instead get 1, $["v1", "v1", "v1"], ["v2"]. Switching to binding solves the issue, so there's no problem I'm trying to solve – but I would very much like to understand why assignment doesn't work here. I notice that a Scalar pointing to an Array works, but a Scalar pointing to an Int doesn't. But in either case, I would have thought that the newly assigned variable would receive the value from CALLERS. What am I missing about the semantics of assignment?

like image 856
codesections Avatar asked Jun 04 '21 03:06

codesections


People also ask

What is a dynamic variable?

Dynamic variables compute their own values by executing statements and logical expressions. A dynamic variable assigns itself the result of a calculation or operation. The dynamic variable types are dynamic string, dynamic number, and dynamic True/False (Boolean).

What is a dynamic variable example?

Dynamic Variable Overview The distinguishing characteristic of a dynamic variable is that its value can change while the application runs. For example, your application might maintain a threshold value that is compared to a field value in each tuple processed.

What is the use of dynamic variable?

A dynamic variable is a variable you can declare for a StreamBase module that can thereafter be referenced by name in expressions in operators and adapters in that module. In the declaration, you can link each dynamic variable to an input or output stream in the containing module.

How do you declare a dynamic variable?

Users can follow the below syntax to create the dynamic array to store dynamic variables. let array = []; for () { array[ key ] = value; // dynamically assign value to the key. }


1 Answers

What am I missing about the semantics of assignment?

I think what you're missing, doesn't have anything to do with dynamic variables per se. I think what you're missing is the fact that:

my @a = Array.new;

is basically a noop. Because of the single argument rule, it is the same as:

my @a = ();

which is the same as:

my @a;

So, in your example in sub f, the:

my @*a2 = Array.new;

in is just setting up an empty array in a dynamic variable.

Then in sub g the:

my @*a2 = CALLERS::<@*a2> // Array.new;

is just basically doing (because of the single argument rule):

my @*a2;

and hence you don't see the pushes you've done before, because every call it starts out fresh.

Regarding the value of $*i in sub g: that also is just incrementing a copy of the callers $*i, so the value remains at 1 in every call.

The reason that $*a1 works, is that containerization stops the flattening behaviour of the single argument rule. Observe the difference between:

sub a(+@a) { dd @a }; a [2,3,4];  # [2,3,4]

and:

sub a(+@a) { dd @a }; a $[2,3,4];  # [[2,3,4],]
like image 105
Elizabeth Mattijsen Avatar answered Sep 19 '22 13:09

Elizabeth Mattijsen