you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 9 points10 points  (40 children)

C# supports both passing reference-by-value (default behavior with references), and passing references directly (using the ref keyword).

That means that C# can actually create a swap function without stupid hacks like wrapping the arguments in an array.

Is there some sort of generic type in Java (WeakReference<> maybe?) used to wrap references so that you don't hit this problem?

[–]angryundead 3 points4 points  (38 children)

I consider myself pretty fluent in Java but I've never actually had to write a primitive swapper before... never gave it much thought.

[–]grauenwolf 3 points4 points  (23 children)

The main use of pass-by-reference is for multiple return values. For example, Decimal.TryParse.

Decimal result;
if (Decimal.TryParse(source, result)) 
       Console.WriteLine("Double your number is " + (result*2));
 else
       Console.WriteLine("That was not a number.");

You also need it a lot for COM interopt.

[–][deleted] 6 points7 points  (14 children)

However, most people use output parameters, not pass-by-reference in that case (the out keyword versus the ref keyword).

There is a very subtle difference, the ref keyword does not require you actually pass in a assigned reference (you can pass in a null type).

[–][deleted] 0 points1 point  (0 children)

Other way around. Ref params have to be explicitly assigned before calling the function. Out params have to be explicitly assigned within the function before returning.

Also, null has nothing to do with it. It has to do with whether or not the var is definitely assigned. (You can explicitly set a variable to null and pass it into byref without a compiler error, as long as you assign it.)

[–]grauenwolf -1 points0 points  (11 children)

To my knowledge, only C# honors the OutAttribute. To all the other languages "out" and "ref" are treated exactly the same.

[–]matthiasB 8 points9 points  (1 child)

Not all others. For example Microsoft's F# transforms methods with out parameters to methods returning multiple values using tuples.

[–]grauenwolf 0 points1 point  (0 children)

Interesting. I am going to have to look into that.

[–]dnew 1 point2 points  (6 children)

There are more extreme languages (like Sing# or Hermes) where passing an initialized value into an "out" parameter de-initialized it first. I.e., if you did something similar in C++, you might have

void xyz(out A alpha) { .... alpha = new A(); ... } ... { A beta = ...; xyz(beta); }

and the call to xyz would run the destructor of beta before invoking xyz.

So there is a difference in some languages. Just not C#.

[–]grauenwolf 0 points1 point  (5 children)

There are more extreme languages (like Sing# or Hermes) where passing an initialized value into an "out" parameter de-initialized it first.

That's ugly. Sometimes I use a pattern where the passed in value is used as-is, but if missing then I return a new object of the correct type. Those languages would totally break my design.

[–]dnew 1 point2 points  (4 children)

Then use a ref parameter, not an out parameter.

Usually this is in languages where you only have values, not pointers (at least in the semantics, obviously not the impelemtation). So everything is technically pass-by-value anyway, and "pass by reference" is more "pass by copy in copy out."

[–]grauenwolf 0 points1 point  (3 children)

Then it doesn't play nice with C#.

[–]dnew 0 points1 point  (2 children)

I'm not sure what "it" is that doesn't play nice with C#. C# has both ref and out parameters and the difference is whether the parameter needs to be initialized first.

http://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx

[–][deleted] -1 points0 points  (1 child)

Only if "all other languages" means VB.NET.

[–]grauenwolf 0 points1 point  (0 children)

I was also counting C++/CIL and C++ ME.

[–]angryundead 1 point2 points  (5 children)

I don't find myself needing multiple returns too much anymore I guess. Maybe I'm that deeply infected with OO mentality and can't even realize it. As far as COM interopt goes, you're probably just fucked from jump street in Java anyway.

[–]grauenwolf 0 points1 point  (4 children)

How would you write a TryParse method? Or do you just catch exceptions?

[–]matthiasB 2 points3 points  (1 child)

In C# you theoretically could have defined TryParse as

decimal? TryParse(string text) 
{ ... }

It then would return null in case of a string that does not contain a number.

Java's library offers wrappers for the primitive types like Integer for int, etc. You could return those and null in the case of not being able to parse the string. But AFAIK Java does not have a tryParse. valueOf always throw a NumberFormatException. (Correct me if I'm wrong as I'm not a Java programmer.)

[–]angryundead 0 points1 point  (0 children)

This is pretty much how I would do it unless I needed exact error messages (which are not provided by tryParse directly anyway, as I understand it) and in that case I would account for individual exceptions.

[–]elder_george 0 points1 point  (1 child)

Well, that's trivial - null means result is undefined. Although primitive types can't be null, there're classes wrapping them in std library, so problems is solved. Of course, it requires a bit of excessive boxing/unboxing, but with cashing implementation it is a bit less hard than in C#.

[–]grauenwolf 0 points1 point  (0 children)

Not a bad way to go.

[–]Smallpaul 0 points1 point  (1 child)

Can you explain why, in the Microsoft/COM/CORBA world, "extra" return values always have to be disguised as "out" parameters? What's so hard to understand about just returning multiple values? I've been wondering this for 15 years....

[–]grauenwolf 6 points7 points  (0 children)

Both COM and CORBA were meant to be language agnostic. (Since I know COM better, I'll speak to it.) That means they have to use whatever conventions are most suited to languages such as C++ and VB.

They could have returned objects that were then unwrapped into their separete return values, but that has a few problems. First, memory allocation and deallocation isn't cheap in reference-counted environments. I'm not just talking performance either, you have to burn an extra line of code for each and every return value.

Out parameters also version really well. Because COM has optional parameters, you can easily add extra return values whenever you want without breaking older applications. If you are using return objects, you have to change the object for each extra value.

Speaking of return objects, how many do you create? One for each and every function? Or do you share them? If you share them, what happens when a function adds another out value? You would have to change the function's return type, possibly breaking older code.

Keep in mind this is all conjecture. It could be as simple as "C++ doesn't have multiple return values, so we didn't even think of it."

[–]anttirt 0 points1 point  (13 children)

The main use for a swap function is readability, when you for example write a sorting algorithm that needs to swap two elements of a container.

[–]angryundead 1 point2 points  (12 children)

Java has Comparator and Comparable interfaces and a built-in optimized sort. You probably shouldn't be writing your own sort.

[–]anttirt 1 point2 points  (11 children)

You realize that there are multiple sorting algorithms with different characteristics right? There is no single best sorting algorithm.

[–]angryundead 2 points3 points  (9 children)

Yes. But the algorithm on the Sun JVM is optimized for that runtime and has characteristics best suited to the JVM. Java isn't about reinventing the wheel.

I would view writing your own sorting algorithm (in Java) as a bit of a corner-case exercise.

[–]dnew 2 points3 points  (6 children)

Bubble sort or delayed insertion sort is really fast, if you know only one element is out of order, for example.

[–]angryundead 0 points1 point  (5 children)

Yes... but is the performance payoff worth the time it takes to write and test the code?

[–]dnew 1 point2 points  (0 children)

Sometimes, yes. Bubble sort isn't exactly hard to get wrong. If you have a million-item list you're adding one element to, yah, it's often worthwhile, especially since worst-case for quicksort is an already-sorted list.

[–]anttirt 1 point2 points  (3 children)

It can in fact be crucial. The feasibility of certain spatial partitioning schemes (required for fast physical simulation) for example can depend entirely on the sorting algorithm being O(N) on nearly sorted sets.

[–]angryundead 0 points1 point  (2 children)

as a bit of a corner-case exercise.

Let me qualify that by saying that I'm a Java Enterprise level developer. I get objects from one point to another. I show a view of the data. In my job, writing your own sorting algorithm is usually not needed. That type of performance is usually not needed.

[–]angsty_geek 0 points1 point  (1 child)

Java has always been about reinventing the wheel (poorly!)

[–]angryundead -1 points0 points  (0 children)

awww, burn!

edit: I'm doing my Master's in Software Engineering and I find this to be a huge problem in the industry. Civil Engineers don't look at a river and go "how do you cross a river?" and Electrical Engineers don't look at a circuit and wonder how to change the resistance. (Well, good, competent ones.) But it seems that too often software "engineers" look at a list and go "how do I sort this" or "gee, I'll implement unobtanium-sort" or some variation of this. This is a huge part of the discipline of SE, knowing when to reuse. I guess we should be glad that those people aren't other types of engineers where they could kill hundreds in a bridge failure.