3 ms·
Not to mention Python, Java, etc... still have pointers and memory leaks (at least in Java, everything is pass by value, but with the exception of the primitive
by strlen 16y ago
Not to mention Python, Java, etc... still have pointers and memory leaks (at least in Java, everything is pass by value, but with the exception of the primitives, every value is a pointer). They will also suffer memory pressure when you allocate objects without thinking (which is rather easy to do if you never had to think about what the runtime does when you say "obj = Foo(bar)").
I'm not a C/C++ bigot, my "favourite language" is currently a three-way tie between Scala, OCaml and Lisp. Plenty of real programming gets done in other languages (plenty of people also think that C is the secret sauce for performance, but that's not the case), but C is important for two reasons: it's the lingua franca of programming and it's a great language for learning how computers work. Pascal may have been another option twenty years ago, but there are hardly any interesting open source projects being done in it today.
- jrockway 16y agoJava is pass-by-reference. Pass in object foo, call smash_with_hammer on foo in the called function, and the caller finds that his foo was smashed by a hammer when control returns to him. You might not have noticed this because, as a Scala, Lisp and OCaml programmer, you don't let your objects smash themselves with hammers :) (Though it is hard to avoid in Java; seems like everything useful takes a StringBuffer instead of a String. Java -- the high-level language with about as much abstraction as assembly.)
- aaronblohowiak 16y agoYou missed the part in strlen's comment where strlen says that every non-primitive value is a pointer. This also explains the behavior that you describe, with the caller's version of a variable being modified by a callee. However, this is different than pass-by-reference. With pass-by-reference, if i assign a new value to the callee argument variable, that value also replaces the value in the caller. This is not true in java/python/ruby where it is termed "call by sharing" http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sha...
- strlen 16y ago> Java is pass-by-reference. Pass in object foo, call smash_with_hammer on foo in the called function, and the caller finds that his foo was smashed by a hammer when control returns to him In agreement here, the state of the object changes according to a message passed to the object. In this case, the value we passed is a pointer to the object. We can't, however, change what object the pointer points to in Java, which is why I call it "pass by value". E.g., I can't do equiv of this Perl code. sub bar { my $foo = Foo->new(a => "a"); foo(\$foo); } sub foo { my $arg = shift; $$arg = Foo->new(a => "b"); } On the other hand, in Perl even though I am passing a reference by value, I can still mutate the state of the object: sub bar { my $foo = Foo->new(a => "a"); bar($foo); } sub foo { my $foo = shift; $foo->set_a("b"); } (Please excuse my Perl, I haven't written OO Perl in over a year now). In any case, I think this is a pedantic point. Both of us agree that other than in few cases (algorithms/data structures that are difficult to express in a functional way), objects shouldn't be smashed by hammers: whether internal or external. I also don't understand why Java's standard library authors didn't do what Scala did and provide both mutable and immutable versions of collections. Java 5+ added great lock free data, concurrent data structures, but much like they have a ConcurrentMap, they could have added a "ImmutableMap"/"ImmutableList" interfaces (especially given the fact that some data structures e.g., CopyOnWriteArrayList behave like this internally). I really like Scala's "functional objects": objects that upon receiving a messages, create new objects. In Java, an object may be final, but it will still (as you put it) "be smashed by a hammer" as long as the hammer smashing was invoked by a message. Same thing happens in C++ with const methods, in objects passed as const& references which contain objects that mutate their state upon a message being passed. Rich Hickey discusses this much better than I do in his famous talk: http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey http://www.infoq.com/presentations/Value-Identity-State-Rich... (although I may not agree with all of his conclusions) > seems like everything useful takes a StringBuffer instead of a String That's a textbook example of premature optimization :-) The compiler will convert string concatenation to StringBuilder. See: https://gist.github.com/670577 https://gist.github.com/670577 It does makes sense to use a StringBuilder when you are doing concatenation inside a loop (and don't want the overhead of allocating a new StringBuilder inside), but otherwise there's no advantage to it. (Oddly enough, in this example the default optimization level did not unroll the loop itself. OCaml, on the other hand, despite having a much more compiler-friendly type system than Java, doesn't perform the equivalent optimization on string concatenations with the '^' operator. I am pretty sure g++ will do both, despite C++ being lower-level and having weaker typing than OCaml and Java). For another example of this kind of premature optimization, see people using inline in C++ code when the gcc/clang will have a much better idea than the developer on when to inline a function call and when not to :-)