Live data from Hacker News

In Java 3 = 12

virtualspecies.com

31–40 of 55 posts

Re: In Java 3 = 12

#31
post #17

I suppose that's something every Java programmer should know: How types are automatically converted during "arithmetic" operations. There are some subtleties (like byte+short => int), but it's not too much to remember. The deeper question is: Was it a wise choice to disallow operator overloading BUT use "+" as a string concatination operator AND convert all values to strings during string concatenation? I think not,…

Thats why I'm glad D chose '~' as a binary concatenation operator so that there is never any confusion.

There is something to be said about using all the special characters of the ASCII table in term of readability.

Looking forward languages that will start making good use of Unicode! I am actually surprised Greek letters haven’t made it already. Lots of computer scientists are mathematicians that are used to math papers looking like an Ancient Greek tablet.

Re: In Java 3 = 12

#32
post #27

Earlier quoted context omitted.

dynamic vs. static typing is independent of strong vs. weak typing. strong typing is basically allowing fewer implicit converstations, weak more. static means type checking happens before runtime, dynamic means the opposite.

Thanks for that explanation. So Java is weakly typed? Or would you say less strongly typed? Is the strength determined by the amount of implicit type coercions that are available? Does static vs dynamic also imply that the strong-ness is checked at compile vs runtime? In other words, in python this bug can lurk undetected in your code list = (1, 2, 3) ‎x = list + 1 while in Java it will throw the error at compile tim…

> In other words, in python this bug can lurk undetected in your code

Well, if you use Python 3 and a modern editor, you will get a big red warning. mypy has been able to check types for a while and a lot of editors embed it.

Re: In Java 3 = 12

#33
post #8

Earlier quoted context omitted.

Yes but that's strange. Java is such a staticaly typed language you would not expect it to do that if you are like me and don't know it very well. While Python is very dynamic, but: >>> print(1 + 2 + "=" + 1 + 2) Traceback (most recent call last): File " ", line 1, in TypeError: unsupported operand type(s) for +: 'int' and 'str'

This is possible exactly because Java is statically-typed. Java's type system works over the operands, and does implicit conversions before the expression gets a chance to run. It sees values and does implicit magic from left to right. Python, on the other hand, does not need to do a typing pass at parse-time. Instead, literals are stored as values, and those values are tagged with their source class. Python's way of…

> This is possible exactly because Java is statically-typed.

Are you saying that Python can't make "a"+1 become "a1" because it lacks static typing? That's not true. If they wanted to, they could have added an overload for the string+integer case.

> Java might be able to yield the same kind of result as Python if it had operator overloading.

Not necessary. They would have just had to omit the built-in overload for string+integer (and perhaps also for string+object, given the newish auto-boxing feature).

Re: In Java 3 = 12

#34
This isn't at all surprising if you know how Java works; you could probably point out this kind of a strange feature case in nearly any language if you look hard enough.

It does left to right order of operands, so 1 + 2 happens as integer addition since both operands are integers, then + "=" does string concatenation since one of the operands is a String, then "3=" + 1 evaluates as a concatenation since one of the operands is a String, giving "3=1" + 2, which evaluates to "3=12" by the same logic. Parenthesis solves this by explicitly specifying order of operations.

And explicitly specifying order of operations is almost always a good idea for making sure it does what you want and maintenance purposes.

Re: In Java 3 = 12

#36
I really don't think this should be confusing - having a decent grasp on associativity and precedence is a pretty useful skill - so for example understanding WHY println(3 * 2 + "-" + 6 * 3) behaves "differently" is something I'd hope people would get.

And let's be honest, you definitely don't want to 'fix' this by tweaking precedence to include types. That way madness lies. ;)

Definite shout to ubernostrum's commment though - perhaps the confusing thing is that string concatenation is +, but a world of explicit Appends seems horrid, and that ship has very much sailed.

Just be (maybe) glad java doesn't allow generalised operator overloading ;)

Re: In Java 3 = 12

#37
post #17

I suppose that's something every Java programmer should know: How types are automatically converted during "arithmetic" operations. There are some subtleties (like byte+short => int), but it's not too much to remember. The deeper question is: Was it a wise choice to disallow operator overloading BUT use "+" as a string concatination operator AND convert all values to strings during string concatenation? I think not,…

Eh, it's just a design decision. They could have required that people construct strings using printf-style formatting (which you can do, with String.format(), but isn't required), or have some sort of interpolation (like Scala does with s"This var is $foo"), but they just opted to let people concat with + instead. You could argue it any way, I suppose; there's no one right answer.

The behavior in the OP's example is unsurprising for a language that defines + to be left-associative and has a well-defined order of operations.

Re: In Java 3 = 12

#38
This is standard behaviour I would expect in most languages that have implicit type conversions. The article seems to be willfully disregarding that. I can think of no language that would not produce either that string, a fault, or (on the outside) NaN. Java is doing a completely sensible thing here.

That majority of operators are left associative, and that associativity is not dependent on the types involved.

Very high level let's say the grammar is:

    Expr :- Expr + Primitive
         |  Primitive
    
    Primitive :- Integer
              |  String

And then determining the type is always:

    type(Integer) = int
    type(String) = string
    type(Expr) = type(Primitive) or minimum_type(left, right)
With the simple rule (in this case)

    minimum_type(left, right)
        if (left == right) return left;
        return string
In java the type conversions are done as pass during compile time, doing something like this

    for (node in AST)
        if (type(node) != required type)
            replace node with type_conversion_node(node, required_type)
But none of this is java specific -- all statically typed languages (with implicit conversion) would do this. Dynamically typed languages in general cannot do this (in practice you can do a degree of it with local inference, etc), but that just changes when the type check is done.

[Edit, because the same confusion about static/dynamic/strong/weak typing is being made in multiple places.

Strong typing: The language does not allow you to perform an operation on a type if that operation were invalid when applied to that type. In java (to make it explicit) I could do (int[])someUnrelatedObject - that cannot be statically verified but it will fault at run time, because it is strongly typed. The equivalent in C will happily go off into the weeds and destroy everything.

Weak typing: A language does not guarantee that invalid operations will be prevented. For example C and C++ do have types, and they will disallow invalid uses, but there is no guard to prevent you from casting to an unrelated type. A more extreme example is some older languages that don't even disallow argument mismatches, etc.

Static typing: the types in the code are static, specifically they do not change run-to-run. The types of fields, variables, etc in the source could be inferred, or explicit by the programmer, but they are all known before the code is ever run. So C, C++, Java, etc are statically typed. Mostly. Because of Java's boneheaded array sub typing behaviour Object array[]; array[0] = someObejct; can fail at runtime due to a dynamic type check.

Dynamic typing: some or all expression types are not known until the code is run, everyone knows python, js, etc

(getting tired running out of steam)

So anyway, you can have:

Strong/Dynamic: Python, JavaScript, ... Strong/Static: Haskell, etc Weak/Dynamic: Can't think of a good example here because tired :D Weak/Static: C

And obviously there's a tonne of in-between

C++: all of C, plus statically type safe casts, and dynamically type safe casts Objective-C: all of C, but the ObjC object system which lets you send arbitrary messages to arbitrary targets. But you don't have to have the correct parameter types... ...

And this all ignores what caused this article in the first place: implicit type conversions. These do not effect the Strong/Weak description of the language if they are well defined, eg. people often complain about string promotion, but neglect to comment on someInt + someFloat promoting the int to a float, even though such a promotion can lose data. The distinction is purely a matter of "does the language allow you to perform an operation on a value of a type that is not compatible with that operation". One way to achieve that is the say it's completely illegal: throw an exception at runtime, fail to compile, etc another alternative is to implicit convert the type to something that is valid. Note that /converting/ a value changes the value being used. Compare that to the not type safe version where you literally ignore the type of the value being used. In the case of int + float it's the difference between converting the int to a float value, and just treating the bits of the integer as if they were the bits in a float.

Many apologies about the awful writing, but it's late :D

Re: In Java 3 = 12

#39
post #31

Earlier quoted context omitted.

Thats why I'm glad D chose '~' as a binary concatenation operator so that there is never any confusion.

There is something to be said about using all the special characters of the ASCII table in term of readability. Looking forward languages that will start making good use of Unicode! I am actually surprised Greek letters haven’t made it already. Lots of computer scientists are mathematicians that are used to math papers looking like an Ancient Greek tablet.

The Fortress programming language was a research project at Sun that incorporated mathematical notation.

See page 24 of http://www.oracle.com/technetwork/systems/ts-5206-159453.pdf

They also had an ASCII-only representation for everything, so you could use a regular text editor if you wanted, kind of like Markdown.

Re: In Java 3 = 12

#40
post #8

Earlier quoted context omitted.

Yes but that's strange. Java is such a staticaly typed language you would not expect it to do that if you are like me and don't know it very well. While Python is very dynamic, but: >>> print(1 + 2 + "=" + 1 + 2) Traceback (most recent call last): File " ", line 1, in TypeError: unsupported operand type(s) for +: 'int' and 'str'

This is possible exactly because Java is statically-typed. Java's type system works over the operands, and does implicit conversions before the expression gets a chance to run. It sees values and does implicit magic from left to right. Python, on the other hand, does not need to do a typing pass at parse-time. Instead, literals are stored as values, and those values are tagged with their source class. Python's way of…

This has literally nothing to do with static typing. It is 100% due to implicit promotion (demotion?) of addition operands to string if either operand is a string.

All static typing does is mean that the type check, and so decision to insert the conversion call is done at compile time. Dynamic typing just means that the type check and decision to insert the conversion is done at the point the + is evaluated.

Post reply on HN