Ick. I like 'is being an equivalence relation. Is there a way you could achieve what you want with 'testify instead?
I'm thinking something like this:
(def isa (x typ)
(.typ:testify type.x))
(extend testify (x) alist.x
[some _ x]) ; uses testify on '_ too!
This doesn't work on (case type.foo ...) though. In 'case, I'd prefer to be able to use predicates as the cases, so what I really want is for the cases to be testify'd. On the other hand, I still believe techniques like 'isa and (case type.foo ...) limit extensibility (even if you're trying to lift those limits a bit here ^_^ ), so I'm not married to any particular semantics for them.
"Ick. I like 'is being an equivalence relation. Is there a way you could achieve what you want with 'testify instead?"
Nope. I don't see a problem with overriding `is`, if that's what you want to do. If you don't want to override `is`, then just don't. Hell, you could override `is` and use testify, if you wanted to.
The point of the `is` attribute is that your object might have a custom idea of equivalence relationship. It's up to you, the designer of the object, to use a sane definition of "equivalence".
Now, if you had suggested to use `iso` instead of `is`, then I could be down with that, but then things like `isa` would need to be changed so they used `iso`... I'm not against the idea, but it would cause incompatibility with Arc/3.1.
I'll also note that the concept of something being eq to multiple things is not exactly new:
(is nil ())
(is nil '())
(is nil 'nil)
So I think you should be allowed to define a custom `is` behavior, when it makes sense for your object.
---
By the way, originally I extended `isa`, which did work fine, as long as you used `isa` only, but I really wanted it to be perfectly seamless. And, by doing this, I also get another benefit: objects can have a type of object and table, so (isa foo 'object) works:
(= foo (object))
(isa foo 'table) -> t
(isa foo 'object) -> t
I would still recommend using `object?` to test for object-ness, though. In addition, if I did this change, then I think I can fix the bug where you can't load the library more than once in the same namespace.
"It's up to you , the designer of the object, to use a sane definition of "equivalence"."
I agree, but your extension to 'is already violates the mathematical definition of an equivalence relation, so it's already insane as far as I'm concerned. For 'is to be an equivalence relation, if (is foo 'cons) and (is foo 'table), then anything equivalent to 'cons must be equivalent to 'table, and that renders the type checks rather useless.
---
"Now, if you had suggested to use `iso` instead of `is`, then I could be down with that, but then things like `isa` would need to be changed so they used `iso`... I'm not against the idea, but it would cause incompatibility with Arc/3.1."
Yes, I consider the pervasive use of 'is to be a flaw of Arc. I'm happy Wart doesn't approximate Arc in this way, and I don't design my languages/libraries to approximate Arc in this way either.
---
"(is nil ())"
When I use 'is, I'm asking if there's any possible way for me to distinguish the values. IMO, all ways to distinguish nil from () in Arc are "nonstandard," so (is nil ()) is just fine.
If there were a way to distinguish them, I wouldn't want (is nil ()) to be true. We could still have (iso nil ()), since 'iso can still be an equivalence relation with that constraint. (Everything 'iso to nil would be 'iso to () as well.)
"...then anything equivalent to 'cons must be equivalent to 'table, and that renders the type checks rather useless."
Right, so if your object has a type of both cons and table, it should definitely act like both a cons and a table, meaning it should have a car, cdr, etc.
---
"Yes, I consider the pervasive use of 'is to be a flaw of Arc. I'm happy Wart doesn't approximate Arc in this way, and I don't design my languages/libraries to approximate Arc in this way either.
[...]
If there were a way to distinguish them, I wouldn't want (is nil ()) to be true. We could still have (iso nil ()), since 'iso can still be an equivalence relation with that constraint. (Everything 'iso to nil would be 'iso to () as well.)"
Alrighty then, it looks like we have a bit of a viewpoint clash. You're seeing `is` as being like `eq`: super-strict, checking for exact equivalence. That's totally fine. I'm seeing `is` as being similar to, but a little bit looser than `eq`.
So perhaps what would be nice is if Arc had 3 operators: eq, is, and iso. eq is stricter than is, which is stricter than iso. Or perhaps we could just get rid of `is` completely and just use `eq` and `iso`.
In any case, those are incompatible changes, so given aw's position with ar, I'm not exactly planning to change ar in that way, even on my fork. Now, if we're talking about Arubic, then yes, perhaps Arubic could be designed differently, using iso everywhere rather than is.
But in the context of ar, I think overloading `is` in this way is the most reasonable choice, given how much of Arc uses `is`. Remember: my goal with this library is to allow you to easily and concisely create both new data types, and also data types that resemble existing data types, like tables.
Thus, I want objects to be as seamless as possible with the existing language. Unfortunately, that means that if the existing language made some poor choices, my library might end up doing something that's kludgy or hacky to make it work. Or hell, maybe the language is perfectly fine, and my library is just hacky and kludgy. :P
In any case, I think an object library designed more in line with a perfect ideal Arc would probably be designed differently than mine, and I'm okay with that, since mine is designed to get things done within existing Arc code.
"Right, so if your object has a type of both cons and table, it should definitely act like both a cons and a table, meaning it should have a car, cdr, etc."
We're miscommunicating spectacularly today. XP
If any one thing is equivalent to both 'cons and 'table, then everything equivalent to 'cons must be equivalent to 'table (for us to be talking about an equivalence relation). This means that if anything's type 'is the symbol 'cons, then its type 'is also 'table. All conses are tables. The converse holds too: All tables are conses.
This is absurd (in a non-mathematical way ^_^ ), so we shouldn't let it get that far: Either you must believe that 'is is not an equivalence relation, or you must accept you're not using 'is propahlay. Anyway, I think you are consciously resigning yourself to one or both of those things, in order to "get things done within existing Arc code."
Personally, I'm very worried Arc-compatibility in ar will hold it back in ways like this.... I'm going to do what I can to help establish compatibility anyway though.
---
"So perhaps what would be nice is if Arc had 3 operators: eq, is, and iso."
Aahhhh, no way. XD I think Akkartik says it pretty well at http://arclanguage.org/item?id=13690: "But the problem isn't that it's impossible to find the one true semantic for equality or coercion, it's that the language designers didn't put their foot down and pick one. Don't give me two different names with subtle variations, give me one strong name."
This helps because there's just one utility for people to use and extend, not a variety of utilities which compete for attention. And as I say at http://arclanguage.org/item?id=12803, if we need a different notion of equality, we can define a wrapper type with its own 'iso support which compares its contents using that new notion.
But in ar, maybe you're right. From http://arclanguage.org/item?id=248, it's clear that your lax interpretation of 'is is consistent with pg's intentions for it. Perhaps ar should provide 'eq and each Arc variant running on ar should choose its own notion of equality.
"All conses are tables. The converse holds too: All tables are conses."
Woah, hey, that gives me an idea... :P
---
"This is absurd (in a non-mathematical way ^_^ ), so we shouldn't let it get that far:"
You sure about that? :P
In all seriousness, I considered representing tables in Arubic as alists (or possibly plists). But that's getting off-topic...
---
"This helps because there's just one utility for people to use and extend, not a variety of utilities which compete for attention."
Absolutely. So I went in and extended `is`. But now you're saying that extending `is` is bad because you want `is` to behave like `eq`. :P It was part-serious and part-joking, since although it would solve this particular problem, I can understand your reluctance to add in a zillion equality-testing things.
---
"Perhaps ar should provide 'eq and each Arc variant running on ar should choose its own notion of equality."
Sounds good to me, provided that I can use Arc's `is` when I want to. In other words: ar provides eq, Arc/ar provides is, and Arc variants can choose to use either one, both, or neither.
---
"Personally, I'm very worried Arc-compatibility in ar will hold it back in ways like this...."
Me too. Personally, I want to just go in and rip up things, and have a backcompat.arc file that smooths over things, but alas... Hell, that's what I did on my fork, and backcompat.arc is loaded automatically, so it behaves almost exactly[1] like Arc/3.1.
---
* [1]: The primary difference is when you want to extend something. For instance, let's say you wanted to extend "no". But my fork doesn't use "no", it uses "not", so you'd be extending the wrong thing. Stuff like that. Probably possible to work around, but ugh.
So, if I can get a perfect compatibility layer, then sure, let's go with that, but as long as it's imperfect, then there will always be some niggling corner case which could be used as justification for not changing ar.
As I'm sure you're aware, conses and tables are an arbitrary part of the example. ^_^ If you wanted anything to act as both a 'num and a 'cons, then all conses would be nums too.
---
"Me too. Personally, I want to just go in and rip up things[...]"
Yeah... I wonder if I should be forking your ar instead of working on aw's. >.> It would become a fork of a fork of a fork of an Arc. :-p Maybe since it's hard to pull-request all those changes, you could treat your ar as a separate project?
Eh, I'm not usually one to make an Arc spinoff from existing source anyway. I'm more likely to either give advice from the sidelines or start from Racket (or JavaScript) and implement utility layers on top of it until I have a system I like. So don't worry about my participation either way, heh. ^_^;
"As I'm sure you're aware, conses and tables are an arbitrary part of the example. ^_^ If you wanted anything to act as both a 'num and a 'cons, then all conses would be nums too."
Of course, I was joking. Wait a second... we could Church encode numbers... then they really would be conses...! (I wonder how much longer I could keep this up :P)
---
"Maybe since it's hard to pull-request all those changes, you could treat your ar as a separate project?"
Yeah, I'm kinda leaning toward that, especially since some of my changes break backwards compatibility, and aw has made it pretty clear that Arc/ar is aiming at compatibility.
"I wonder how much longer I could keep this up :P"
Probably until we reach "Everything's an object." Then we can take a look at all the ways we distinguish certain objects from others, and we can start all over again. ^_^