5 ms·
I really want to understand what the fuss is about with Scala so I fired up a REPL and found a tutorial and went to work. Then I can across this: scala> pr
by agentultra 13y ago
I really want to understand what the fuss is about with Scala so I fired up a REPL and found a tutorial and went to work. Then I can across this:
scala> print("5" + 5)
55
And I stopped there (for now). At least my C++ compiler will warn about that (although it will still compile even if it doesn't print anything save for the newline):
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
cout << "5" + 5 << endl;
return 0;
}
Python gives me a TypeError. And so does Common Lisp. I was expecting the same from Scala; a language which purports to be a multi-paradigm language with static type inference and a strong functional programming bias. Not even a warning.
What's the reasoning behind this in Scala?
- jmount 13y agoI am hoping reasoning is in a non-print application the type of the captured value will be compile time checked elsewhere. But if the language is willing to cast both ways between int and string then there is no safety (no idea if it does do that). Also I do agree with your points (explicit and implied) I don't see "hey free parsing" as a big enough advantage to infect the language with these sort of implicit conversions.
- ape4 13y agoThis is handy for something like: scala> print("The result is " + iResult)
- jmgao 13y agoIt's inherited from Java, where adding something and a string will implicitly convert the something into a string. The C++ behavior is notably worse, though: "5" + 5 in C++ is undefined behavior, and will give you a pointer to some mystery data.
- agentultra 13y agoThe example is merely illustration and not the recommended practice for writing C++! (Can you imagine?) I only meant to illustrate that even in C++ where types have a different meaning I will get a warning with a decent compiler. In either case the expression in both languages garners a silly result. However Scala is happy with the result and reports nothing wrong with it (not even a warning). I was just surprised is all.
- Sharlin 13y agoHow is the result in Scala/Java silly? I'd say it's perfectly intuitive to most people that you can concatenate non-strings to strings using that syntax, via an implicit conversion of the non-string operand. You could do the same thing in C++ with operator overloading, and the unnecessary difficulty of building strings in C++ is probably one of the pet peeves of most people, and certainly something hard to explain to beginners (who will probably try "5" + 5 and be very very confused when the result is garbage instead of "55").
- agentultra 13y agoFirst off there's nothing intuitive about programming, PLs, or PLT. And certainly nothing perfect about anything related to computers at all. "5" + 5 Which is the sillier result: 10, "10", or "55"? All of them are equally valid based on what system of assumptions and implicit evaluation rules you decide are in effect when interpreting this expression. There are some languages that will output 10. Java/Scala will obviously choose the latter result. Neither of them are wrong. What I think is silly is that, to my knowledge, Scala won't warn you that the result of interpreting this expression is ambiguous and their chosen implementation might not be what you had expected. A decent C++ compiler will warn you (by default) that adding arrays of bytes to integers doesn't make sense and you are probably making a mistake somewhere. A lesser one will let you opt-in to receive warnings. A poor, silly compiler will just compile it without warning and let you figure out its strange result on your own.
- denis1 13y agoSince print() most likely expects a string, isn't the result exactly what you would expect? Why would you want a warning in this case?
- ionforce 13y agoBecause it crosses type boundaries. One would normally expect the plus method of Ints to only work on Ints, and similarly Strings for Strings.
- ckarmann 13y agoWell, why? I mean, I'm so used to work in Java which has the same behaviour, so I may have been totally unable to see the problem due to the familiarity of that code, maybe, but I still don't understand the problem. First, let state the basis: the meaning of the + operator is overloaded. For numeral types, it makes the sum of the operands. For string, it concatenates them. These are two different meanings in different context. For the numeral types, it will not protest if you sum up a float with an int (and I think most programming languages won't either). The rules of the language are quite clear: the int would be coerced to a float, then the two float be added, and a float will contain the result. For the string operation, you could force the operands to have all the same types, but you could also practice the same kind of coercion: convert everything (yes, it works for every object of any sort) to a string, then concatenate. OK, it may be odd mathematically, but let's see it for what it is: a very handy syntactic sugar in the form of an overloading of the meaning of +, which obey simple rules, and thus have no potential to mean something else than what the programmer meant.
- chilldream 13y agoThe thing is, it's not just an overload; it's an overload and a typecast. Those are two separate questions, and OP is really complaining about the typecast, not the overload. The ints vs. floats thing is kind of a red herring. In that specific case, at least you're still talking about numbers. The argument against having contagion for 5 + 5.5, and overloading for "5" + "5.5", but throwing an exception for "5" + 5.5 is that the first is a pair of numeric types, the second is a pair of strings, but the third is a pair of unrelated types. You can say white is lighter than black, and a feather is lighter than an anvil, but you can't say that white is lighter than an anvil because that's nonsense. Incidentally, this is why, say, Python and Ruby (and I imagine Lisp) people insist upon the distinction between dynamically typed and weakly typed. If I fire up a node.js repl, I find that '50' + 5 is '505', but '50' - 5 is 45, and am reminded why JavaScript drives me nuts. In the extreme you get things like [this](http://phpmanualmasterpieces.tumblr.com/post/33198366857/layers-of-mistaken-like-an-ogre http://phpmanualmasterpieces.tumblr.com/post/33198366857/lay...) and [this](https://www.destroyallsoftware.com/talks/wat https://www.destroyallsoftware.com/talks/wat). I realize that Java probably doesn't do anything near that bad, but the point is that it's a question of balancing convenience vs. error prevention, and that we're talking about a very strictly-typed language which will naturally attract people who tilt toward wanting the error detection, and even dynamic languages that swing the other way on most things often find that you don't need to make your math operators cast numbers into non-numeric types (and risk the resulting runtime errors) to have convenient string handling. In fact, I think Ruby's string interpolation is actually a better syntatic sugar than Java's `+` cat overload. Consider that I want to print a string along the lines of "1 + 5 = 6" but with arbitrary integers. Here's how it might look in Ruby: puts "#{x} + #{y} = #{x+y}" It's hard to imagine a syntax much better than this, especially for short strings, since the shape is basically identical to the string it's creating. Python 3 is less pretty, but still reasonable: print("{} + {} = {}".format(x, y, x+y)) print(x, "+", y, "=", x+y) Meanwhile, neither Ruby nor Python makes you declare types as a rule. In fact, one of the non-backward compatible changes in Python 3 was to make it so that 1/2 returns .5, since that's how numbers work and it's probably what you meant (there are still ways to specify integer division if you want). However, in either language, if you write "5" + 5, they will raise a ValueError because that doesn't actually mean anything, is likely to be a bug, and is always easily rewritten in a concise but less ambiguous way. Speaking of which: > have no potential to mean something else than what the programmer meant is just false. There is a very obvious way for it to mean something other than what the programmer wanted: When the programmer forgot to cast a string to a number and tried to add it to a number. This is particularly a risk in dynamic languages or those using type inference (it's harder to pull off in languages where you have to explicitly declare all your variable types, which may make it a non-issue in Java speficially).
- n1kh1lp 13y agoFYI, this works in Java too. System.out.println("5" + 5);
- modersky 13y agoScala inherits essentially all its expression syntax from Java, including the string +. This was done because a lot of other things in Scala are new, so we did not want to rock the boat too much with changes that might seem arbitrary. That said, I believe string + is probably the most criticized feature in Scala's expression syntax. People are generally moving away from it, towards String interpolation, which is available from Scala 2.10.
- noahmarc 13y agoThanks for joining the discussion. Just want to say I'm working through the the videos for your coursera course (https://www.coursera.org/course/progfun https://www.coursera.org/course/progfun) and, in addition to being a great introduction to Scala, it's changing how I approach other functional languages like JavaScript and R
- mercurial 13y agoAt most JavaScript is an imperative language with functional flavour
- klibertp 13y agoTry LiveScript: http://livescript.net/ http://livescript.net/ JS semantics are those of a functional-oop language. It lacks a few standard functions (LiveScript has prelude-ls) and a ton of syntactic support for things. Once these are in place, you can write the code which looks and feels like Ocaml. For example, moment.js function is `moment(dateString, formatString)`. In LiveScript I used it as: parseDate = (flip moment) "DD/MM/YYYY" Now tell me that this doesn't look like functional code :) (The only really lacking feature in JS is of course TCO, but then Clojure, so yeah, let's just trampoline everything.)
- agentultra 13y agoFair enough. Thanks for the answer. :)
- eklavya 13y ago
- p8 13y agoEven better: scala> println("5" + 5 + 5) 555
- adriaanm 13y agoscala> val pi = "pie!" pi: String = pie! scala> println(f"Care for some $pi%f?") <console>:9: error: type mismatch; found : String required: Double println(f"Care for some $pi%f?") ^ scala> val pi = Math.PI pi: Double = 3.141592653589793 scala> println(f"Care for some $pi%f?") Care for some 3.141593? ps: - http://docs.scala-lang.org/overviews/core/string-interpolation.html http://docs.scala-lang.org/overviews/core/string-interpolati... - read: https://github.com/adriaanm/talks/blob/master/scala-2.10/slides.md https://github.com/adriaanm/talks/blob/master/scala-2.10/sli... - watch: http://www.youtube.com/watch?v=tcQgNEFAVjI http://www.youtube.com/watch?v=tcQgNEFAVjI
- CookWithMe 13y agoscala> "5" + 5 res0: java.lang.String = 55 Don't use print in the REPL... > Python gives me a TypeError. And so does Common Lisp. I was expecting the same from Scala scala> val i:Int = "5" + 5 <console>:7: error: type mismatch; found : java.lang.String required: Int val i:Int = "5" + 5 ^ You can easily get a compiler error, if you enforce the type. The inheritance of Javas "I'll call .toString on anything" is definitely not something I'll defend, but it's much less of a problem than it may appear. To do anything interesting with that "fake" integer, you'll have to call a method that only accepts integers - and the compiler will throw an error then. E.g.: scala> math.max("5" + 5, 5) <console>:8: error: overloaded method value max with alternatives: (x: Double,y: Double)Double <and> (x: Float,y: Float)Float <and> (x: Long,y: Long)Long <and> (x: Int,y: Int)Int cannot be applied to (java.lang.String, Int) math.max("5" + 5, 5) ^
- codygman 13y agoIsn't this something that type inference should catch though?
- lmm 13y agoThe type of "5" + 5 is inferred to be String. If you pass it to print(), which takes a String, that's not an error, and printing "55" is presumably what you meant to happen. If you tried to pass it to a method expecting an integer, you'd get an error.
- lmm 13y agoJava compatibility. Slightly unfortunate, but less of a problem than it would be in python or lisp thanks to static typing - if you tried to pass "5" + 5 to a method that expected an int you'd get an error.
- memracom 13y agoThe problem is that you don't understand Scala operators. There are none. That + sign there is simply the name of a method in the class of the object preceding it. So you invoked print("5".+(5)) What else would you expect. The nice thing about Scala is that you can leave out some of the extra syntax that is not needed for the compiler to decode the meaning. Now as for why the String class has a + method to do string concatenation? I don't know but this is far from the first language that I have come across that conflates string concatentation with numeric addition. Maybe it comes from the Java libraries? In any case, it is not really a problem to most people because we follow the maxim, if it hurts, DON'T DO THAT!
- chilldream 13y agoscala> 5 + "5" res0: String = 55