Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Rebol interpreter bug with comparison of dates

 [1/25] from: al:bri:xtra at: 4-Dec-2002 11:34


I discovered a problem with dates and comparisons:
>> 'foo < 4/Dec/2002
== false
>> 4/Dec/2002 < 'foo
** Script Error: Cannot use lesser? on date! value ** Near: 4-Dec-2002 < 'foo Note that the comparison can't be reversed. This seems to affect all Rebol versions, including Rebol/Base. The correct response from Rebol should be like:
>> 4/Dec/2002 < 'foo
== false Andrew Martin -><- Andrew Martin

 [2/25] from: jan:skibinski:sympatico:ca at: 3-Dec-2002 18:51


Hi Andrew, The problem seems to be much broader:
>> 2 < 'foo
** Script Error: Expected one of: integer! - not: word! But at least in this case the error message makes some sense. Personally, I don't mind such a behaviour, which disallows comparison of apples to oranges. But I think the definition of (<) is too broad: it should be more specific - narrowed down to the orderable things, such as numbers, dates, but not points, etc. However, since the arguments of this operator are untyped, the "help <" suggests that one can compare anything to anything - and hence those unpleasent runtime surprises. Jan [al--bri--xtra--co--nz] wrote:

 [3/25] from: carl:cybercraft at: 4-Dec-2002 13:51


On 04-Dec-02, [al--bri--xtra--co--nz] wrote:
> I discovered a problem with dates and comparisons: >>> 'foo < 4/Dec/2002
<<quoted lines omitted: 7>>
>>> 4/Dec/2002 < 'foo > == false
Don't you mean true? Surely they both can't be greater than each other? -- Carl Read

 [4/25] from: carl:cybercraft at: 4-Dec-2002 15:23


On 04-Dec-02, Jan Skibinski wrote:
> Hi Andrew, > The problem seems to be much broader:
<<quoted lines omitted: 10>>
> runtime surprises. > Jan
Going by previous comments, I think the comparing of different types is allowed so routines for soting them will work. ie...
>> sort [2 foo]
== [foo 2]
>> sort [foo 2]
== [foo 2] -- Carl Read

 [5/25] from: jan:skibinski:sympatico:ca at: 3-Dec-2002 21:56


Carl Read wrote:
> On 04-Dec-02, Jan Skibinski wrote: > > Hi Andrew,
<<quoted lines omitted: 19>>
> -- > Carl Read
Hi Carl, But there is a lack of consequence, because this works:
>> sort/compare [1 3 11 2] (func[x y][x > y])
== [11 3 2 1] and this fails:
>> sort/compare [2 foo] (func[x y][x > y])
** Script Error: Expected one of: integer! - not: word! Jan

 [6/25] from: al:bri:xtra at: 4-Dec-2002 16:14


Carl wrote:
> Andrew wrote: > > The correct response from Rebol should be like: > >>> 4/Dec/2002 < 'foo > > == false > > Don't you mean true? Surely they both can't be greater than each other?
I'm right. :) Both: 4/Dec/2002 < 'foo and: 'foo < 4/Dec/2002 should return 'false, because both are invalid comparisons. Andrew Martin ICQ: 26227169 http://valley.150m.com/

 [7/25] from: al:bri:xtra at: 4-Dec-2002 16:24


Jan wrote:
> Personally, I don't mind such a behaviour, which disallows comparison of
apples to oranges. But I think the definition of (<) is too broad: it should be more specific - narrowed down to the orderable things, such as numbers, dates, but not points, etc. However, since the arguments of this operator are untyped, the "help <" suggests that one can compare anything to anything - and hence those unpleasant runtime surprises. I prefer being able to compare any-value with any-value. I think it's more versatile, as it enables one to write 'find -like functions that can find values in a series and not have to type check first. Here's an example that I was working on today (and where I found the problem): Find-Range: function [Ranges [block!] Value [any-type!] /Strict] [Range] [ repeat Index length? Ranges compose [ ; 'Compose adds more comparisons! Range: Ranges/:Index if all [Value >= Range/1 Value <= Range/2] [ return at Ranges Index ] ( if not Strict [ [ if Value < Range/1 [ return at Ranges max 1 Index - 1 ] if all [ Value > Range/2 Index >= length? Ranges ] [ return at Ranges Index ] ] ] ) ] ] ; The following is normally in a separate file: save %Term.r [; First and Last dates for each term. [28/Jan/2002 28/Mar/2002] [15/Apr/2002 28/Jun/2002] [15/Jul/2002 20/Sep/2002] [ 7/Oct/2002 6/Dec/2002] ] Term: first Find-Range load %Term.r now/date First_day_of_Term: first Term Last_day_of_Term: last Term Which finds the current (school) term for the current date (with allowance for a date before or after the individual terms). Andrew Martin ICQ: 26227169 http://valley.150m.com/

 [8/25] from: al:bri:xtra at: 4-Dec-2002 17:07


Jan wrote:
> >> sort/compare [1 3 11 2] (func[x y][x > y]) > == [11 3 2 1]
Just a helpful hint: One doesn't need to use parenthesis around the func and it's two blocks. So:
>> sort/compare [1 3 11 2] func[x y][x > y]
== [11 3 2 1] :) Andrew Martin ICQ: 26227169 http://valley.150m.com/

 [9/25] from: jan:skibinski:sympatico:ca at: 3-Dec-2002 23:44


Hi Andrew,
> I prefer being able to compare any-value with any-value. I think it's more > versatile, as it enables one to write 'find -like functions that can find > values in a series and not have to type check first. Here's an example that > I was working on today (and where I found the problem):
One of us is really confused here. :-) I am provoked to use the type annotations here, but believe me - that was not my intention to start with. :-) You wrote a generic function find-range :: [[b]] -> b -> [[b]] which accepts a block of blocks of entities 'b and an entity 'b as its two arguments, which you call 'Ranges and 'Value. Your function produces as a result a block of blocks of the same entity 'b. And you do not compare apples to oranges inside your function! You correctly compare entities of the same type. But you wrote the GENERIC function, which can work on any GENERIC variable 'b, such as DATE, or an INTEGER, etc. For example::
>> find-range [[1 3][31 35] [38 91]] 32
== [[31 35] [38 91]] So why do you need comparing apples to oranges, may I ask? Best wishes, Jan P.S. Thanks for the advice about redundant parenthesis

 [10/25] from: jan:skibinski:sympatico:ca at: 4-Dec-2002 0:35


> I wrote: > > You correctly compare entities of the same type. But you wrote > the GENERIC function, which can work on any GENERIC > variable 'b, such as DATE, or an INTEGER, etc.
To be more precise I should have added to the above: - subject to the condition that 'b is orderable. Generic as it is, your function should fail for a type b = POINT and many other unorderable entities.

 [11/25] from: anton:lexicon at: 4-Dec-2002 17:00


Andrew, An invalid comparison should throw an invalid comparison error. If a < b returns false, that implies that a >= b should return true, but under your scheme it would also return false. I think your scheme would produce far more complications. Maybe an explanation for the problem is that the < operator tries to convert the second argument to the datatype of the first argument. So a word can perhaps be converted to a date (I did this in the console via a string). But I had trouble converting a word to a date! Anton.

 [12/25] from: al:bri:xtra at: 4-Dec-2002 20:15


Jan wrote:
> You correctly compare entities of the same type. But you wrote the GENERIC
function, which can work on any GENERIC variable 'b, such as DATE, or an INTEGER, etc. For example::
> >> find-range [[1 3][31 35] [38 91]] 32 > == [[31 35] [38 91]] > > So why do you need comparing apples to oranges, may I ask?
Unfortunately, my example wasn't good enough to show why. Sorry about that. I wanted to make 'Find-Range operate _exactly_ the same way as Rebol's 'find works:
>> find [1 2 3 foo "test" #issue] 'bah
== none
>> find [1 2 3 foo "test" #issue] "test"
== ["test" #issue] Note that 'find can find any value in the series, just like 'Find-Range can find any range that matches the value. This allows me to extend the words in my Rebol vocabulary. Andrew Martin ICQ: 26227169 http://valley.150m.com/

 [13/25] from: carl:cybercraft at: 4-Dec-2002 21:08


On 04-Dec-02, Anton wrote:
> Andrew, > An invalid comparison should throw an
<<quoted lines omitted: 4>>
> I think your scheme would produce far more > complications.
I tend to agree here - it should return an error when it doesn't make sense to compare different datatypes.
> Maybe an explanation for the problem is that > the < operator tries to convert the second
<<quoted lines omitted: 18>>
>> >> Andrew Martin
-- Carl Read

 [14/25] from: anton:lexicon at: 4-Dec-2002 19:29


Sorry, I meant: So a *date* can perhaps be converted to a *word*. But I had trouble converting a word to a date! Anton.

 [15/25] from: g:santilli:tiscalinet:it at: 4-Dec-2002 11:49


Hi Andrew, On Wednesday, December 4, 2002, 4:24:42 AM, you wrote: AM> I prefer being able to compare any-value with any-value. I think it's more AM> versatile, as it enables one to write 'find -like functions that can find safe-greater?: func [ "A GREATER? that works with all datatypes" value1 value2 ] [ greater? reduce [:value1] reduce [:value2] ] safe-lesser?: func [ "A LESSER? that works with all datatypes" value1 value2 ] [ LESSER? reduce [:value1] reduce [:value2] ] Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [16/25] from: jan:skibinski:sympatico:ca at: 4-Dec-2002 10:07


Hi Gabriele, You just proved that you could do anything with Rebol. :-) But what does this mean:
>> safe-greater? 2x4 1x3
== true This is a classical example of concept stretching and this is what bites later on. (Ignore what follows, or read on - this is just and example illustrating the above statement.) .......... This is what happened in Haskell Prelude, where someone erronously decided to define a class Num of numbers as entities supporting: (+), (-), (*), (>), (<), (==) and few other operations. (The comparison operations got there by inheritance from the Ord class, but that's the minor detail .) Any entity claiming to be an instance of the Number class, such as Integer, is entitled to use any of those operators. As a tradition has it with any newly designed language, noone cared at that time about complex numbers. [It happened in C, in Eiffel, in Java, in Rebol - you name it.] So when the datatype Complex was finally introduced a natural reaction was to make it an instance of a Num class, so one could use (+) in expressions like this: c + d where c = (2, 3) d = (1, 0) But then the concept stretching took place, as far as the comparisons are concerned. Complex numbers, similar as pairs in Rebol, are not orderable. Of course, you can always make arbitrary decisions and say: "Well, this is just one exceptional kind of number, so let us compare it by its norm: square-root x * x + (y * y)". And so they did. But this is not what the mathematicans like, and unfortunately this is not the only one single exception. People started thinking: "Why cannot I use (+) operation on my matrix package? True, a matrix is not a number, but I can add matrices, can't I? Give me back my (+) operator so I will use it with grace anywhere where it make sense to use it!" But the problem with this is that in order to use (+) one would have to make Matrix datatype an instance of class Num, which obviously is a gross misnomer. But even if this was somehow acceptable, the Matrix would have to support all other operations from the Num class - including comparisons: (>), (<), etc.? But how to compare two matrices? What does is mean: mat-a > mat-b? Well, this is where the concept stretching has bitten again. To start with, there was no need to throw all those arithmetic and comparison operations into one common class and call it the Num. One could start small and define a RING class that supports only two operations: (+) and (-), or (+) and 'negate if you wish. Any number, including Complex could be made an instance of a Ring. Matrices could be rings too. And Tensors ... And one does not have to claim that one knows how to compare Complex numbers or Matrices. There is no need for it. To finish up the story: From time to time people come up with new proposals for alternative Haskell Prelude, where those things are to be clarified and corrected. Everyone agrees that this has to be done sooner or later. Unfortunately, things got so far already that it is hard to untangle the old jungle of misconceptions and its hard to decide on what is supposed to be backward compatible and whatt not. And the old Prelude still persists even though people complain, complain, complain.... Jan Gabriele Santilli wrote:

 [17/25] from: g:santilli:tiscalinet:it at: 4-Dec-2002 16:58


Hi Jan, On Wednesday, December 4, 2002, 4:07:13 PM, you wrote: JS> But what does this mean: JS> >> safe-greater? 2x4 1x3 JS> == true That REBOL will, for some reason, sort 2x4 after 1x3. (I wrote those two functions to use them in my b*tree implementation; you will want to insert in it any REBOL value like you can do in a REBOL hash!, and you will want it to sort values in the same way SORT does...) I know that this does not make sense, and RT knows too. A couple versions before the current one (maybe you were not here yet) GREATER? and LESSER? were able to compare pair!s; Carl decided that it wasn't a good thing after all and so now it gives an error. So, I agree with you that comparison only makes sense to things that can be ordered; however, due to its nature, REBOL will actually order any value, even if this ordering is absolutely arbitrary. You don't really want SORT to give back an error, and once we have a function that can sort any couple of REBOL values, we have an implicit (even if arbitrary) ordering relation between all of the REBOL values. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [18/25] from: joel:neely:fedex at: 4-Dec-2002 14:57


Hi, Jan, Just to take the "road less travelled"... ;-) Jan Skibinski wrote:
> But what does this mean: > >> safe-greater? 2x4 1x3 > == true > > This is a classical example of concept stretching and this > is what bites later on... >
I'm actually sympathetic toward your skepticism re "concept stretching" and have raised questions about how much we can sweep under the rug of polymorphism . However, on the specific issue of comparing PAIR! values, we've had this debate on the list a while back, and my personal conclusion was that 2x4 > 1x3 should evaluate to TRUE (and, of course, reversing the values should return FALSE ;-) My basis for arguing that position was that REBOL already has "unified" a number of data types through the concept (though without official terminology) of ordered composite values. Specifically, there are many types for which FIRST , SECOND , and so on, are defined. For example, in addition to the series types, for which the ordinal selectors have the obvious meaning, REBOL applies the selectors to dates as follows:
>> foo: now/date == 4-Dec-2002 >> first foo == 2002 >> second foo == 12 >> third foo == 4
to times as:
>> foo: now/time == 14:27:01 >> first foo == 14 >> second foo == 27 >> third foo == 1
and so on. (And we have the shorthand of X/1 for FIRST X and so on.) Now, if we have a type which is a sequence of component types, where each component type posesses a set of ordering relations, it seems perfectly reasonable to define the ordering relations on the (top-level) type in terms of the lexicographic ordering across the collection. In pseudo-REBglish, a < b whenever any [ a/1 < b/1 all [a/1 = b/1 a/2 < b/2] all [a/1 = b/1 a/2 = b/2 a/3 < b/3] ... and so on ... ] This works exactly as expected for DATE! and TIME! values, but also works for heterogeneous series values! (See the postscript for an exhaustive/exhausting illustration. ;-) The same game can be played for tuple values, BTW. That said, even though I completely agree that there is no "natural" ordering for cartesian coordinates *as spatial coordinates* I believe that there *is* a natural ordering for ordered pairs of integers, namely the lexicographic order. The PAIR! type certainly has all of the symptoms of being an ordered pair of integers, and has FIRST and SECOND (or /1 and /2) defined. Allowing PAIR! values to be treated as ordered pairs (including the support for lexicographic ordering in support of such an interpretation) shouldn't break any code that simply uses them as e.g. pixel coordinates, but would extend their range of possible applicability. In short, things that otherwise behave as tuples (in the Mathematical sense of the word, not in the REBOL TUPLE! sense) should all be able to participate in meaningful tuple-like behavior, including the ability to be lexicographically ordered. I'm now climbing down off my soapbox... ;-) -jn- Here's a generated example showing how REBOL handles order inquiries over heterogeneous blocks. (This is output from a wad of nested loops that actually set up the values and printed the output; I assume it is too obvious to waste bandwidth on.) [1 "A" #"a"] < [1 "A" #"a"] = false [1 "A" #"a"] < [1 "A" #"b"] = true [1 "A" #"a"] < [1 "B" #"a"] = true [1 "A" #"a"] < [1 "B" #"b"] = true [1 "A" #"a"] < [2 "A" #"a"] = true [1 "A" #"a"] < [2 "A" #"b"] = true [1 "A" #"a"] < [2 "B" #"a"] = true [1 "A" #"a"] < [2 "B" #"b"] = true [1 "A" #"b"] < [1 "A" #"a"] = false [1 "A" #"b"] < [1 "A" #"b"] = false [1 "A" #"b"] < [1 "B" #"a"] = true [1 "A" #"b"] < [1 "B" #"b"] = true [1 "A" #"b"] < [2 "A" #"a"] = true [1 "A" #"b"] < [2 "A" #"b"] = true [1 "A" #"b"] < [2 "B" #"a"] = true [1 "A" #"b"] < [2 "B" #"b"] = true [1 "B" #"a"] < [1 "A" #"a"] = false [1 "B" #"a"] < [1 "A" #"b"] = false [1 "B" #"a"] < [1 "B" #"a"] = false [1 "B" #"a"] < [1 "B" #"b"] = true [1 "B" #"a"] < [2 "A" #"a"] = true [1 "B" #"a"] < [2 "A" #"b"] = true [1 "B" #"a"] < [2 "B" #"a"] = true [1 "B" #"a"] < [2 "B" #"b"] = true [1 "B" #"b"] < [1 "A" #"a"] = false [1 "B" #"b"] < [1 "A" #"b"] = false [1 "B" #"b"] < [1 "B" #"a"] = false [1 "B" #"b"] < [1 "B" #"b"] = false [1 "B" #"b"] < [2 "A" #"a"] = true [1 "B" #"b"] < [2 "A" #"b"] = true [1 "B" #"b"] < [2 "B" #"a"] = true [1 "B" #"b"] < [2 "B" #"b"] = true [2 "A" #"a"] < [1 "A" #"a"] = false [2 "A" #"a"] < [1 "A" #"b"] = false [2 "A" #"a"] < [1 "B" #"a"] = false [2 "A" #"a"] < [1 "B" #"b"] = false [2 "A" #"a"] < [2 "A" #"a"] = false [2 "A" #"a"] < [2 "A" #"b"] = true [2 "A" #"a"] < [2 "B" #"a"] = true [2 "A" #"a"] < [2 "B" #"b"] = true [2 "A" #"b"] < [1 "A" #"a"] = false [2 "A" #"b"] < [1 "A" #"b"] = false [2 "A" #"b"] < [1 "B" #"a"] = false [2 "A" #"b"] < [1 "B" #"b"] = false [2 "A" #"b"] < [2 "A" #"a"] = false [2 "A" #"b"] < [2 "A" #"b"] = false [2 "A" #"b"] < [2 "B" #"a"] = true [2 "A" #"b"] < [2 "B" #"b"] = true [2 "B" #"a"] < [1 "A" #"a"] = false [2 "B" #"a"] < [1 "A" #"b"] = false [2 "B" #"a"] < [1 "B" #"a"] = false [2 "B" #"a"] < [1 "B" #"b"] = false [2 "B" #"a"] < [2 "A" #"a"] = false [2 "B" #"a"] < [2 "A" #"b"] = false [2 "B" #"a"] < [2 "B" #"a"] = false [2 "B" #"a"] < [2 "B" #"b"] = true [2 "B" #"b"] < [1 "A" #"a"] = false [2 "B" #"b"] < [1 "A" #"b"] = false [2 "B" #"b"] < [1 "B" #"a"] = false [2 "B" #"b"] < [1 "B" #"b"] = false [2 "B" #"b"] < [2 "A" #"a"] = false [2 "B" #"b"] < [2 "A" #"b"] = false [2 "B" #"b"] < [2 "B" #"a"] = false [2 "B" #"b"] < [2 "B" #"b"] = false -- ---------------------------------------------------------------------- Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446

 [19/25] from: jan:skibinski:sympatico:ca at: 4-Dec-2002 16:05


Hi Gabriele, A summary of this thread - as I see it: Things that break Joel's "Principle of the Least Surprise": + comparison functions are improperly documented + 'sort and 'sort/compare are logically incompatible. + arbitrary ordering of incompatible things is undocumented and subject to wild guesses, experiments and luck - if a third party code is documented. . Best wishes Jan Gabriele Santilli wrote:

 [20/25] from: jan:skibinski:sympatico:ca at: 4-Dec-2002 16:53


Ho Joel, Actually I do not mind lexicographical ordering - providing that I exactly know what it is. Some simple official rules would be helpful, such as a < b means mold a < mold b , or whatever. What to do when 'a is an object? Mold it? And I simply do not know, whether your list of rules is a norm, a suggestion, or whatever. My first sentence ever voiced in this thread was using words like "Personally, I do not mind". I am not trying to convince anyone to anything, and I consider it a personal choice whether or not someone wishes to take some kind of risks with their code. My personal choice is: "play it safe, play it by simple predictable rules." All the best, Jan

 [21/25] from: lmecir:mbox:vol:cz at: 5-Dec-2002 10:52


Hi Gabriele,
> So, I agree with you that comparison only makes sense to things > that can be ordered; however, due to its nature, REBOL will
<<quoted lines omitted: 3>>
> we have an implicit (even if arbitrary) ordering relation between > all of the REBOL values.
just a little nitpicking: unfortunately, your comparison functions will not compare any Rebol values. You would have to work harder to achieve that. The trouble is with: 1) errors 2) cyclic series Some inspiration can be found in http://www.rebolforces.com/~ladislav/evaluation.html . As to whether it is useful to have such comparison: Some applications may need it, therefore it might be handy. Ciao -L

 [22/25] from: g:santilli:tiscalinet:it at: 5-Dec-2002 12:35


Hi Ladislav, On Thursday, December 5, 2002, 10:52:18 AM, you wrote: LM> 1) errors LM> 2) cyclic series Is SORT able to put them in some order? (It looks like REBOL considers all error!s to be equal, and I was able to compare some simple cyclic blocks with my functions...) Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

 [23/25] from: lmecir:mbox:vol:cz at: 5-Dec-2002 21:47


Hi Gabriele,
> I was able to compare some > simple cyclic blocks with my functions...)
interesting, Rebol crashed here, but you probably used a beta, didn't you? Ciao -L

 [24/25] from: rotenca:telvia:it at: 5-Dec-2002 22:44


Hi Ladislav and Gabriele, I did not have any crash here. But how rebol sort Object? I did not see a logic in what happens:
>> sort reduce [context [a: "a"]context [b: "b"]]
== [ make object! [ b: "b" ] make object! [ a: "a" ]] --- Ciao Romano

 [25/25] from: g:santilli:tiscalinet:it at: 6-Dec-2002 2:26


Hi Ladislav, On Thursday, December 5, 2002, 9:47:08 PM, you wrote: LM> interesting, Rebol crashed here, but you probably used a beta, didn't you? Yep, this is View 1.2.8.3.1. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted