#Zigling for loop with ptr capture example?

1 messages · Page 1 of 1 (latest)

topaz bolt
#

Hi I am doing ziglings 47 https://github.com/ratfactor/ziglings/blob/main/exercises/047_methods.zig#L84. Here is the code

 var aliens = [_]Alien{
        Alien.hatch(2),
        Alien.hatch(1),
        Alien.hatch(3),
        Alien.hatch(3),
        Alien.hatch(5),
        Alien.hatch(3),
    };

    var aliens_alive = aliens.len;
    const heat_ray = HeatRay{ .damage = 7 }; // We've been given a heat ray weapon.

    // We'll keep checking to see if we've killed all the aliens yet.
    while (aliens_alive > 0) {
        aliens_alive = 0;

        // Loop through every alien by reference (* makes a pointer capture value)
        for (&aliens) |*alien| {

Can someone help me understand what the syntax is for that for loop with the & and *. I tried removing them and just doing

        for (aliens) |alien| {
            heat_ray.zap(&alien);

But that isnt valid because its expecting a const alien apparently but the signature is *Alien. Why does this not work and what is actually happening here with this loop?

wind hollow
#

I read the exercise and the zap() function takes zap(self: HeatRay, alien: *Alien) which means you are going to mutate whatever Alien is inside this function. By default loops give you const Alien when you want a *Alien to be able to modify it with the heat_ray variable and its method.

#

The & and * just say: Oh get this thing by reference and give me the pointer to the item when you iterate so I can modify it within this loop.

#

One more note, if you wanted for whatever reason to mutate values of a slice while you are iterating, you need to dereference them (because they are now pointers) like this:

for (&items) |*item|
    item.* = whatever_new_value;
#

The second loop you mention, namely:

for (aliens) |alien| {
    heat_ray.zap(&alien);

Gives the zap() function not a *Alien to modify, but a *const Alien which means that yes, you have a pointer, but it's basically useless because you can't modify what it points to, which is the only reason here to have a pointer in the first place.

topaz bolt
#

Ah ok i did not realize that the returned thing was a *const.

Then i am suprised that this is not valid?

        for (&aliens) |*const alien| {
            heat_ray.zap(alien);
            if (alien.health > 0) aliens_alive += 1;
        }
#

sorry im aware that it wont work the the zap, because of the const issue before, but I mean valid in terms of its not valid syntax

wind hollow
#

The reasoning I guess is that by default a capture without * is already const. The fact that you use the * to get its pointer invalidates the const part. So then being able to add the const back in the capture would seem kind of just going in circles to do the same thing as the first regular capture.

#

The thing between the |pipes| just expects an identifier, meaning no type information, except for wheter it's a pointer or not (with *)