#869 Obj.type => Obj.typeof

brian Tue 15 Dec 2009

Proposal background: #862 #680 #321

In most of the original discussions we toyed with the idea of also using the # symbol to mean get the type of an instance. That would allow us to free Obj.type up as a slot for general application code.

Just to review we currently use # for type and slot literals:

Str#         // type literal
Str#replace  // qualified slot literal
#mySlot      // slot literal for enclosing type

I propose two options for syntax where obj is any expression:

  1. obj#
  2. obj.#

The first is a little cleaner and perhaps more consistent with type literals. The second is a little more unambiguous in that you don't need to distinguish b/w type versus variable identifiers at parse time (although the Fantom compiler already does this so it is a taste issue, not really really a grammar issue).

Other options includes:

  • Java style: obj.class (since class is a keyword)
  • C# style: typeof(obj) using keyword operator

tactics Tue 15 Dec 2009

This syntax proposal is strictly decorative. It's not necessary to introduce a new syntax to get a Type from an Obj (clearly, because that's the way it's currently implemented). The real issue here is that a very common identifier, type, is being reserved, and we want to unreserve it. The simplest way to achieve this is to simply rename Obj.type to something new.

That said, I'm not against adding the new syntax. I just want to make sure there's still an Obj method to get the type of this.

I vote for option 1. It is the most consistent with the look and feel of the other uses of #.

Additionally, we could overload # to allow for slot lookups on objects, like we do for type literals. For example, foo#bar would be equivalent of Foo#bar where foo is of type Foo.

DanielFath Tue 15 Dec 2009

I'm with tactics on this. obj# seems as the most consistent with the use of #; As long as this can be used on object as well as classes.

If push comes to shove I could settle for something like obj.class.

andy Tue 15 Dec 2009

obj# seems most natural here. Otherwise I think I would go the typeof(obj) route.

qualidafial Wed 16 Dec 2009

+1 for obj#. I'm assuming that this# would also be a valid expression under the proposed syntax?

KevinKelley Wed 16 Dec 2009

Any time you assign a meaning to an arbitrary symbol, you have to accept that it will be a full-stop, break in the flow of understanding, to anybody that doesn't have the meaning learned. That said, some usage of symbols is useful for conciseness.

We seem to find it fairly reasonable to treat # as a type-meta-character, and obj# seems to be consistent with other usages, so I think this is in the category of, if you're going to do it (assign a meaning to a symbol), do it everywhere that it is applicable.

I actually like the way obj.class looks; it's hard to be more clear than that. But given that we've got # already, I vote for using it here.

typeof(obj) is understandable enough, but I don't want to see yet another syntax style introduced without serious need.

jodastephen Wed 16 Dec 2009

My vote is for obj# as it is the most natural syntax given the current Fantom design.

As I've indicated before, I believe that obj#method, if added, would return a BoundMethod which would be a new class holding the object and the method.

ivan Wed 16 Dec 2009

+1 for obj# But small note - will it be possible to use it with function calls, like this:

foo(a,b)# //type of function result object

I assume yes, and if so, since parens are not necessary when there are no parameters, we can write like this:

foo#

and in fact, if foo is a method, this looks very similar to #foo However there is no ambiguity from syntax point, and case is very rare.

Yuri Strot Wed 16 Dec 2009

obj.anyTypeSlotName also can produce FFI conflict, so obj# seems the best in all respects.

brian Wed 16 Dec 2009

OK - we'll go with the obj# syntax which formally will be an operator with same precedence as . -> [] etc used after an arbitrary expression.

I am not going to do anything for obj#slot - we'll leave that open for a future feature (most likely something along the lines of Stephen's bound slot for data binding).

Still one more decision - I still need a virtual method in the runtimes for accessing the actual Fan type. This method will still effectively take a name out of the sys::Obj slot namespace, so it should be obfuscated - convention has been to use $ in the JVM since it is a legal identifier for Java, but not for Fan. So I suggest we make that method type$. Now since that it is fairly ugly we can also create a static Type.of method which is the standard way to get a type from an object in Java code. I can also use Type.of in fcode instead of creating a new opcode.

Does that sound ok to everybody?

tactics Wed 16 Dec 2009

I still don't understand why we need to obfuscate the method name. Is there a technical reason to do so? Is it not possible to just rename Obj.type to Obj.fanType or Obj.typeOf? This way, the method still appears in the Fandoc for Obj, it appears in the slot list during reflection, you can call it with trap, etc.

Replacing Obj.type with # seems, to me, a needless reduction in power. It works exactly like a method, except that it is exempt from reflection.

Freeing up the Obj.type slot and adding this foo# syntax are two separate issues and it feels like we're mixing them together.

andy Wed 16 Dec 2009

I agree with tactics. The existing type method still needs to be made available. So I leaned towards Type.of from Brian's proposal. But since that method is still a proper virtual method on Obj, I think I prefer tactics suggestion of Obj.typeOf in order to free up type. And then maybe just punt on the obj# syntax until we decide how it fits into obj#slot. I don't have a huge preference on that one.

andy Wed 16 Dec 2009

Actually, type is not a normal virtual method, it is definitely something special. So, yeah, we need to remove that method from the Obj slot namespace. So I think the correct solution is what Brian proposed:

  • Type.of (needed for Java/.NET/JavaScript)
  • obj# sugar for Type.of(obj)
  • Remove Obj.type

tactics Wed 16 Dec 2009

After Andy restated it, it makes sense. Type.of works in place of Obj.type.

brian Wed 16 Dec 2009

Just to recap - Obj doesn't need any slot. Whatever static method or operator we come up with will work with any object (FFI objects included), so we don't really need any specific slot on Obj which would consume a name (even if we change to a more friendly name like Obj.typeof).

I was originally sort of obsessed with this being a terse operation, but tactics is the anti-Perl voice of reason here. I am not sure we really have to use an obtuse operator here just to save a few chars.

So my new proposal is:

  • Remove Obj.type instance method
  • Add Type.of static method
  • Add Pod.of static method

Leave any syntax sugar as a future discussion.

Examples:

type          =>  Type.of(this)
obj.type      =>  Type.of(obj)
obj.type.pod  =>  Pod.of(obj)

How does that work for everyone?

jodastephen Wed 16 Dec 2009

I agree with these being the method based options, but I strongly believe you should have the obj# syntax as well, as its so useful and consistent with the rest of the language.

DanielFath Wed 16 Dec 2009

I have a question though. How do I find slots from a Type in the new syntax? (Type.of(obj)).slots , Type.of(obj).slots or something else?

Personally the thing is a bit iffy but if it is a temporal solution I could live with it.

tactics Wed 16 Dec 2009

Type.of(obj).slots. Type.of(obj) will return the exact same thing obj.type does today.

qualidafial Thu 17 Dec 2009

+1 to Type.of(Obj). Perhaps even Type.of(Obj?) such that Type.of(null) returns Void#?

Let's hold off on the obj# syntax until we have a chance to learn from the above changes.

KevinKelley Thu 17 Dec 2009

+1 what qualidafial said.

tactics Thu 17 Dec 2009

+1 to Type.of(Obj). Perhaps even Type.of(Obj?) such that Type.of(null) returns Void#?

I don't really like this. We don't treat null and Void the same, as languages like Python and Haskell might.

I'd rather Type.of be typed as Obj? of(Obj?), returning null for Type.of(null).

brian Thu 17 Dec 2009

Promoted to ticket #869 and assigned to brian

Let's avoid nullables - I think this is a case where its best to just throw NullErr if you try to pass null. Having that method return Void# or null seems like we'd just be delaying the root error.

brian Thu 17 Dec 2009

Renamed from Proposal for obj.type => obj# to Proposal for obj.type => Type.of

brian Fri 18 Dec 2009

I added Type.of and Pod.of and deprecated Obj.type. In the build 49 I will remove it and type will be freed up as a valid slot name for your own code.

As part of this process I also deprecated Type.log and Type.loc since most of these use cases were convenience which is now better suited to using Pod.of:

type.log         =>  Pod.of(this).log
type.loc("key")  =>  Pod.of(this).loc("key")

After going thru all our own code, I think just using Type.of will work ok. It is a bit more noisy when you've gotten so use to chaining dot methods. But I think considering how often it is used, it doesn't make sense to tie up a valuable slot name or to introduce an additional operator.

EDIT: I also added Test.verifyType(Obj?, Type)

tactics Tue 22 Dec 2009

Did this ticket get resolved in 1.0.48?

brian Tue 22 Dec 2009

I added Type.of, Pod.of and deprecated Obj.type - but this issue isn't fully resolved yet until I can remove Obj.type and rework all the JVM/C# backend code.

tactics Tue 22 Dec 2009

Ok. Just checking.

brian Fri 8 Jan 2010

OK - I absolutely hate using Type.of - it sucks compared to how easy it was before. This is a failed experiment.

But I'm going to assume we still want to free up type for user code.

There are two options:

  1. Add # operator on instances
  2. Just rename type method to something else like typeof

I am going to propose option B for for three reasons:

  • it works with ?. operator to handle null
  • it works with interpolation so I don't have to wrap with ${}, for example "wrong type $foo.typeof"
  • it keeps the language simpler and keeps # in play for future features

Having type be a proper method just interacts with all the other language features better.

So I propose to keep type, but just rename it to typeof.

tactics Fri 8 Jan 2010

Just rename type method to something else like typeof

Definitely option B. I love my synatx sugar more than most, but this is just a method call.

Would it be better as typeOf? The spelling rules would suggest that, but typeof is easier to type.

brian Fri 8 Jan 2010

Would it be better as typeOf? The spelling rules would suggest that, but typeof is easier to type.

I think of typeof is a single word like the C# typeof keyword, or Java's instanceof

katox Fri 8 Jan 2010

But it is not a keyword. Why making it a special case where there are functions like toListOf in sys::List already?

andy Fri 8 Jan 2010

My main objection to type was that its a special non-virtual polymorphic method. But I can't argue against the naturalness of using it like a normal method call - so I'm fine with renaming to typeof. Tho probably needs to be typeOf for consistency.

brian Fri 8 Jan 2010

I prefer typeof over typeOf because:

  • I think it looks better
  • easier to type
  • consistent with C# typeof
  • consistent with Java instanceof

So I'd rather change toListOf to listof for consistency, rather that use typeOf.

tactics Fri 8 Jan 2010

I'd go for typeof as an exception to the rule.

jodastephen Fri 8 Jan 2010

My vote remains for option A, its a better more consistent approach.

Look at it from the other direction, why is Str# not Str.typeof, ie. a static method call?

There is an underlying grand unification here, which I wish I had more time to write about. Its about making the static part of a class an object, thus Str just becomes a globally scoped singleton variable referring to the static parts of the Str type, while astr would be a variable referring to the instance part of the Str type. In this model, you want a single mechanism to access the "typeof", whether the LHS is a singleton (static) or an instance.

DanielFath Sat 9 Jan 2010

Same here, A is consistent and therefore in my humble opinion a better approach.

Though consistent using of typeof is fine as well.

brian Sun 10 Jan 2010

My vote remains for option A, its a better more consistent approach.

I don't consider # off the table, in fact I want to leave it in place for lots of other stuff that we might do in the future.

But I don't think using a method call in an OO language is inconsistent. That advantage it has is interpolation and null safe calling which an operator won't provide.

KevinKelley Sun 10 Jan 2010

Agree, that Type.of(x) is turning out to be kind of a pain in the butt. Don't especially care, between x.type and x.typeof or whatever.

msl Sun 10 Jan 2010

Fantom already has:

  • Str# - Type literal
  • acme::SomeType# - Type literal
  • Int#plus - Slot literal
  • #echo - Slot literal

From a relatively new user's point of view, the intuitive thing to try (or at least the thing I'd try) to get an instance's type would be something like:

myStr:= "something"
echo(myStr#)

But I don't think using a method call in an OO language is inconsistent.

I think the most consistent mechanism comes from using # to refer to Type/Slot literals across the board - regardless of whether it's referring to a Type/Slot or an instance of something. So, my vote would be for whatever is internally consistent with the way other types are referenced (ie # over typeof).

As an aside, is there any reason it needs to be an either/or decision? Can we not have myStr# being sugar for myStr.typeOf?

katox Sun 10 Jan 2010

As an aside, is there any reason it needs to be an either/or decision? Can we not have myStr# being sugar for myStr.typeOf?

+1

lbertrand Mon 11 Jan 2010

Like msl or katox, I feel like being coherent with the rest of Fantom should be the way to go here.

brian Mon 11 Jan 2010

A month ago I would have said obj# is the way to go. But after a month of being really annoyed not using the dot operator with ?. and string interpolation I want type as a method.

That doesn't mean we won't do obj#, but I am not going to tackle that right now. That discussion needs to wait for when we potentially do bound methods. I don't want to rush that feature until we have time to think about the larger picture.

brian Thu 21 Jan 2010

Renamed from Proposal for obj.type => Type.of to Obj.type => Obj.typeof

brian Thu 21 Jan 2010

Ticket resolved in 1.0.49

I have renamed the Obj.type method to Obj.typeof.

I am going to leave the Type.of and Pod.of methods, I don't think it hurts anything to have an alternate method.

If anyone has Java code which was calling Obj.type, it will need to be fixed.

cbeust Mon 25 Jan 2010

Why typeof and not typeOf?

brian Mon 25 Jan 2010

Why typeof and not typeOf?

The answer was in the comment trail (but easy to get lost)...

I prefer typeof over typeOf because:

  • I think it looks better
  • easier to type
  • consistent with C# typeof
  • consistent with Java instanceof

cbeust Fri 29 Jan 2010

Personally, I find it sad to be consistent with conventions that were broken to start with and it makes Fantom looks older than it really is, but well...

Java programmers who have had to deal with Hashtable and hashcode() for the past ten years can probably relate.

andy Fri 29 Jan 2010

I prefer typeOf as well myself.

katox Sat 30 Jan 2010

@cbeust I think current API is pretty consious regarding naming conventions. Skimming through API only a few irregularities:

  1. qname, basename, hostname, username, filename but htmlName, displayName
  2. ro, rw but isRO, isRW
  3. printLine but newline
  4. dumpenv but dumpScope
  5. utf16BE but readUtf, toCss, makeHsv
  6. typeof but of, toArrayOf, toListOf, dateOfYear, localeStartOfWeek

I agree many these are strongly burned into brain synapses, like web-isms in 1 - I wouldn't probably touch these. I wouldn't change newline because it is used consistenly for a new line character (never for a new line as such).

I would however like to see the change from isRO and isRW to isRo and isRw in 2 as well as utf16BE to utf16Be in 5. In Java world camelcasing things like URL, HTTP, SQL and others is pretty hopeless - I never match a proper variant. It also complicates things like code generators which usually choke on such names like resolveHTTPTinyURL.

I strongly prefer typeOf and dumpEnv instead typeof and dumpenv - because there is a clear pattern elsewhere.

Brian's first argument why typeof is I the most important one. But even though typeof might look better at first but I think the longer you look at typeOf the less you prefer the irregular one. The second reason is also true for almost any toXyz and xyzOf - so why only here? It is also not really consistent with Java or C# because there the special notation is used only for operators - ORM and reflection APIs use camelcased naming convention typeOf resp. TypeOf.

helium Sat 30 Jan 2010

I like the .Net capitalization conventions regarding to acronyms (probably not unique to .Net).

  • Do capitalize both characters of two-character acronyms, except the first word of a camel-cased identifier.
  • Do capitalize only the first character of acronyms with three or more characters, except the first word of a camel-cased identifier.
  • Do not capitalize any of the characters of any acronyms, whatever their length, at the beginning of a camel-cased identifier.

And it seams Fantom follows these rules (isRO, utf16BE, ... but readUtf, toCss, ...).

But I agree that it should be typeOf.

brian Sat 30 Jan 2010

For things like io/IO, rw/RW, ro/RO we follow the rules .NET Framework Design Guidelines (great book if you don't have it).

Given how anal we've been with consistency, I believe Fantom has one of the best APIs with regard to uniformity. Everything we've done is codified in the Convention docs. If there are outstanding issues, then lets address them while we still can (but in another topic, not this one). We fixed a whole lot of issues in #855 .

But no matter how anal you are, it boils down whether you think of something as a single name or a compound name. For example most programmers would consider hostname one word, not host name. In the new Env API I avoided this altogether and just used host (but didn't think that would work in IpAddr.

So is it typeof or type of? You can make the case either way because as programmers we've come to think of this as one word (at least I have). So it boils down to taste. For something as often used as typeof I believe the captialized typeOf hurts readability:

obj.typeof.name
obj.typeOf.name

To me the capitalized O in a flow of chained lower case methods sticks out like a sore thumb.

This change is already done - and I picked typeof. That is what I believe it should be. But if there is huge opposition, I might consider changing it again.

mike Sat 30 Jan 2010

+1 typeof

andy Sat 30 Jan 2010

But no matter how anal you are, it boils down whether you think of something as a single name or a compound name.

I agree, and there is definitely a fine line between some the choices we've made, and thats understandable. But I think considering typeof as a single word is a stretch, if for no other reason, than of is not even a noun.

I guess I missed out on this vote, or wasn't paying attention. But this seems like a poor choice for a really core term, we should correct. And in regard to taste, I prefer typeOf aesthetically as well.

cbeust Sat 30 Jan 2010

Hi Brian,

First of all, let me be clear about one thing: I totally agree that Fantom has one of the most consistent and uniform APIs today. You have fully leveraged the fact that the language is very recent and you have made sure not to repeat mistakes made by other languages.

This discussion is just about ironing out a few wrinkles and make Fantom even awesomer than it already is.

I think the problem can be summarized by your following statement:

To me the capitalized O in a flow of chained lower case methods sticks out like a sore thumb.

Personal feelings and aesthetics have no room in API naming. None. Naming rules are clearly documented and they should be followed to the letter. No exceptions, ever. I think you agree that this method should be called typeOf but you choose to break the rule and make an exception for it, and that's what I disagree with.

As a side note: I haven't read the .Net book you just linked to but it seems to me that the Fantom conventions are closer to Java's than they are to .Net's since Windows conventions typically use uppercase letter for methods...

tactics Sat 30 Jan 2010

Now that I think of it, the only reason typeof feels natural lower case is probably because it's a keyword in some languages, and keywords are almost always all lower, regardless of how many words they squish in there.

tactics Wed 3 Feb 2010

If the polls are still open, I'm going to flip my vote. I keep finding myself trying to type foo.typeOf.

qualidafial Thu 4 Feb 2010

Me too. +1 for typeOf

kaushik Thu 4 Feb 2010

+1 for typeof :) .. mainly since is already there..

jodastephen Thu 4 Feb 2010

I support typeOf for two reasons.

  1. its correct according to the naming conventions of Fantom, thus least surprise as a method
  2. I believe Fantom is eventually going to have the # operator for this task (thus this will only be used as a method, and should therefore follow method naming conventions)

Login or Signup to reply.