Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Add static Object.typeOf(_) (and deprecate Object.type ?) #1162

Open
mhermier opened this issue Mar 31, 2023 · 9 comments
Open

[RFC] Add static Object.typeOf(_) (and deprecate Object.type ?) #1162

mhermier opened this issue Mar 31, 2023 · 9 comments

Comments

@mhermier
Copy link
Contributor

Hi,
While working on the mirror module, I had to implement an equivalent of static Object.typeOf(_). Since Object.type is user over-loadable, it is not safe. Usually these guarantees are required when working with foreign functions.

Since most code does not need strong type guaranties, Object.is(_) is used instead. Because of that, deprecating Object.type should not have a wide impact. In addition is was meant to be overloaded to

I know at least 2 usage for Object.type to be over loadable:

  • Reuse the name type and rely on the fact that you don't do meta programming (wrenalyzer did that, to simulate enum).
  • Augment the class to augment the class data (done in a private experiment).
    Both of them are crude hack, and can make the user code fragile.

Forbidding the overloading of type is also a solution, but would require a lot of compiler support when generalized (tagging a method final can be interesting but introduce extra inheritance checks, and storage to track final methods)

I suggest that next version at miminum add static Object.typeOf(_). Deprecation of Object.type would be done at next or a future release, while its removal would be due before 1.0.0.

@PureFox48
Copy link
Contributor

I don't know about anyone else but I use Object.type quite a lot for checking arguments are of the correct built-in type where, of course, inheritance is not a concern and the method is perfectly safe.

As I'm allergic to using a lot of parentheses, I prefer to write:

if (arg.type != Num) Fiber.abort("Argument must be a number.")

rather than:

if (!(arg is Num)) Fiber.abort("Argument must be a number.")

I also occasionally use it in string form where I want to refer to a type in a different module without importing that module.

if (arg.type.toString == "BigInt") { // do something }

I don't know why it was made an instance method in the first place unless it was to allow type 'spoofing' which I think is the second usage you alluded to. That's not something I recall ever doing myself but who knows what other folks get up to!

So, whilst I have no problem with the introduction of a static Object.typeOf method, I'd personally prefer the instance Object.type method to remain and not be deprecated. The situation would then be analogous to the static Object.same method being an alternative to the overloadable == operator.

BTW, if static methods were to become inheritable and presumably therefore overloadable, then this solution wouldn't work anyway unless there was some way to make a static method final.

@mhermier
Copy link
Contributor Author

mhermier commented Apr 1, 2023

About your initial concern, it should be factorized to a utility function method in the first place. In the future, you may wan't to return an hypothetical TypeError or whatever. And it also become an opportunity to use !(arg is type) once and forget about it.

If static methods are inheritable, it won't change much, unless one wrongly use arg.type.typeOf(foo) instead of Object.typeOf(foo). Anyway, that error is easily fixable. In the other hand type "spoofing" is not. The VM is not fooled, but from the language there are no solution to get the true type without Object.typeOf(_) (or similar solution, like keyword of what ever).

@PureFox48
Copy link
Contributor

Well, I'll wait and see whether this change is accepted and what other breaking changes there are in the next version before changing any existing code.

My main concern is the 1600+ Rosetta Code tasks as the code for those is publicly available. I'm not really bothered about my private stuff as I'm forever fiddling about with that!

In the meantime, although I dislike it, I'll try and stick with !(arg is Num) for new stuff. If there were an isnot operator then my objection would disappear as we could then write arg isnot Num without the need for parentheses. I may do a PR to add this as is is the only boolean operator we have which doesn't have a convenient negative form.

Regarding the possibility that static methods might become inheritable and hence overrideable (which, like youself, I now hope doesn't happen) then, on the face of it, people would still be able to do stuff like this:

class MyClass {
    static typeOf(arg) {
        if (arg is this) return Num
        return super(arg)
    }

    construct new() {}
}

var mc = MyClass.new()
System.print(MyClass.typeOf(mc))  // Num

Incidentally and pedantically, I think we've both been guilty in this issue in talking about 'overloading' when we really mean 'overriding' inherited methods :)

@mhermier
Copy link
Contributor Author

mhermier commented Apr 1, 2023 via email

@PureFox48
Copy link
Contributor

This is the reason I said you should abstract the behavior in a function,

As it happens, I already have this in the form of my check module which can validate arguments of all kinds not just for type but for range as well. Curiously, I've used the !(arg is type) syntax throughout in this module so I must have had a premonition that this issue was coming :)

However, I introduced this late in the day and have used it mainly for inter-module checking. I haven't used it directly very much as I didn't want to ask people to import a 350 line module just to run a short script. But anyway that's my problem.

OK, I'll refrain from doing a PR for isnot if it's something you already have in hand for veery :)

@mhermier
Copy link
Contributor Author

mhermier commented Apr 1, 2023 via email

@mhermier
Copy link
Contributor Author

mhermier commented Apr 2, 2023

OT @PureFox48 out of curiosity do you have command line argument parser ? I have one that is not really OO and quite a lot manual (though I can factorize it to be OO)

@PureFox48
Copy link
Contributor

No, it's not something I've bothered to write.

There's one here though it's probably too simple for your needs.

@mhermier
Copy link
Contributor Author

mhermier commented Apr 2, 2023

Too simple but confirms that what I do is right, it is only a matter of making it more OO then ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants