ODD? Defined in Terms of EVEN?

I've been slowly migrating generic dispatch to a new mechanism that's more extensible, and also provides the ability to have common code which does pre-or-post processing on what the generic portion does.

This raises semantic questions everywhere. Something as simple as EVEN? and ODD? you can ask how this should be defined in terms of other things.

Is there just a generic MODULO function, that you use with 2 and ask if it produces 0 or 1 to get the behavior of EVEN? and ODD? Or are EVEN? and ODD? separate methods? Or is EVEN? a method and ODD? just defined as the negative of that? Or vice-versa?

(You can even have fallbacks... e.g. EVEN? could check to see if there's a specific narrow methodization for EVEN? and use that if so. But if not, it could then see if MODULO of 2 was available and worked.)

This is a big headache, and I wish I didn't have to care. But until all these things are migrated, the old generics system is just hanging around being lame.

So I have to do something with it.

Haskell Defines ODD in Terms Of EVEN

 even :: Integral a => a -> Bool
 even n = n `mod` 2 == 0

 odd :: Integral a => a -> Bool
 odd n = not (even n)

The operations specifically require things to be "Integral", and do mod

Historically EVEN? and ODD? have been able to work not just on INTEGER!, but also on TIME!, DATE!, PAIR!, MONEY!...

Leading to the question: Why would EVEN? and ODD? be defined for all these things? What does it even mean to say a pair of two numbers is even or odd? Does DATE! tell you if the day is even, the month...? Does the TIME! tell you if the seconds are even?!? :pouting_cat:

For The Curious, The Answers Were...

DECIMAL! tested the rounded version, I guess? :roll_eyes:

(even? 0.0)
(not even? 1.0)
(even? 2.0)
(not even? -1.0)
(even? -2.0)
[  https://github.com/metaeducation/rebol-issues/issues/1775
    (even? 1.7976931348623157e308)
]
(even? -1.7976931348623157e308)

CHAR! tested the codepoint:

(even? NUL)
(not even? #"^a")
(even? #"^b")
(not even? #"^(ff)")

Time Tested seconds:

(even? 0:00)
(even? 0:1:00)
(even? -0:1:00)
(not even? 0:0:01)
(even? 0:0:02)
(not even? -0:0:01)
(even? -0:0:02)

Date checks the day, though there's no test of that.

There's no test for PAIR!, and it seems like it's just something in the type signature that's not supported (presumably because someone copied the type spec from somewhere else, and it had PAIR! in it, but there's no actual implementation).

Weirdness, But If It Supports MODULO...

Trying to explain to people the semantics of why a TIME! or a PAIR! or a DECIMAL! is even or odd requires explaining what you're doing in terms of the conversion to get the integer to test.

But... if your datatype supports MOD, I guess it's reasonable enough to say that if MOD 2 = 0 is true then it's even... but:

rebol2>> modulo 0:1:00 2
== 0:00

That doesn't "equal zero" in terms of precise equality with the integer 0. But the ZERO? test might say it's the zero for the type.

So is it ZERO? of MODULO with 2...?

:face_with_head_bandage:

This Is Not A Big Concern For Me

But I have to get rid of the old generics.

  • I'm going to delete the PAIR! from the type spec, that's nonsensical

  • I'm going to delete the DECIMAL! implementation because even? 1.5 is ridiculous. If you want to test the rounded number, say how you're rounding and test the integer result.

  • I'm going to delete the DATE! implementation, because if you want to check if the day of a date is even, say that.

  • I'm not going to support it for RUNE!, because since the unification of CHAR w/ISSUE it makes sense on even fewer cases.

But for now I'll leave the TIME!, as an example of "we could methodize EVEN-ness, if you had some concept of evenness and oddness of an arbitrary type, perhaps even not an arithmetic one".

So there'll be a separate EVEN? entry point... with ODD? defined as the negation of whatever that answers. I'll let people of the future (AI of the future?) worry about it.

2 Likes