4 ms·
> Because it's unsafe some portion of the time?
Yes, in the rare case of using string buffering across threads simultaneously. This "some" is so small as to ha
> Because it's unsafe some portion of the time?
Yes, in the rare case of using string buffering across threads simultaneously. This "some" is so small as to have no practical benefits to default to the safe way. I don't know of any code that does it or would use it (and if that code did exist, you would opt in to the safety guarantees by using a different class for that rare purpose).
> Are we not talking about some small percentage of performance loss in string concatenation in exchange for a program that doesn't crash in the case it's used in a particular manner with threads? Am I misunderstanding this?
A bit. New code makes a conscious choice to be thread safe or not. I would not recommend anyone edit old code to improve performance. But for new code, thread safe string buffers are like thread safe anything else in the language, they are opt in because the default is assumed to not be thread safe unless you really mean it. All programming languages I know that support cross-thread racy invocations have a thread-unsafe-by-default approach to their stdlib. This is a reasonable approach/default for practical reasons.
> I will side with the safer way as a default
This is specifically why I used the word "practicality". In your mind I assume that there never should be such things as dynamic languages? If safety trumps all other forms of practical choice, your programming environment and library choice will be really limited. We can all theoretically tout we choose safety over everything else, but we all know we have to make practicality sacrifices for many reasons that are unrelated to safety.
> In your mind I assume that there never should be such things as dynamic languages?
In what way are dynamic languages "unsafe"? To be clear, what I mean here by unsafe, and everywhere I've used the word, is "can cause a crash or memory corruption", which I consider different than "not the output I expected", such as weird order of operations.
Can using one over the other cause a Java program to crash in certain circumstances? Then I advise the one with the possibility to crash not be the default, if at all possible. Is it extremely rare that it could cause a crash? Are we sure that will always remain the case? Could interesting developments later on the JVM make it markedly less rare (maybe some auto-threading loop constructs)? Perhaps we shouldn't use current common current behavior as a justification for what will be safe in the future?
Is it not a case of actual crashing or corruption, and just a non-intuitive ordering of operations than someone might expect? Well then we aren't really talking about the same thing at all, and I don't really care as much what the default should be, as a matter of industry best practices.
Because dynamic languages by definition don't stop you from doing silly things like:
Math.floor("banana")
They might attempt to provide a sensible answer, such as NaN if I run the above in JavaScript. But that operation doesn't really have a sensible semantic definition and the choice to return NaN instead of crashing is somewhat arbitrary.
I don't know, treating anything that is not a number as NaN (and mathematical operations on it as producing NaN) seems to be exactly semantically correct.
I mean, really, all NaN is in any language is a signal that a mathematical operation was used with a set of inputs for which the operation does not produce a defined numerical result. In a sense, this is always a sign of an insufficiently expressive type system that can't prevent you from feeding a bad value (or bad combination of values) to the operation.
I said it was a sensible response to a non-sensible operation. The operation of flooring "banana" is not semantically-correct. The fact that IEEE floating point numbers happens to have a value that provides a sensible result to this operation is a bit of a fluke. What if the return value was an integer type, which is perfectly valid considering that the floor operation always provides an integer result?
What is sensible is first based on the language definition, not your opinion. If the language defines it explicitly and has well defined rules, there's nothing non-sensible about it. Consider the following, which fall well within the definition of how Perl handles implicit conversion of strings to numeric types, and is well known to Perl programmers:
# perl -E 'say "1zero"+0 '
1
# perl -E 'say "zero1"+0 '
0
No, I'm pretty sure that the question "what's the mathematical floor of banana" doesn't make any sense, no matter what the language definition is. The fact that some (dynamic) languages even allow you to ask the question is the entire point being made by kodablah in regards to typing as a safety mechanism. The fact that some smaller subset of languages even attempt (and fail) to make sense of the operation (weak typing) is just diving straight off the deep-end of safety.
That expressly ignores what I set up as my criteria, so I'm unsure why you presented this.
Even if that does cause a crash, which is entirely dependent on the language, I think there's a clear delineation of whether something can be expected to crash or not based on the opt-in assumptions of the language you choose. If your language is not type-safe, you've already accepted that as a constraint ("types may not help you"). Should we expect addition to be implemented in some way that causes problems within the constraints you've already accepted? I think not.
Here's two specific examples of dynamic languages, one weakly typed (Perl), one strongly typed (Python), and how they are internally consistent.
# perl -E 'say 1 + "2" + "four" + 8'
11
# python -c 'say 1 + "2" + "four" + 8'
File "<string>", line 1
say 1 + "2" + "four" + 8
^
SyntaxError: invalid syntax
Each makes it clear what you can expect up-front. If python could occasionally crash from addition of two integers, or Perl would occasionally interpret an all alpha string as non-empty in numeric context, all for the name of being slightly faster, I would consider that the wrong thing to do as well. (Note: There are rules for how mixed alphanumeric strings are interpreted in Perl, but they are well defined).
> I think there's a clear delineation of whether something can be expected to crash or not based on the opt-in assumptions of the language you choose.
I can say exactly the same thing about StringBuffer vs StringBuilder, with the obvious substitution for the word "language".
The point of kodablah's post is that, if your stance is that safety should always be chosen over other practical concerns, then a natural conclusion is that you should by default be opposed to dynamic languages, as they trade type safety for programmer comfort (for lack of a better term).
EDIT: I also want to point out that "crashing" vs throwing an error is not a distinction worth making for this conversation. If your program stops executing for any reason that could be prevented by a type-checking system, then it seems reasonable to call a type-checking system a safety feature.
> I can say exactly the same thing about StringBuffer vs StringBuilder, with the obvious substitution for the word "language".
Sure. And if you think the the difference in developer efficiency between a dynamic language and a static one is less than 10%, but when the gains are small, as has been shown in the linked article, then why pay the cost of possible program failure for a less than 10% gain in string concatenation speed when you probably won't event see it?
> I also want to point out that "crashing" vs throwing an error is not a distinction worth making for this conversation. If your program stops executing for any reason that could be prevented by a type-checking system, then it seems reasonable to call a type-checking system a safety feature.
I disagree. Exceptions which can be caught are not comparable to memory corruption, unless you can ensure the corruption can not cause a segmentation fault (which may be the case here, I have no idea).
Nobody seems to be answering my question as to what type of problem the threading error is limited to in Java. I've made clear that any objection I have to the default is moot based on possible assurances that the JVM might provide, but I haven't had anyone clarify.
> Sure. And if you think the the difference in developer efficiency between a dynamic language and a static one is less than 10%, but when the gains are small, as has been shown in the linked article, then why pay the cost of possible program failure for a less than 10% gain in string concatenation speed when you probably won't event see it?
I actually think that dynamic languages have negative efficiency impact over long periods of time and large numbers of developers. (If that doesn't make it clear where I stand on static vs dynamic typing...)
> Exceptions which can be caught are not comparable to memory corruption...
I never compared exceptions to memory corruption, I compared them to crashes. I could also "catch" crashes with techniques such as watch-dog processes with very similar effects. Now if you really mean "crashes" as "program faults due to memory corruption", as opposed to "unexpectedly halting execution", then you're both using a niche definition and gave a bit of deceiving definition of "unsafe":
> To be clear, what I mean here by unsafe, and everywhere I've used the word, is "can cause a crash or memory corruption"...
> I actually think that dynamic languages have negative efficiency impact over long periods of time and large numbers of developers.
I agree, but that does leave open the possibility of them being more efficient in some circumstances.
> I could also "catch" crashes with techniques such as watch-dog processes with very similar effects.
Without a system for handling the crash information in such a way that you can feed it back into the restarted program to retrieve prior that and recover from it, I don't really see how they are equivalent.
> Now if you really mean "crashes" as "program faults due to memory corruption", as opposed to "unexpectedly halting execution", then you're both using a niche definition and gave a bit of deceiving definition of "unsafe"
I mean either, for the entire program, not some executing branch. I think "crash" is fairly unambiguously accepted as "an unrecoverable problem within the current running context causing it to halt." An exception is not a crash, it's a problem, which if unhandled can lead to a crash. Perhaps I'm in the minority in my opinion on this, but I don't think so.
OK, now this is turning into a real tangent on exceptions vs crashes. I see little difference between an exception with no actionable programmatic resolution and a program crash. You can always retry, but the bottom line is that there's never going to be a good answer to flooring a banana. You can try to floor something else, or you can try to do an operation that's not flooring, but that particular combination isn't going to ever have a good solution.
> I mean either, for the entire program, not some executing branch.
That's a pretty arbitrary line to draw. The difference between one thread acting as a watch-dog for another thread, or the same situation with processes could probably be made indistinguishable with the proper setup.