Damian Conway wrote:
> I think I opened a bigger can of worms than I intended :-)

Yes, sorry about the overload of email you must of got from me on this, this
morning ;-)
>
> As MJD as pointed out to me in private email, if we are serious
> about this feature, we probably want to go the whole hog and
> look at Haskell's notion of list comprehensions. See
>
> http://www.haskell.org/tutorial/goodies.html
>
Exactly right. Haskell provides some great ideas, although there's more
perlish ways of thinking about it (give me a moment, I'll get back to
them...)

> Personally, I intend only to update the RFC to include the *possibility*
> of (..$x) and (..). I'm reasonably sure Larry will kill the whole thing
> -- I think I might too, were I in his place ;-)
>
Now don't encourage its death already! Still, I'm glad you're prepared to
keep it open.

> Rather than continue to argue the details, why don't people post some
> examples of code where they feel these lazy lists might be useful, and
> let's see if there aren't already good alternatives.
>
OK, you're on. But infinite lists (can I say that?... 'semi-finite' is a bit
weird) are one part of a bigger picture, so let me show you some code that
also incorporates higher-order functions, and an extension to Christian
Soeller's upcoming RFC on notation for slicing.

  @matrix = (1,3,4,2,6,7); # actually a flattened version of
[[1,3,4],[2,6,7]]
  @column1of3 = (1:3:); # Creates an infinite list (1,4,7,...)
  print sum(@matrix[@column1of3]); # Prints 3
  @matrix2 = readReallyBig3ColumnMatrixFromSomewhere();
  $column1Sum = sum(@matrix2[@column1of3]); # Handy, no need to redefine our
slice!

So, it provides some nice slicing notation. Note that more complex slicing,
masking, and indirection across n-dimensional tensors would make the win of
not having to respecify the indexes more substantial. But I'm trying to keep
the examples simple here...

Another win is in evaluation of lists constructed by generator functions:
  # ($start: f(__): $end) == ($start, f($start), f(f($start)), ...)
  @powersOf2 = (1:__*2:); # (1, 2, 4, 8, ...)
  @first10PowersOf2 = @powersOf2[0..9]; # Calculates 1st 10 powers of 2
  # ...interesting manipulation of @first10PowersOf2...
  @first20PowersOf2 = @powersOf2[0..19] # Calculates 2nd 10 powers of 2 (1st
10 are already computed!)

The real difference between an infinite list and a function with a domain of
the integers (other than notation) is that an infinite list is a guarantee
of stability. If we've already calculated @powersOf2[9], we don't have to do
it again when we next want it. The same is not true of 2^__, since perl
can't know that it returns the same result for every evaluation (for
instance, what if it was <>^__ ?)

You could argue that we could achieve the same with an attribute of a sub,
such as 'stable'. This would guarantee that this function returns the same
result each time it's called with the same arguments. Then perl would be
smart enough to cache the result of calls to this sub to avoid recalculating
it again later. Personally, however, I find this approach less intuitive.


Reply via email to