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

Rename abstract numeric types like FloatingPoint and Complex? #8142

Closed
jiahao opened this issue Aug 26, 2014 · 89 comments
Closed

Rename abstract numeric types like FloatingPoint and Complex? #8142

jiahao opened this issue Aug 26, 2014 · 89 comments
Labels
breaking This change will break code needs decision A decision on this change is needed

Comments

@jiahao
Copy link
Member

jiahao commented Aug 26, 2014

We've seen empirical evidence that new users sometimes use abstract numeric types like FloatingPoint or Complex in lieu of concrete types like Float64 and Complex128. The result is that users end up with slow code or even wrong code due to operations over variables with types like Array{Complex,2} or Vector{FloatingPoint}. (For example: this comment in #4796)

The unintentional use of abstract numeric types seems especially prevalent with FloatingPoint or Complex which share common prefixes with concrete types. Other abstract numeric types like Signed or Real do not seem prone to accidental misuse to the same extent.

Suggestions for new names? I'd propose something like FloatingPointAbstract or AbstractFloatingPoint to emphasize the abstract nature of the type. And perhaps something like ComplexCartesian instead of Complex to emphasize the canonical (real, imaginary) representation and to distinguish it from polar forms or other more esoteric representations.

@StefanKarpinski
Copy link
Member

My votes:

  • FloatingPointAbstractFloat
  • leave Integer alone
  • leave Complex alone
  • introduce AbstractComplex as a supertype of Complex
  • introduce PolarComplex as a polar representation of complex values

@tknopp
Copy link
Contributor

tknopp commented Aug 26, 2014

Hard to get this consistent at this point. A radical change would be to use the Abstract prefix for all abstract types. Or use an I prefex like in C# (i.e. IArray, IComplex, IFloat).

@tknopp
Copy link
Contributor

tknopp commented Aug 26, 2014

@nalimilan
Copy link
Member

@StefanKarpinski +1, but why not AbstractInt, for similarity with AbstractFloat? Integer is easily confused with Int.

@StefanKarpinski
Copy link
Member

I hear you on the consistency issue. But something is off about AbtsractInt. Int is a specific implementation so AbstractInt is like writing AbstractInt64 or AbstractFloat64 – it's an oxymoron. In that case, it would have to be something more like AbstractInteger at which point, which may be ok, but why not just Integer then since there's no such concrete type.

@tknopp
Copy link
Contributor

tknopp commented Aug 26, 2014

The more I think about it, the more I like the idea of introducing a common prefix for all abstract types. This makes it entirely obvious that one is dealing with an abstract type. The argument that a name is "free" like in the Integer case is not very strong in my opinion. It is a rather local name optimization for which one gives up clarity.

Since Abstract is a really long prefix I would formally propose the I convention (where I stands for Interface). In Gtk.jl prior to version 0.5 (I think) the I was used as a suffix by the way.

@johnmyleswhite
Copy link
Member

I'm not a fan of the I prefix. It's pretty obscure.

Can I suggest a very different perspective here? I think the confusion we see on the mailing list is only correlated with names and tab-completion: the real cause is that many people coming to Julia have never worked with any type system before. So FloatingPoint confuses them because the idea of abstract types confuses them. And Complex confuses them because parametric types confuse them. We can maybe fix these specific issues with name changes, but there's a broader cultural problem: the manual doesn't provide any way for newcomers to learn what a type system is.

@quinnj
Copy link
Member

quinnj commented Aug 26, 2014

-1 to I prefix as well.

I think it may also be prudent to consider other upcoming changes: #1470 will allow the use of Abstract types differently, #6975 talks about official Interfaces which will overlap, and #6984 is the covariance change. I think any name changes needed to be looked at in the broader scope of the future of the type system.

I'm also really looking forward to a lot of these changes; can't wait to throw them all together and get my "Julia-legs" again with the new system.

@JeffBezanson
Copy link
Member

I kind of agree that it's not very satisfying to keep second-guessing which names will have an intended psychological effect. We thought FloatingPoint would be long and awkward enough that people would shy away from it. Maybe it's not a good name. But we should just pick good names and go with them.

The issue with Complex can't be solved by renaming. Types with parameters become abstract-ish when the parameters are left off, and this is a pretty subtle point to be sure. The same problem exists with Array, Vector, etc. For example creating an array of vectors with Vector[[1,2],[3,4]]. At one time I probably wanted to disallow using "incomplete" types as parameters (e.g. Array{Complex}). However in julia it turns out to be very difficult to disallow things. But it would be nice to do something about this.

@nalimilan
Copy link
Member

The issue with Complex is... complex. ;-) But for Integer and FloatingPoint I think it's pretty simple: people get rightly confused because there's nothing in their names indicating they are abstract versions of Int(32|64)? and Float(32|64); the latter are abbreviations of the former, and it's not a big hint that they are abstract for newcomers.

@StefanKarpinski I'd be fine with AbstractInteger too.

@tknopp
Copy link
Contributor

tknopp commented Aug 26, 2014

@quinnj: Absolutely, these things all need to be seen in a common scope. Still, explaining the difference between Int, Integer, Array, AbstractArray, FloatingPoint is quite difficult isn't it?

Let me ask the other way around: Would there be a drawback if we would introduce a convention how to name abstract types? On a related note, the bang-convention is IMHO great too.

@tknopp
Copy link
Contributor

tknopp commented Aug 26, 2014

And it does not has to be the I prefix if everbody find this ugly. Abstract is also fine. The C# programmer in me makes the I prefix pretty natural.

@JeffBezanson
Copy link
Member

I'm not opposed to a naming convention, especially if it's fairly lightweight (e.g. an A prefix) and we use it pretty consistently. Any might make a good prefix; Any is already the ultimate abstract type. AnyFloat, AnyInteger, etc. seem to convey the right idea.

@tknopp
Copy link
Contributor

tknopp commented Aug 26, 2014

Jep, the "lightweight" property is what made me like I more than Abstract. But A and Any are also just fine. Would be awesome if we could agree on something like this. It will presumely break any package out there but its IMHO worth it.

@StefanKarpinski
Copy link
Member

We could keep aliases around for a while to smooth the transition. Is Abstract too long as a prefix?

@johnmyleswhite
Copy link
Member

If we adopt prefixes, can we at least go with one that has some mnemonic property like Abs or Abstract rather than A?

@eschnett
Copy link
Contributor

Yes, Abstract is too long; Any is much better.

-erik

On Tue, Aug 26, 2014 at 11:38 AM, Stefan Karpinski <[email protected]

wrote:

We could keep aliases around for a while to smooth the transition. Is
Abstract too long as a prefix?

Reply to this email directly or view it on GitHub
#8142 (comment).

Erik Schnetter [email protected]
http://www.perimeterinstitute.ca/personal/eschnetter/

@quinnj
Copy link
Member

quinnj commented Aug 26, 2014

+1 to Any

@johnmyleswhite
Copy link
Member

Carrying this to a systematic extreme: is AbstractArray going to become AnyArray? Is String going to become AnyString?

@StefanKarpinski
Copy link
Member

AnyArray is pretty confusing since it's not the same as Array{Any}. I do not care for the Any prefix.

@nalimilan
Copy link
Member

+1 for a short prefix. A sounds fine to me once you understood it stands for Abstract. Any on the other hand could be confusing.

@johnmyleswhite
Copy link
Member

Am I the only one who things the A prefix is not just non-mnemonic, but anti-semantic?

"What type is x? Oh, it's AFloat"

@tknopp
Copy link
Contributor

tknopp commented Aug 26, 2014

@johnmyleswhite: (refering to String): Yes and this is a good thing. Lets say if we would go with Abstract it would be AbstractString. I have used String in many situations and very lately recognized that it is an abstract type and that I have to use ASCIIString instead

@quinnj
Copy link
Member

quinnj commented Aug 26, 2014

I believe at one point, it was mentioned that we would actually have an
AbstractString with String becoming an alias for UTF8String.
On Aug 26, 2014 11:54 AM, "Tobias Knopp" [email protected] wrote:

@johnmyleswhite https://github.com/johnmyleswhite: Yes and this is a
good thing. Lets say if we would go with Abstract it would be
AbstractString. I have used String in many situations and very lately
recognized that it is an abstract type and that I have to use ASCIIString
instead


Reply to this email directly or view it on GitHub
#8142 (comment).

@StefanKarpinski
Copy link
Member

Am I the only one who things the A prefix is not just non-mnemonic, but anti-semantic?

Nope. Me too. AFloat is horrible.

@staticfloat
Copy link
Member

I don't see what the problem with such a long prefix on AbstractInteger is. Are any of us really going to write that much code that contains the type AbstractInteger written out? Isn't the whole point of this discussion to discourage people to use AbstractInteger in their code?

@StefanKarpinski
Copy link
Member

I agree. I think the only reasonable prefix so far is Abstract.

@ivarne
Copy link
Member

ivarne commented Aug 26, 2014

Integer is used 870 times in Base, so the change to AbstractInteger will add 6090 characters to base.

+1 for almost any convention for making it easier to understand the meaning of some piece of code. A full Abstract* seems like too much, but none of the alternatives seems better. Int vs Integer is not as pretty as it used to be, after I've seen real people struggling because they don't understand the difference.

@JeffBezanson
Copy link
Member

The problem with Float is that 100% of people will think it is C's float type.

@StefanKarpinski
Copy link
Member

I think that's an overestimate, but only by about 50%.

@ViralBShah
Copy link
Member

I think 100% of the users who have used C before will think it is the same.

@jiahao
Copy link
Member Author

jiahao commented Oct 18, 2014

Well, that's exactly the situation with Fortran users and Complex.

@JeffBezanson
Copy link
Member

That's true, but the issue with renaming Complex appears to be fundamental to our type system. So far the only solution I see is to allow types to be "reinstantiated", e.g. so that Complex{Float64}{Float32} yields Complex{Float32}. That seems quite marginal.

Also float has been used for the single precision type in many languages; it is certainly more widespread than complex.

@nalimilan
Copy link
Member

The real issue IMHO is that new Julia users willl think Float is the equivalent of Int, which will1) increase the confusion WRT Float64 being the native type even on 32-bit, and 2) make people add ::Float type annotations believing they will improve performance.

@staticfloat
Copy link
Member

I think at some point we are going to run into a situation where consistency/sanity will be directly opposed to background experiences of programmers from other languages. I think that if the cost is worth the benefit, and if this is possible at all, we should put less emphasis on previous coding backgrounds once we have good lint/analysis tools. If I could, in IJulia, press a "lint this" button, have it highlight an a = Array(Float, 100, 100) line and say "Using an Array of Float objects is almost never what you want, see the numeric types section of the manual", I think we would be able to do pretty much whatever we want. People will think "okay, coming from C, that's weird" but once they care enough about their performance to hit the lint/analysis button (Assuming such a thing is possible) they'll get it. Just like they've gotten that whitespace is semantic in Python, or that curly braces denote scope in the C family, or that functions in MATLAB can be called without parens or commas between arguments, and this causes arguments to be escaped in quotes.

@JeffBezanson
Copy link
Member

Yes, it is all about cost vs. benefit. However some words simply have established meanings. In computing it's often not clear which those are, which makes things difficult. But if a meaning is firmly-enough established, I believe there is nothing to gain by using it differently. Float is one of those cases.

I agree we should not be overly slavish to backwards compatibility. We need to distinguish between terms that are firmly established, and those that are simply backwards-compatible with one system or another.

@staticfloat
Copy link
Member

I just realized I wrote "if the cost is worth the benefit". I'm such a Realist. ;D

@Sisyphuss
Copy link

Since in Julia, only leaf nodes are concrete types, presenting the type tree to users will largely solve the problem. (well, I just wanted to say that I want this type tree, but cannot find it.)

@lostanlen
Copy link

@Sisyphuss here you go:

include(JULIA_HOME[1:rsearch(JULIA_HOME, joinpath("usr", "bin")).start - 1] * "examples")
TypeTrees.print_tree(TypeTrees.types_tree)

@Sisyphuss
Copy link

@lostanlen Thanks for your humor! I think that users would prefer a concise, portable and visible typetree that could be used as a reference card.

@nstiurca
Copy link
Contributor

I came late to the party, so several comments and thoughts:

I would like to have Real <: AbstractComplex despite @JeffBezanson's protests. After all, any function that wants a complex should work given a real input, just as a function that wants a Real is perfectly happy with an Int even though as Jeff would put it "Ints are not Reals, they are just embedded in them". Why should we separate complex values from the rest of the Number type hierarchy?

Regarding the abstract-ness of Complex (and Array, etc) and how many Julia users don't realize the type is abstract, how about requiring a trailing pair of braces to be explicit about the fact that the type is parametric? For example, instead of being able to simply type Complex, require Complex{}, or maybe even Complex{?} to be even more explicit that the parameter(s) is/are unknown. This would be a pretty far reaching change throughout the language, and maybe deserving of its own issue. I haven't even slept on it yet, so it's a very premature thought on how to solve this problem.

I think the Abstract prefix is fine despite the verbosity and I think it was a good change in v0.4. (If anyone is really offended by the extra keystrokes, they are free to typealias to something shorter in their own codebase.)

For what it's worth, I find Integer and Int as defined to be both useful and sometimes confusing. :-S

@nstiurca
Copy link
Contributor

Also, +1 for having AbstractComplex and PolarComplex.

@toivoh
Copy link
Contributor

toivoh commented Nov 14, 2015

Sure, a function that takes a complex value can always take a real value instead, but what if you have a function that accepts an Array{T} where T <: AbstractComplex and writes to it?

I think it does make sense to be able to talk about the set of types that do not only represent complex numbers, but are able to represent more or less any complex number (up to precision).

@nstiurca
Copy link
Contributor

Then you get InexactError, which is business as usual. We already have something like this within the Real type tree.

bar!{T<:Real}(a::Array{T}) = copy!(a, rand(Float64, size(a)...))  # copy some non-integers into a
fArr = Array(Float32, 3,4);  bar!(tArr)       # OK: double -> float conversion
rArr = Array(Rational, 3,4); bar!(rArr)       # OK: rational approximation
iArr = Array(Int, 3,4);      bar!(iArr)       # ERROR: InexactError()

@Ismael-VC
Copy link
Contributor

@Sisyphuss here is a GraphViz based plot of v0.3.10 by @jbn, here is the code he used, it would be nice if we could automatically provide similar plots updated and linked in the documentation.

@Sisyphuss
Copy link

@Ismael-VC it seems to me that he used Julia to write a Graph data object (a sort of metaprogramming). IMHO, his code can be directly used in a v0.4 kernel and produce a correspondent v0.4 type graph.

@Ismael-VC
Copy link
Contributor

@Sisyphuss it's done with Graphviz, but I don't know much dot foo, this: julia_0.4.1_type_hierarchy.pdf graph looks too crowded, I'll try to make it better. Acrobat reader doesn't render this file for me (too big I guess?), but Chrome does! If this can be prettyfied, I'd like to add them to the documentation somewhere.

@Sisyphuss
Copy link

@Ismael-VC it can be opened by other application such as evince. To make it pretty, maybe it will help to divide the tree to subtrees at the first level.

@iagobaapellaniz
Copy link
Contributor

I vote +1 for A prefix. It stands for Abstract as well as for "a" the indefinite article. They could be easy to read as "a complex" or as "a real". And A is short enough to implement.

This lead me to think on "an integer". Should it be AnInteger the abstract type for integers? I don't know what to think about this. It could be good for new people to find abstract types like...

AComplex
AFloat
AnArray
AMatrix
AnInteger

Don't know... You can skip this idea ;-p

Definitely to stress the fact they are abstract is a huge improvement

@quinnj
Copy link
Member

quinnj commented Apr 28, 2016

Should we close this? We made the change to AbstractFloat and I think the consensus was everything else could stay the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking This change will break code needs decision A decision on this change is needed
Projects
None yet
Development

No branches or pull requests