Generator/Exponential: Difference between revisions

Content added Content deleted
(→‎{{header|Go}}: better implementation. replaced entire program.)
(Add Perl. Tweak C, Ruby.)
Line 16: Line 16:
=={{header|C}}==
=={{header|C}}==
==={{libheader|libco}}===
==={{libheader|libco}}===
libco is a tiny library that adds ''cooperative multithreading'', also known as ''coroutines'', to the C language. Its <tt>co_switch(x)</tt> function pauses the current cothread and resumes the other cothread <tt>x</tt>.


This example provides <tt>next64()</tt> and <tt>yield64()</tt>, to generate 64-bit integers. <tt>next64()</tt> switches to a generator. Then the generator passes some 64-bit integer to <tt>yield64()</tt>, which switches to the first cothread, where <tt>next64()</tt> returns this 64-bit integer.
libco is a tiny library that adds ''cooperative multithreading'', also known as ''coroutines'', to the C language. Its <tt>co_switch(x)</tt> function pauses the current thread and resumes the other thread <tt>x</tt>.

This example adds <tt>next64()</tt> and <tt>yield64()</tt>, to generate 64-bit integers. <tt>next64()</tt> switches to a generator. Then the generator passes some 64-bit integer to <tt>yield64()</tt>, which switches to the first thread, where <tt>next64()</tt> returns this 64-bit integer.


<lang c>#include <inttypes.h> /* int64_t, PRId64 */
<lang c>#include <inttypes.h> /* int64_t, PRId64 */
Line 151: Line 150:


for (;;) {
for (;;) {
while (c < s)
c = next64(&f.cubes);
if (c != s)
if (c != s)
yield64(gen, s);
yield64(gen, s);
while (c <= s)
c = next64(&f.cubes);
s = next64(&f.squares);
s = next64(&f.squares);
}
}
Line 354: Line 353:
<lang j>20 }. uncubicalSquares 30
<lang j>20 }. uncubicalSquares 30
529 576 625 676 784 841 900 961 1024 1089</lang>
529 576 625 676 784 841 900 961 1024 1089</lang>

=={{header|Perl}}==
These generators are anonymous subroutines, which are closures.

<lang perl># gen_pow($m) creates and returns an anonymous subroutine that will
# generate and return the powers 0**m, 1**m, 2**m, ...
sub gen_pow {
my $m = shift;
my $e = 0;
return sub { return $e++ ** $m; };
}

# gen_filter($g1, $g2) generates everything returned from $g1 that
# is not also returned from $g2. Both $g1 and $g2 must be references
# to subroutines that generate numbers in increasing order. gen_filter
# creates and returns an anonymous subroutine.
sub gen_filter {
my($g1, $g2) = @_;
my $v1;
my $v2 = $g2->();
return sub {
for (;;) {
$v1 = $g1->();
$v2 = $g2->() while $v1 > $v2;
return $v1 unless $v1 == $v2;
}
};
}

# Create generators.
my $squares = gen_pow(2);
my $cubes = gen_pow(3);
my $squares_without_cubes = gen_filter($squares, $cubes);

# Drop 20 values.
$squares_without_cubes->() for (1..20);

# Print 10 values.
my @answer;
push @answer, $squares_without_cubes->() for (1..10);
print "[", join(", ", @answer), "]\n";</lang>

Output: <pre>[529, 576, 625, 676, 784, 841, 900, 961, 1024, 1089]</pre>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
Line 434: Line 476:
c = cubes.next
c = cubes.next
powers(2) do |s|
powers(2) do |s|
(c = cubes.next) until c >= s
yield s unless c == s
yield s unless c == s
(c = cubes.next) until c > s
end
end
end
end
Line 466: Line 508:
loop do
loop do
s = squares.next
s = squares.next
(c = cubes.next) until c >= s
yield s unless c == s
yield s unless c == s
(c = cubes.next) until c > s
end
end
end
end