for 98,99 -> $i {
for 0..255 -> $j {
# testing IP addresses with $i.$j
}
}
I was thinking about what would happen if I allowed the user to input
those ranges, like:
67.173.[98,99].[0..255]
After appropriate data massagng, I'd have to do something like:
for @(@ranges[1]) -> $i {
for @(@ranges[2]) -> $j {
for @(@ranges[3]) -> $k {
for @(@ranges[4]) -> $l {
# ...
}
}
}
}
Using a permutations module I could make that shorter, but I figure that
since we're already providing C<zip> to make looping easier, why not
provide C<outer> (perhaps spelled °)? The outer function would provide
a way to I<dynamically> nest loops.
for outer(*@ranges) -> [ $i, $j, $k, $l ]
{
# ...
}
Or better yet:
for outer(*@ranges) -> @cp {
my $ip = @cp.join('.');
}
And the original loop could be written:
for 98,99 ° 0..255 -> [$i, $j] {
# ...
}
Supposing ° had sufficiently low precedence. And supposing ° were used
at all, something I'm not particuarly attached to happening.
I believe it could be programmed lazily. Like this:
sub _outer_coro(*$first is context(Scalar),
*@rest is context(Scalar))
is coroutine
{
if @rest {
_outer_coro *@rest;
}
else {
yield $first;
}
}
sub outer(*@data is context(Scalar))
{
<_outer_coro(*@data)>
}
Luke
Which is of course wrong.
sub _outer_coro(@prev, @data) is coroutine
{
if (@data) {
_outer_coro([ @prev, @data[0] ], @data[1...])
}
else {
yield \@prev;
}
}
sub outer(*@data is context(Scalar))
{
<_outer_coro([], @data)>
}
Luke
I'm just going to stop trying after this one.
sub _outer_coro(@prev, @data) is coroutine
{
if (@data) {
_outer_coro([ @prev, $_ ], @data[1...]) for @(@data[0]);
...
> Using a permutations module I could make that shorter, but I figure that
> since we're already providing C<zip> to make looping easier, why not
> provide C<outer> (perhaps spelled °)? The outer function would provide
> a way to I<dynamically> nest loops.
>
> for outer(*@ranges) -> [ $i, $j, $k, $l ]
> {
> # ...
> }
>
> Or better yet:
>
> for outer(*@ranges) -> @cp {
> my $ip = @cp.join('.');
> }
>
Before this gets simonized, let me add that this seems genuinely useful: It provides a way of constructing a loop in a dimension that is not really accessible, except via recursion.
Luke: Would that have to be
for outer(*@ranges) ->« @cp {...}
?
> Supposing ° had sufficiently low precedence. And supposing ° were used
> at all, something I'm not particuarly attached to happening.
I'm opposed to it: bad huffman coding.
> I believe it could be programmed lazily. Like this:
> sub _outer_coro(*$first is context(Scalar),
> *@rest is context(Scalar))
> is coroutine
> {
> if @rest {
> _outer_coro *@rest;
> }
> else {
> yield $first;
> }
> }
>
> sub outer(*@data is context(Scalar))
> {
> <_outer_coro(*@data)>
> }
I find this code utterly baffling. How does this yield 255.255.0.[0..2] ?
Or is this supposed to be yielding iterators, in which case it seems to reverse them?
=Austin
Oh, it *is* useful, and it's extremely nice to know that something like this
will be able to be done as a user-defined extension, outside the core, or even
in the standard library, I don't mind, once the Perl 6 core itself gets
designed and implemented.
--
Be not anxious about what you have, but about what you are.
-- Pope St. Gregory I
Granted it can be a UDF. My interest is more in the question "What else have
we omitted?"
As I recall, the discussion a while back about iterators quickly mutated
into a discussion on how to do coroutines. We never actually explored the
"what cool things are possible with iterators as a basic data object/type"
question.
Luke just illuminated one of those dark corners for us:
"By applying iteration to iterators, you can express
complex code structures via arrays.
"Also, you can reclaim the FORTRAN variable namespace
($i..$n) for other uses."
Cool:- thinking on it, the fact that every damn coding book on the planet
has a section about nesting loops should have been a flag that P6l should be
looking at that.
What else have we missed?
=Austin
PS: The thought just occurred to me that C<outer> enables something like:
for outer(*grep ...) -> @indices {...}
which means that the code structure gets even more dynamic.
I wonder if it's possible to code C<outer> to handle variable length, like
walking a graph. (Garbage collector, anyone?) That would be C<traverse>, or
<enumerate>. Good for walking XML, too.
->« @cp makes about as much sense as sub«(@cp). C<outer> returns a
list of array references, right? So it binds each one to @cp (the right
of -> is a subroutine parameter list, remember?).
> > Supposing ° had sufficiently low precedence. And supposing ° were used
> > at all, something I'm not particuarly attached to happening.
>
> I'm opposed to it: bad huffman coding.
That's why it's a non-ascii operator. But I agree, there's really no
need for an operator here.
> > I believe it could be programmed lazily. Like this:
>
> > sub _outer_coro(*$first is context(Scalar),
> > *@rest is context(Scalar))
> > is coroutine
> > {
> > if @rest {
> > _outer_coro *@rest;
> > }
> > else {
> > yield $first;
> > }
> > }
> >
> > sub outer(*@data is context(Scalar))
> > {
> > <_outer_coro(*@data)>
> > }
>
> I find this code utterly baffling. How does this yield 255.255.0.[0..2] ?
It doesn't. You probably noticed by my numerous replys fixing the
numerous bugs in that code.
Luke
> -----Original Message-----
> From: Luke Palmer [mailto:lu...@luqui.org]
>
> Austin Hastings writes:
> > Before this gets simonized, let me add that this seems genuinely
> > useful: It provides a way of constructing a loop in a dimension that
> > is not really accessible, except via recursion.
> >
> > Luke: Would that have to be
> >
> > for outer(*@ranges) ->« @cp {...}
> >
> > ?
>
> ->« @cp makes about as much sense as sub«(@cp). C<outer> returns a
> list of array references, right? So it binds each one to @cp (the right
> of -> is a subroutine parameter list, remember?).
Are you saying that sub«(@cp) is not, in fact, an alias for C<map &sub, @cp> ?
Anyway, I ask because I wonder what happens if @cp happens to contain some discrete number of elements that is not equal to the number returned by C<outer>?
IOW:
@cp = (1, 2, 3);
for outer([0..255] xx 4) -> @cp {...}
Does the current number of entries have any impact?
for outer(@a, @b, @c) -> ($a, undef, $c) {...}
Does that work?
> > I'm opposed to it: bad huffman coding.
>
> That's why it's a non-ascii operator. But I agree, there's really no
> need for an operator here.
And more to the point, the fact that we've "opened the (code) page" doesn't mean that we have an infinite supply of iso-latin-1 glyphs. We'd be prudent to conserve them.
=Austin
Allow me to rewrite the loop to clarify. This has the exact same
semantic effect (as long as there is no C<return> within the loop
body), and pretty close to the same parse:
for outer(@a, @b, @c), sub (@cp) {...}
And now you can see that the previous contents of @cp don't mean
anything, because you're working with a different variable entirely. It
just happens to share the same name, but it's associated with a
different lexical scope.
The reason that:
for outer(@a, @b, @c) -> [$a, $b, $c] {...}
Works comes from Apocalypse 6, which states that a parameter list can be
placed in square brackets to indicate that an array is expected, and
that it will be decomposed as a separate, nested parameter list.
At first, I thought that was an unnecessary, bloating feature, but now I
see how marvelously useful it is :-)
Oh, by the way, this:
for outer([0..255] xx 4) -> @cp {...}
Needs to be written:
for outer(*[0..255] xx 4) -> @cp {...}
(Or even:
for outer(*([0..255] xx 4)) -> @cp {...}
depending on the precedence of unary *)
Luke
> for @(@ranges[1]) -> $i {
Oooh, where did that dereferencing syntax come from, using parens rather
than braces?
Smylers
It isn't a dereferencing syntax--it's a context-forcing syntax (one I'm
intimately familiar with), which forces @ranges[1] into list context.
Which shouldn't affect anything. So I think it's probably a mistake.
--
Brent "Dax" Royal-Gordon <br...@brentdax.com>
Perl and Parrot hacker
Oceania has always been at war with Eastasia.
@(...) is the "list context" operator in S3. I hope array references won't
explode in list context, that would be very annoying when making
multi-dimentional arrays:
@foo = ([1, 2], [3, 4]) # oops, would be (1, 2, 3, 4)
@foo = ($([1, 2]), $([3, 4])) # ugh :(
__________________________________
Do you Yahoo!?
Yahoo! Finance Tax Center - File online. File on time.
http://taxes.yahoo.com/filing.html
> @(...) is the "list context" operator in S3. I hope array references won't
> explode in list context, that would be very annoying when making
> multi-dimentional arrays:
>
> @foo = ([1, 2], [3, 4]) # oops, would be (1, 2, 3, 4)
> @foo = ($([1, 2]), $([3, 4])) # ugh :(
I would expect [] to force itself into scalar context anyway. Is there
ever a reason to want otherwise? Clearly the entire point of [] is to
create a scalar array ref from a list of arguments.
More to the point is there ever a reason to want any array ref in list
context to NOT explode other than []? I can't think of any.
push @a, $b
Is it too non-obvious that if $b is an array ref, then this is going to
extend @a by $b.length elements?
Pardon my ignorance, but I thought this was the plan. Feel free to
correct me if I am wrong.
--
Aaron Sherman <a...@ajs.com>
Senior Systems Engineer and Toolsmith
"It's the sound of a satellite saying, 'get me down!'" -Shriekback
Quite a bit too subtle, yes. While array references are now doing many
of the same things in similar contexts as arrays, flattening in list
context is not one of them. Array references are still different beasts
from arrays. Your push example is one of the reasons why.
Some time back, Larry said that you had to do:
push @a, @$b;
Just like in Perl 5. But this was before * was a unary operator instead
of a context forcing operator. That is, as of A6:
sub foo(@a, @b, @c, @d, @e);
foo(@a, @b, *@c, @d); # Flatten @c and @d into the parameter list
But now, it's:
foo(@a, @b, *@c, @d); # Flatten @c into the parameter list
So that might mean that push looks like:
push @a, *$b;
Luke
Yes, things that look like scalars have to stay scalars in list context.
: Some time back, Larry said that you had to do:
:
: push @a, @$b;
:
: Just like in Perl 5. But this was before * was a unary operator instead
: of a context forcing operator. That is, as of A6:
:
: sub foo(@a, @b, @c, @d, @e);
: foo(@a, @b, *@c, @d); # Flatten @c and @d into the parameter list
:
: But now, it's:
:
: foo(@a, @b, *@c, @d); # Flatten @c into the parameter list
:
: So that might mean that push looks like:
:
: push @a, *$b;
Yes, * was originally a no-op in list context, but I think now we can
use it to deref a list that would otherwise not interpolate itself.
It maps better onto how a C programmer thinks, and if in scalar
context it also happens to defer the signature checking to use the
interpolated values, that's just an extra bonus.
However, we'll have to be a little careful about calling it a
"flattening" operator, because it isn't exactly... Normal list context
only flattens notionally in Perl 6, and the actual flattening is done
lazily by default. If you really, truly want it flattened Right Now,
you have to use unary ** instead (by analogy to the ** prefix in the
declaration, or is it the other way around now?). But usually you
want the * semantics such that, if a lazy list is interpolated into
the list, it's just another generator in that list. To wit:
$foo = 0...; # take ref to an infinite range
@bar = $foo; # puts in the iterator as a reference
say @bar.elems; # prints 1
@bar = *$foo; # puts in 0...
say @bar.elems; # prints Inf
@bar = **$foo; # throws exception: "Please install a lot more memory"
It seems to be a useful mnemonic that, loosely speaking, ** is always
an "exponential" operator, one way or another... :-)
Larry
C<say>? Not C<print>?
It's just a "println" spelled Huffmanly.
Larry
It seems like this is creating the same confusion.
> $foo = 0...; # take ref to an infinite range
> @bar = $foo; # puts in the iterator as a reference
> say @bar.elems; # prints 1
> @bar = *$foo; # puts in 0...
> say @bar.elems; # prints Inf
> @bar = **$foo; # throws exception: "Please install a lot more memory"
I hope that Perl will be intelegent enough to notice that the range is
infinite, and say "attempt to flatten infinite list" rather then
"ENOMEM" here.
Also, how does the use of *$foo differ from @$foo here? Is the later
going away? (I'd think that horrible, for the same reason as above: C
is confusing because it's not always clear what you get when you *.)
By the way, I like say, but wonder if we're going to become a horrible
mix of APL and PHP. At least we don't have a Unicode alias for say
(yet, why do I suspect we're about to get a unary » operator for it?
Perhaps I'm just pessimistic this morning.)
-=- James Mastros
No, the confusion in C is because you never know whether * indicates a
single item or the start of a list. In Perl it will only indicate
that something should be considered listier than it otherwise would.
: > $foo = 0...; # take ref to an infinite range
: > @bar = $foo; # puts in the iterator as a reference
: > say @bar.elems; # prints 1
: > @bar = *$foo; # puts in 0...
: > say @bar.elems; # prints Inf
: > @bar = **$foo; # throws exception: "Please install a lot more
: > memory"
: I hope that Perl will be intelegent enough to notice that the range is
: infinite, and say "attempt to flatten infinite list" rather then
: "ENOMEM" here.
Er, that was a joke...
: Also, how does the use of *$foo differ from @$foo here? Is the later
: going away? (I'd think that horrible, for the same reason as above: C
: is confusing because it's not always clear what you get when you *.)
No, @$foo is not going away. You can write it that way when you think
it's clearer. The primary use of * is still to defeat the signature,
and @$foo doesn't do that.
: By the way, I like say, but wonder if we're going to become a horrible
: mix of APL and PHP. At least we don't have a Unicode alias for say
: (yet, why do I suspect we're about to get a unary » operator for it?
I will let other people define their own Unicode alias for "say". And
I hope it takes them more than three keystrokes to type. :-)
And "say" isn't in there because of APL or PHP. It's actually inspired
by something worse in Ruby.
: Perhaps I'm just pessimistic this morning.)
Don't slit your wrists just yet...
Larry
Presumably by "something worse" you mean "puts"? Not a great name, to
be sure, but it does have a venerable tradition behind it. :)
I do like having an auto-newline-appending version of print (without
having to make *all* my prints behave that way via -l), and my Perl
scripts of late often begin with a
sub puts(@) { for (@_) { print "$_\n" } }.
Of course, then I start forgetting my semicolons . . .
-Mark
Okay, good. So this is correct:
my $baz = @foo;
@bar = map { ... } @$baz;
(to be equivalent of mapping over @foo)?
Is @{$foo} going away? More specifically, how do I write that map if
$baz is some more complex expression, and I don't want to use * (say I
want to adhere if map decides to change its signature to take a real
array)?
Luke
What happened to the principle that things that work similarly should look
similarly?
I dislike having another method/function/whatever to do exactly the same
thing, yet a little different. That is PHP's niche.
Can't we instead just have a pseudo-filehandle or perhaps a tied one and
just use C<print> to print?
ln.print @bar.elems;
print ln : @bar.elems;
Though I'm not sure why a feature like this would be needed at all, so I
think this is something users should define something like this
themselves if they want it:
my &say = &print.assuming :ors "\n";
(Wildly guessing syntax here. I cincerely hope parens won't be needed.)
I think I prefer things the way they happen to already be.
print @bar.elems, "\n";
Also, I think C<say> is a bad choice. Many people use a function called
C<say> for chat bots and text-to-speech. It will of course be possible
to override the builtin, but for a good reason most people choose to not
do that.
Has this C<say> already been decided?
Juerd
Well I'm sincerely certain that they are.
my &say := &print.assuming(:ors("\n"));
> I think I prefer things the way they happen to already be.
>
> print @bar.elems, "\n";
Ugh. You do!? I think that's the biggest PITA in Perl. I never
thought of "say", but I've been known to write:
sub p { print @_, "\n" }
In some of my more verbose scripts.
It's a sign that something's wrong when on every one-liner I write, and
in even some longer scripts, I specify -l on the command line. C<say>
is indeed shorter than C<print>, and I like that, because I use it more
often.
Will there also be:
sub complain(*@_) {
print $ERR: @_, "\n";
}
:-)
> Also, I think C<say> is a bad choice. Many people use a function called
> C<say> for chat bots and text-to-speech.
Uh huh, but the ones I have experience with use it as a method, so it
doesn't interfere.
$bot.say("Welcome, $user")
Plus, a lot of people use C<index> to create an index, C<length> to find
the length of an array, C<delete> to delete files, C<study> to do their
homework, and C<die> to commit suicide (or was that C<goto>?). That's
why variables have sigils, and lexicals have scopes...
You even said yourself:
my &say := ...
That works even if C<say> is built-in.
> It will of course be possible to override the builtin, but for a good
> reason most people choose to not do that.
>
> Has this C<say> already been decided?
Doesn't matter, because most of these decisions are up for discussion.
I think everything that was "decided" when Apocalypse 3 was written has
changed at least three times (contrast with Synposis 3 :-).
Luke
Yes, that's correct.
: Is @{$foo} going away? More specifically, how do I write that map if
: $baz is some more complex expression, and I don't want to use * (say I
: want to adhere if map decides to change its signature to take a real
: array)?
@{EXPR} still works.
Larry
Okay, now that that's all cleared up, time to propose something.
When writing Perl 5, I always find myself writing @{ more often than @$.
Maybe it's just a bad habit that I don't tend to use a lot of
intermediate variables.
I propose that the precedence of the of the dereferencing sigils be
loosened so I don't have to write those pesky squigglies all the time.
What used to be:
for my $i (@{$foo->{bar}[$ind]}) { }
Can now be:
for @$foo{bar}[$ind] -> $i {...}
It doesn't feel quite right, but that's probably because I've written it
the other way so much.
The only reason to keep it around is if you wanted to use the archaic:
@$foo[2];
Or if you wanted to call methods on the array:
@$foo.sort;
But since you can call methods on a reference and get them delegated
anyway, that's not a problem. And as for the first one, well, who needs
that when they can just leave off the @ altogether?
Luke
> When writing Perl 5, I always find myself writing @{ more often than @$.
> Maybe it's just a bad habit that I don't tend to use a lot of
> intermediate variables.
Well, one of the big problems with Perl 5's dereferencing is that it's
painful to create intermediate variables that make it any easier. For
example, you can say "my $ref = $x{$y}{$z};@$ref" or you can say "local
*ary=$x{$y}{$z};@ary" but the latter isn't that obvious to most, and can
run afoul of strict. In Perl 6:
my @ary := %x{$y}{$z};
should make it much more likely that we'll all use those intermediates.
I also seem to recall something about a ".@" operator that would work
like so:
for %x{$y}{$z}.@ -> $i {...}
No? If everything else is chained on the right for dereferencing, I
certainly see the utility in this. Am I imagining that it was stated
earlier?
What's more that could be:
for *%x{$y}{$z} -> $i {...}
and I can't imagine it makes any sense to bind that * anywhere but:
for *(%x{$y}{$z}) -> $i {...}
I like the division between @ and *, since the two meanings had somewhat
too much overlap in most code.
> Juerd writes:
> > Has this C<say> already been decided?
>
> Doesn't matter, because most of these decisions are up for discussion.
> I think everything that was "decided" when Apocalypse 3 was written has
> changed at least three times (contrast with Synposis 3 :-).
>
If Larry is still adding functions to the core, maybe he can add the
"outer" function that Luke suggested last week. This function would be very
useful in inner loops, so if it is possible to implement it more efficiently
in the core than as a sub in a module I think we should do so.
Joe Gottman
And, if it's possible to implement it more efficiently in the core than as a
sub in a module that Parrot didn't live up to one of its design principles.
--
<yrlnry> I think the real problem here is that he is a university CS
professor and therefore knows very little about programming in the real
world, in any languge.
Erm... I suppose. As long as you've written the module code in C...
--
Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk
Well, hey, I'm not required to decide anything about functions till
Apocalypse 29 or so... :-)
Larry