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

[REBOL] Re: Sameness - a pragmatic approach.

From: joel:neely:fedex at: 12-Feb-2003 6:39

Hi, Ladislav, Sorry! Didn't mean to ignore it! I distinguish between equality testing in general and equality over object methods (though they are certainly functions) because context makes a difference. Fundamentally we have to "shoehorn" three-valued logic into the REBOL two-valued LOGIC! type... Ladislav Mecir wrote:
> BTW, you didn't answer my question about equality of functions. > (I am not sure my question was understandable.) Have you got > any opinion? >
Me? Have opinions? ;-) Let me bound the answer with two assertions, and then try to narrow the gap. 1) I would not expect REBOL to determine general functional equivalence, that e.g. fun0: func [a [number!]] [a + 2] and fun1: func [a [number!]] [2 + a] are (intended to be) equivalent, much less fun2: func [a [number!]] [return 1 + a + 1] or fun2: func [a [number!]] [1 + a + 3 + a / 2] 2) My original question was in reference to the example of foo: make object! [a: 1 b: "Hi!"] baz: make object! [a: 1 b: "Hi!"] equal? foo baz where functions were not involved. It seems to me that this is not significantly harder to solve than fooblk: ["a" 1 "b" "Hi!"] bazblk: ["a" 1 "b" "Hi!"] without functions in the picture. With "elementary" types, EQUAL? is strictly two-valued: we can state with total confidence that two values are or are not equal. Aristotle would have been proud. There are really three possible answers for EQUAL? over function values: we know they are equal (probably SAME?), we know they are not equal (e.g. different argument signatures), or we simply can't tell (given a specific set of criteria). Of course EQUAL? must return a boolean value by definition, so we fold the "can't tell" case into FALSE (properly IMHO). Let me interrupt myself to assert the view that enhanced equality testing for objects should be concerned with correspondance of the attributes and content, without regard for ordering, so that altfoo: make object! [a: 1 b: "Hi!" c: false d: 3.14] would be considered equal to altbaz: make object! [d: 3.14 a: 1 c: false b: "Hi!"] because the *sets* of local words can be placed into 1-to-1 correspondance with equal names and values. Now back to our regularly scheduled program... So this leaves open a number of possibilities for object equality testing: 0) Give up unless the two objects are SAME? This is the present behavior AFAIK. 1) Define equality of objects without trying to analyze inner functions. This would allow equality testing over objects that are used as structured data containers, as in the common REBOL idiom: make object! decode-cgi system/options/cgi/query-string or the FOO and BAZ pairs above. Synonymous object attributes that are set to FUNCTION! values would be compared with EQUAL? which would still "do the right thing" for such cases as newfoo: make object! [a: 1 b: "Hi!" say: :print] newbaz: make object! [a: 1 b: "Hi!" say: :print] where the words referred to the same external/nonmethod func. This case would treat normal methods as "don't know" = FALSE . 2) Use a smarter "method-aware" equality test for the specific case of functions being compared as values of object-local words: two methods would be considered equal if corresponding arguments and refinements had the same names and types, their locals had the same names, and their bodies were the same except for the appearance of corresponding argument, local, refinment, and parent-object words, which would have to match in the obvious way. Thus we would get TRUE for EQUAL? over foofun: make object! [ a: 1 b: "Hi!" say: func [n [number!]] [ loop n [ print ["a" a tab "b" b] ] ] ] and bazfun: make foo [] ;; OK, I'm lazy... ;-) because of the following analysis: foofun type bazfun ---------------------- ---------------------- a: corr. a: 1 equal 1 b: corr. b: "Hi!" equal "Hi!" say: corr. say: func [ equal func [ n corr. n [number!]] [ loop equal [number!]] [ loop n corr. n [ print [ "a" equal [ print [ "a" a corr. a tab "b" equal tab "b" b corr. b ] ] ] ] equal ] ] ] ] (where I'm crowding as much "equality" as possible into one line for the sake of brevity). In all of these alternatives, there will still be "don't know" cases that become FALSE (i.e. our heuristics can't prove they are equal) but I see some virtue in pushing the envelope. My (uninformed) guess is that option (1) wouldn't be very costly to add, as we already have an equality test for functions:
>> stampa: :print >> equal? :print :stampa
== true We certainly don't want to wait for the interpreter to solve the Halting Problem, however! ;-) -jn-