Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Iterator
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
===Raku=== Iterators in [[Raku (programming language)|Raku]] are a fundamental part of the language, although usually users do not have to care about iterators. Their usage is hidden behind iteration APIs such as the <code>for</code> statement, <code>map</code>, <code>grep</code>, list indexing with <code>.[$idx]</code>, etc. The following example shows typical implicit iteration over a collection of values: <syntaxhighlight lang="raku"> my @values = 1, 2, 3; for @values -> $value { say $value } # OUTPUT: # 1 # 2 # 3 </syntaxhighlight> Raku hashes can also be directly iterated over; this yields key-value <code>Pair</code> objects. The <code>kv</code> method can be invoked on the hash to iterate over the key and values; the <code>keys</code> method to iterate over the hash's keys; and the <code>values</code> method to iterate over the hash's values. <syntaxhighlight lang="raku"> my %word-to-number = 'one' => 1, 'two' => 2, 'three' => 3; for %word-to-number -> $pair { say $pair; } # OUTPUT: # three => 3 # one => 1 # two => 2 for %word-to-number.kv -> $key, $value { say "$key: $value" } # OUTPUT: # three: 3 # one: 1 # two: 2 for %word-to-number.keys -> $key { say "$key => " ~ %word-to-number{$key}; } # OUTPUT: # three => 3 # one => 1 # two => 2 </syntaxhighlight> Iterators however can be used and defined explicitly. For any iterable type, there are several methods that control different aspects of the iteration process. For example, the <code>iterator</code> method is supposed to return an <code>Iterator</code> object, and the <code>pull-one</code> method is supposed to produce and return the next value if possible, or return the sentinel value <code>IterationEnd</code> if no more values could be produced. The following example shows an equivalent iteration over a collection using explicit iterators: <syntaxhighlight lang="raku"> my @values = 1, 2, 3; my $it := @values.iterator; # grab iterator for @values loop { my $value := $it.pull-one; # grab iteration's next value last if $value =:= IterationEnd; # stop if we reached iteration's end say $value; } # OUTPUT: # 1 # 2 # 3 </syntaxhighlight> All iterable types in Raku compose the <code>Iterable</code> role, <code>Iterator</code> role, or both. The <code>Iterable</code> is quite simple and only requires the <code>iterator</code> to be implemented by the composing class. The <code>Iterator</code> is more complex and provides a series of methods such as <code>pull-one</code>, which allows for a finer operation of iteration in several contexts such as adding or eliminating items, or skipping over them to access other items. Thus, any user-defined class can support standard iteration by composing these roles and implementing the <code>iterator</code> and/or <code>pull-one</code> methods. The <code>DNA</code> class represents a DNA strand and implements the <code>iterator</code> by composing the <code>Iterable</code> role. The DNA strand is split into a group of trinucleotides when iterated over: <syntaxhighlight lang="raku"> subset Strand of Str where { .match(/^^ <[ACGT]>+ $$/) and .chars %% 3 }; class DNA does Iterable { has $.chain; method new(Strand:D $chain) { self.bless: :$chain } method iterator(DNA:D:){ $.chain.comb.rotor(3).iterator } }; for DNA.new('GATTACATA') { .say } # OUTPUT: # (G A T) # (T A C) # (A T A) say DNA.new('GATTACATA').map(*.join).join('-'); # OUTPUT: # GAT-TAC-ATA </syntaxhighlight> The <code>Repeater</code> class composes both the <code>Iterable</code> and <code>Iterator</code> roles: <syntaxhighlight lang="raku"> class Repeater does Iterable does Iterator { has Any $.item is required; has Int $.times is required; has Int $!count = 1; multi method new($item, $times) { self.bless: :$item, :$times; } method iterator { self } method pull-one(--> Mu){ if $!count <= $!times { $!count += 1; return $!item } else { return IterationEnd } } } for Repeater.new("Hello", 3) { .say } # OUTPUT: # Hello # Hello # Hello </syntaxhighlight>
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)