Re: Maybe it's Just Nothing (was: Look-ahead arguments in for loops)

2005-09-30 Thread Jonathan Scott Duff
On Thu, Sep 29, 2005 at 11:21:20PM -0600, Luke Palmer wrote:
[ discussion on undefs elided ]

Since we can annotate our undefs now, perhaps undefs that would be
generated because there are no previous or next elements get tagged
as such.  Something like:

# assuming $b and $a are before and after elements
for @list - ?$b, $c, $?a {
given $b {
when undef but generated { say a fake undef!; }
when undef   { say a real undef!; }
}
}

 Oh, right, and as for my favorite actual usage of for:
 
 for @list, :lookbehind(2) :lookahead(1)
 - $behind1, $behind2, $value, $ahead {
 ...
 }

Hmm.  Something like:

for @list - $c :behind($b1,$b2) :ahead($a1) { ... }

would seem to make a more direct connection between the variables and
what they are aliased to (if only there wasn't that use/mention problem
with the variables). 

I think there needs to be something that clearly and unambiguously says
that C$c is the value being iterated over and clearly makes a
correspondence between the other variables and their position relative
to C$c even with whatever other syntactic mumbling may be necessary.
(And maybe the proposed use of ? is it, but it feels wrong to me)

But, don't we have something like

for @list.kv - $i,$x { ...  }

and even if I'm misremembering @Larry's blessing on that particular
construct, we certainly have this:

for zip([EMAIL PROTECTED](),@list) - $i,$x { ... }

And then getting the values fore and aft of the current value is just a
matter of indexing into @list. This seems clearer to me than virtual
parameters that exist on either side of the sliding window of the real
parameters.

Also, since for seems to be some kind of non-consumptive iterator, maybe
we can get at it with some magical $?ITERATOR variable if we need to:

for @list - $x {
   my ($b1,$b2) = $?ITERATOR.prev(2);
   my ($a) = $?ITERATOR.next;# defaults to next(1)
}

Though that's far more syntax than using zip, but has the advantage
that it would work when @list really is a list rather than an array.

I still like using zip() or .kv and indexing the array directly. Putting
the values in an Array-like thingy seems to be a smallish price to pay
for easily getting at some number of elements before or after the
current element.

Rambling in a pre-caffienated way,

-Scott
-- 
Jonathan Scott Duff
[EMAIL PROTECTED]


Maybe it's Just Nothing (was: Look-ahead arguments in for loops)

2005-09-29 Thread Luke Palmer
On 9/29/05, Austin Hastings [EMAIL PROTECTED] wrote:
 Matt Fowles wrote:
 
 for (1, 2) - ?$prev, $cur, ?$next {
say $prev  - $cur if $prev;
say $cur;
say $cur - $next if $next;
say next;
 }
 
 [...]

 I assume so because it's the only execution path that seems to work. But
 that would be assuming there was always at least one non-optional
 binding. Given that Luke's against all-optional signatures, too, I'll
 withdraw that part of the suggestion. And with at least one required
 binding, then there's no reason that we can't have the window extend on
 both sides of the current value.

 Luke?

Hm, I'm being called upon now.

Well, then I start to ask questions like:

for 1..10 - ?$a, $b, ?$c, $d, ?$e {...}

Which simply doesn't make any sense to me.  Also, figuring out such
things (as is the case with lookbehind argumentS) needs a little bit
too much knowledge about the signature of the function you're viewing.

So instead of sticking that in the signature, we could do it with
adverbs on for:

for 1..10, :lookbehind(1) :lookahead(1) - $cur, ?$left, ?$right {
...
}

You'll note that, unfortunately, the lookbehind has to come *after*
the cur argument because it must be optional.  Hmm... actually, that
doesn't work, because at the beginning of the list you won't have a
$left, and at the end you won't have a $right.

It's possible that it's time to start kicking undef into gear.  Until
now in Perl culture, undef has been just a little bit special, with
people not fearing to put it in lists and data structures.  There may
be benefit in making it more special, so that people shouldn't define
their own meaning for it.  Making exceptions undefs are a step in that
direction.  If we take another step in that exact same direction, we
could make undefs exceptions (the converse of before):

sub foo() {
return undef;# almost the exact same as fail
}

That is, under use fatal, all undef return values are converted into
exceptions.

That was somewhat beside the point, but not really.  If undefs are a
bit taboo--for example, actually writing undef in most code is
considered bad style--then we can steal them for the language's
purposes, such as passing to a for block as lookbehind and lookahead
parameters when you're near the beginning or end of a list.

It seems like I'm making a pretty big deal out of just passing undef
when there is no look-behind/-ahead, but I really want to be able to
distinguish between there was an undef in the list and we're almost
done, so there was actually nothing here.  Of course, I still don't
get to distinguish those, but a list with an undef in it becomes much
less common.

The way we can help ease the pain of undef not being available for
user purposes anymore is to allow easy manipulation of Either types. 
If you define easy weakly, then union types give us that:

union Maybe[::t] (Nothing, Just(::t));

Mmm, Haskellicious.  But of course you wouldn't need to declare your
types everywhere because of Perl's dynamic typing/type inference
(depending on your mood).  Nothing is nice, but I wouldn't call
working with Just easy for Joe Schmoe.  It's nice and safe, but it's
annoying sometimes.  What I might think I want is:

union Maybe[::t] (Nothing, ::t);   # not legal union syntax

You lose a lot with that, though.  For instance, Just(Nothing) becomes
unrepresentable.  And consequently, nested calls to things that return
Maybes become woosy.  So that's not a good idea.

So allowing the definition of Maybe is a good start.   But it's
difficult to know whether Perl programmers will put up with it.  It's
easier--lazier--just to use undef.

Maybe we ought to call the whole thing off.  Undefs have no stigma,
and everything is as usual.  If you want to iterate over a list with
lookahead and lookbehind, you shouldn't have put undefs in your list.

The last thing to do, if we want to keep the undef status quo, is to
define Maybe in the language and use it for things like for's
lookahead binding.  It's kind of like a formal undef, something like
listen, it's pretty common that I won't give you a value here, so I'm
going to mark it specially when I both do and do not.  Again, not
easy enough; too much abstraction to think about for an everyday task.
 I think my favorite so far is the previous paragraph's resolution. 
Just because it's my favorite doesn't mean I'm happy with it.

Oh, right, and as for my favorite actual usage of for:

for @list, :lookbehind(2) :lookahead(1)
- $behind1, $behind2, $value, $ahead {
...
}

Luke