その他の翻訳 > github.com

Perl/RFCs/rfcs/rfc0001 の翻訳

この文書は、Perl/RFCs/rfcs/rfc0001を翻訳したものです。

0e57765a667b340b709e16a96cbf10df 7d68f6c97a3ff2dc413ba834324a6ed3 05b623612e9222e3c3ad0243b54612fd 68da2aaa6a616b93ef162ce84dde59b7 Implement the currently illegal syntax `for my ($key, $value) (%hash) { ... }` to act as two-at-a-time iteration over hashes. This approach is not specific to hashes - it generalises to n-at-a-time over any list. c74ce0b34b5157849c9b1a38acfba306 The `each` function is generally discouraged due to implementation details, but is still the most "pretty" and concise way to write such a loop: a5885e8f5ba2f1352fd7d0678b196dfe An alternative to this would be a syntax to alias multiple items per iteration in a `for` loop. ddd1cb6445b86ef1fde32fd980ae36a0 This generalizes as a "bundler" - to alias a number of elements from the list equal to the number of variables specified. Such as: bb408199a87809eef30842a23e38fb26 831d2d39260be23b69c551b14ff2b114 The existing syntax to iterate over the keys and values of a hash: a5885e8f5ba2f1352fd7d0678b196dfe suffers from several problems 7e6895342c26a2cef19c749b69622751 You *can* write it in two lines as 8c8af1b90072da6de80042dc9f6837db (three if `%hash` is actually a complex expression you don't want to evaluate twice) but that's not perceived as an obvious "win" over the one-liner. The more general *n-at-a-time* iteration of an array problem doesn't have a simple generic solution. For example, you can **destructively** iterate an **array**: 19dbb9e904ac39419e067feadc2d424b (with that *3* needing to be written out explicitly - it can't derived from the number of lexicals) You can iterate over an list non-destructively like this: 828f596052072d9389c8911d18c9f23f but that f32292144ca6fe1b67d053621c6438e6 The proposed syntax solves all of these problems. 23bbfee52618e1bfb06eb381662d779f ``` diff --git a/pod/perlsyn.pod b/pod/perlsyn.pod index fe511f052e..490119d00e 100644 --- a/pod/perlsyn.pod +++ b/pod/perlsyn.pod @@ -282,6 +282,14 @@ The following compound statements may be used to control flow: 73cad8774c582d5ae045e39615269f0e +As of Perl 5.36, you can iterate over multiple values at a time by specifying +a list of lexicals within parentheses + + no warnings "experimental::for_list"; + LABEL for my (VAR, VAR) (LIST) BLOCK + LABEL for my (VAR, VAR) (LIST) BLOCK continue BLOCK + LABEL foreach my (VAR, VAR) (LIST) BLOCK + LABEL foreach my (VAR, VAR) (LIST) BLOCK continue BLOCK + If enabled by the experimental C feature, the following may also be used 9dc0d25414337dfec4ee7954be6168b5 @@ -549,6 +557,14 @@ followed by C. To use this form, you must enable the C feature via C. (See L. See also L.) +As of Perl 5.36, you can iterate over a list of lexical scalars n-at-a-time. +If the size of the LIST is not an exact multiple of number of iterator +variables, then on the last iteration the "excess" iterator variables are +undefined values, much like if you slice beyond the end of an array. You +can only iterate over scalars - unlike list assignment, it's not possible to +use C to signify a value that isn't wanted. This is a limitation of +the current implementation, and might be changed in the future. + Examples: c68e60fbd39a9c8596c5db571e4ddb81 @@ -574,6 +590,17 @@ Examples: # do something which each %hash } bad829cdb0e14a94761ada0dee33ef9b fe337b2452a66bd753f67573589de633 The new syntax is a syntax error on existing Perls. It generates this error message `Missing $ on loop variable at /home/nick/test/three-at-a-time.pl line 4.` Existing static tooling should be able to recognise it as a syntax error, but without changes wouldn't be able to give any better diagnostics. The proposed implementation has tests and patches for `B::Deparse` and `B::Concise`. `Devel::Cover`, `Devel::NYTProf` and `Perl::Critic` handle the new syntax just fine. I don't think that we have any way to emulate this syntax for earlier Perls. I don't have any feel for what sort of API we would need to add to the parser to make it possible in the future, and whether any API we could add would be fragile and tightly coupled to the exact current implementation. f61c065d002bd68fb832d0241dbbc67c We don't think that this change is likely to cause CVEs or similar problems. 1efcb2ce24468a5e3abb5e801716cffe The examples in the *Motivation* seem sufficient. f63004bd229e5d2105424339fe6b551f See https://github.com/nwc10/perl5/commits/smoke-me/nicholas/pp_iter 56d86b53f18de739da566734fd6d768e 857fe7d41b1cb5c4b395e6f28e211935 aca2dcd3b7c2ebe031f384f5c876a58a It's a reasonable generalisation of list assignment, where you can assign to undef to mean "ignore this value". It's also safe syntax to implement for `foreach` (either as part of this proposal, **or** at a later date), and likely will be useful in some specific cases. But **not** having it doesn't hinder the utility of the basic proposal. The easiest implementation of *n-at-a-time* `foreach` is if there are exactly *n* scalars, all declared in the `for` loop itself, because this way they occupy adjacent Pad slots. This means that there is only one extra integer to store in the optree, which used both to calculate the *n*-at-a-time **and** the addresses of the target variables. adding `undef` to the mix rules out an obvious simple, clear implementation. If we discover that there is a good way to add `undef` without much increased complexity, then we should consider doing this. dd2e340d24e9c6d91290c579c80d241d 834d18fba1dfdeb390aa1b0bb464cae3 f15a0889b3ea1fa53718469bbd372cf7 Syntactically these all "work", and don't violate the assumption that all lexicals are in adjacent Pad slots. But it would add complexity to the runtime. Generalising *1 scalar at a time* to *n at a time* is mostly just adding a C `for` loop around some existing (known working) code. Implementing these would mean adding code for what is basically a funky way of writing 1cb49a1e971f77c4f802c5ca470101e2 8933e628c9d56ff4fb0675542f042806 Using `our` instead of `my` works in the grammar. ie we can parse this: 63f03ff3cb3f2b2813c43d8501dcb6fd However, the implementation would be far more complex. Each package variable would need a pair of GV and RV2GV ops to set it up for aliasing in a lexical, meaning that we'd need to create a list to feed into ENTERITER, and have it process that list to set up Pads. This complexity isn't worth it. 129d71e53df2e36fc5c78bf8e92539fb When this syntax was suggested in 2017, Father Chrysostomos observed that in addition to the first syntax, the next two are also currently errors and could be parsed: d7cb3e96ff76dc2a9accf0e12ee39936 He notes that it's only this illegal syntax that could not be parsed: 71c8fb4fb0712bb8f281ff869dacf9fb https://www.nntp.perl.org/group/perl.perl5.porters/2017/04/msg243856.html Strictly we also can't parse this: bd5d34c2f5817c02e42e8a880e3e39db meaning that we can't offer choice of syntax in `for` analogous to: 17631278a741e40b4a96b6f94d1034b4 which parse to the same optree. However, these two lines are **not the same**: ee562fecbba2ab58644bfcf06ef5113a hence we should not offer the alternative syntax: dfe0e7c23a225af00e6a5f5641467cb1 For implementation reasons we only want to handle lexicals. This rules out: 782b608dba9e571336b7513fd9755c5a So these alternative possible syntaxes should not be offered. a5fe090c0e8746fbe4fac67cbff8ac7d As the new syntax was previously an error, and previously in similar situations we have not used a feature guard, we don't think that we should this time. f90133e13cd1ffd34e6467f45cebce81 887703d4dd404d2bfc83c23c6023a689 Copyright (C) 2021, Nicholas Clark This document and code and documentation within it may be used, redistributed and/or modified under the same terms as Perl itself.