http://qs1969.pair.com?node_id=11134437


in reply to Using 'keys' on a list

keys doesn't operate on a list, it operates on a hash (or an array since 5.12).

You can create a hash, populate it with the list, and get its keys:

my %h = f(); say for keys %h;

You can also just return every second element of the list:

my $i; say for grep ++$i % 2, f();

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^2: Using 'keys' on a list
by Corion (Patriarch) on Jun 29, 2021 at 12:48 UTC

    Also, when the Perl RFC 0001 comes into a stable release, you can write

    for my ($key, $value) (f()) { say $key; }

    I guess that this will come in 5.36 as experimental feature and hopefully will leave the experimental stage with 5.38.

      And this would have its own iterator?

        Yes, that's the point of this syntax. It wouldn't help for the case of the OP, as the call to f() will still generate the whole list.

Re^2: Using 'keys' on a list
by lammey (Novice) on Jun 29, 2021 at 14:55 UTC
    Thanks for the response =).
    keys doesn't operate on a list
    Do you know why this might be? Maybe because strictly speaking, only hashes have keys, and lists don't? But then perl isn't usually that strict e.g. as you mentioned from 5.12 keys can operate on an array. I ask because I was hoping to be able to do this in one line. It's not a big deal but I'm kind of curious to see if it's possible.
      > Do you know why this might be?

      Lists don't have keys. For arrays, keys returns the indices of the elements, not every second element. So, given a list, should keys use the hash semantics or the array one?

      Also note that a "list" in fact doesn't exist in Perl. There's a list context, but there always has to be something in the context, and this something is never a list. It might be a hash, it might be an array, or a sequence of comma operators. But keys doesn't want to see the hash (or array) in a list context, it wants to see its underlying HV or AV (which also makes getting the keys much faster, Perl doesn't really iterate over alternating keys and values, skipping the latter).

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        I understand that there's no list datatype - that perhaps it is used shorthand for something which can be evaluated in list context, but how can I reconcile this with the fact that subroutines return lists? Is it more correct to say that subroutines return a sequence of comma operators?