>When you write:

>    (1..Inf) equal (0..Inf)

>I'd like Perl to consider that false rather than having a blank look
>on its face for a long time.  

The price of that consideration would be to give the Mathematicians
blank looks on *their* faces for a very long time instead.  Certainly,
they'll be quick to tell you there are just as many whole numbers
as naturals.  So they won't know what you mean by equal up there.

The Engineers might also be perplexed if you make that false, but
for rather different reasons.  I think that you will have to define
your "equal" operator in a way contrary to their respective
expectations, because both have ways of thinking that could quite
reasonably lead them to expect the answer to the expression above
to come out to be false, not true.

Practically speaking, I'm not sure how--even whether--you *could*
define it.  One is tempted to attempt something like saying that
operator "equal" is true of a *lazy*, *infinite* list if and only
if elements 0..N of both lists were each themselves "equal", and
then only blessedly finite values of N.

But where then do you stop?  If N is 1, then (1..Inf) and (1..Inf:2)
are ok.  If N is 2, meaning to check both the first pair from each
list and also the second one, they aren't.  However, if N is true,
(1..Inf) and (1, 2..Inf:2) are certainly ok.

In fact, that definition seems trivial to break.  Given a known N
steps of comparison, the lazy lists (1..Inf) and (1..N-1, (N..Inf:2))
would both test equal in the first N positions and differ in position
N+1.  Therefore, we can always break any operator that tests the
first N positions of both lazy lists, and thus that definition would
be wrong.

The reason Mr Engineer might expect false would be if they thought you were
eventually testing against Inf.  Due to his experience in numerical
programming, he sees NaN and Inf having certain behaviors that no pure
mathematician would even countenance.  On a system whose system nummifier
knows things like Inf and NaN already, you see this happening even today.
Witness real Perl:

    % perl -e 'printf "%g\n", NaN'
    nan
    % perl -e 'printf "%g\n",  1 + NaN'
    nan
    % perl -e 'printf "%g\n", 42 * NaN'
    nan
    % perl -e 'printf "%g\n", Nan == NaN'
    0
    % perl -e 'printf "%g\n", 1+Nan == NaN'
    0
    % perl -le 'printf "%g\n", Inf'
    inf
    % perl -le 'printf "%g\n", 1+Inf'
    inf
    % perl -le 'printf "%g\n", 2+Inf'
    inf
    % perl -e 'printf "%g\n", Inf == Inf'
    1
    % perl -e 'printf "%g\n", Inf == -Inf'
    0
    % perl -e 'printf "%g\n", 1+Inf == Inf'
    1
    % perl -e 'printf "%g\n", Inf + Inf' 
    inf
    % perl -e 'printf "%g\n", Inf * Inf'
    inf
    % perl -e 'printf "%g\n", Inf / Inf'
    nan

=begin ASIDE

Yes, it's platform dependent what you'll get:

    mach1%  perl -le 'printf "On $^O, NaN == NaN is %g\n", Nan == NaN'
    On openbsd, NaN == NaN is 1

    mach2% perl -le 'printf "On $^O, NaN == NaN is %g\n", Nan == NaN'
    On linux, NaN == NaN is 0

I believe that's because the libc on openbsd doesn't nummify string "NaN"
to any special IEEE float, whereas the redhate one did.

I am truly hoping that on Perl6, comparing "apples" with "greed" will mean
that you're testing NaN with itself, that testing NaN and *anything*
including another Nan with == will get you into trouble no matter what your
platform, and that that trouble will be the same irrespective of platform.

=end ASIDE

In other words, if you treat Inf as any particular number (which Mr
Mathematician stridently yet somewhat ineffectually reminds you that are
*not* allowed to do!), then you may get peculiar results.  Heck, you could
probably then get Mr Engineer to agree that the lazy lists (1..Inf) and
(0..Inf) are the same in the *last* N positions for all values of N, and
since you could just select N to be equal (ahem) to the length (ahem**Inf)
of your list, they must be equal. :-)

Mr Mathematician, purist that he is, has of course long ago thrown up his
hands in disgust, contempt, or both, and stormed out of the room.  To him,
most of those Perl examples given above were utter nonsense: how can you
say 1+Inf?  It bothers him to talk about Inf+1, and 1..Inf will be
problematic, too, since to say 1..Inf is also to say there must exist some
number whose successor is Inf.  And of course, there isn't.  Which is why
Inf is not a valid operand for numerical questions in Mr Mathematician's
platonically purist world of ideas.  But practical Mr Engineer has defined
his own Inf in which you can do limited otherwise apparently numerical
operations, because it was *practical* for him to do so.  He had work to
do, and needed some new rules.

While Mr Mathematician won't put up with comparing numbers and infinities,
he's quite comfortable with comparing *infinities* themselves.  He's
comfortable with infinite sets, and he's comfortable with infinite series,
too, which is what these lists seem to be.  I'm not sure that his
experience with infinite series will help us much here, because you see, 
those aren't finite (duh).  It's all fine to talk about the limit 
of some convergent infinite series like the sum of 1 / (2 ** N) as 
N goes from 1 to Inf, but that doesn't really seem applicable to us here.

So instead of thinking about infinite series, perhaps Mr Mathematician will
when seeing your expressions (0..Inf) and (1..Inf) think of infinite 
sets.  Certainly (0..Inf) corresponds to the Whole Numbers and (1..Inf)
corresponds to the Natural Numbers, so this isn't a great stretch.

Perilously, the notion of comparing infinite sets takes you down Cantor
Lane, an infinitely long road whose alleys threaten madness.  There, there
exists a notion of "equal" that is defined to be true whenever elements of
both infinite-set operands can be paired up sequentially--if you can make a
one-to-one correspondence between enumerable set members.  Under that
definition, these all hold true

    (0..Inf)                equal   (1..Inf) 

    (1..Inf)                equal   (1..Inf:2) 

    (1..Inf:2)              equal   (1..Inf:5) 

    (1..Inf)                equal   (1..Inf:100) 

    (1..Inf)                equal   (1..Inf:Googleplex) 

    (The Set of Integers)   equal   (The Set of Rationals)

And therefore, Mr Mathematician would not be surprised by a definition of
equals that allowed all of those to come out saying that they are true.

However, Mr Mathematician would therefore also expect any sort of testing of 

    (The Set of Integers)   equal   (The Set of Reals) 

to come out not true but false, due to Mr Cantor's Diagonalization Proof.
Eek.  Let's please not go there.

Thankfully, we don't even have real numbers on a computer, just
finite-sized sets of rationals masquerading as real numbers.  Only on a
computer are there "more" rationals than integers, and well, even there it
seems to me that given equal bitlength of N in both int and float types,
that, well, perlifically speaking, (1..2**N) equal (1..2**N), eh? :-)

Anyway, all fun and games with Messrs Engineer and Mathematician,
you still want to find some sensible way of comparing lazily evaluated
infinite lists so that you could get some sort of answer.  But what
is that answer?  Or what is *an* answer?  Can there even *be* one?

>So whatever equivalence and ordering operators we end up with, they
>had better be able to do lazy comparisons of characters or elements
>and give up as soon as they know the answer.  In fact, they need to
>be smarter than that if we also want:

>    (0..Inf) equal (0..Inf)

>to run in finite time.  Lazy arrays need to delegate the operation
>to their underlying generators whenever possible.

As I've outlined above, I'm not completely certain that that strategy--or
in fact *any* possibly strategy--is necessarily guaranteed to provide a
sensible answer to what may or may not be a sensible question after all.

--tom

Reply via email to