5 ms·
Reading this, I though to myself that one of the biggest features I like in python that is missing in java is named and optional parameters. Also, any api/libr
by herge 13y ago
Reading this, I though to myself that one of the biggest features I like in python that is missing in java is named and optional parameters.
Also, any api/library that lets you create an object that is unusable because specific methods to set up values haven't been called yet is very error prone.
- sparkie 13y agoI think optional parameters are a mis-feature in C#. You can acheive the same thing with a simple overload which calls a method without the optional parameter, and this is more robust. The problem with optional parameters is they work by call site rewriting. If I have some library method where I give an optional parameter a default value, and a program is built against it - if I later change the default value, this will not be propagated to the program until it's recompiled - it'll continue to use the old default. They could probably fix this by implementing overloads behind the scenes, rather than rewriting the call site though. If Java does ever implement this, I hope they do it that way.
- Associat0r 13y agoThey fixed this in F#.
- sukuriant 13y agoHaving lived in both overload world and optional parameter world, I have found optional parameters to be infinitely more useful, especially when there are SEVERAL optional parameters that you may or may not want. Most of the time when I see the overload style, we have several: public void A() { A(1); } public void A(a) { A(a, 2); } public void A(a, b) { A(a, b, c); } public void A(a, b, c) { /* do something */ } Or, worse, public void A() { A(1, 2, 3); } public void A(a) { A(a, 2, 3); } public void A(a, b) { A(a, b, 3); } public void A(a, b, c) { /* do something */ } It wastes several lines and could be much more simply expressed, to the developer as: public void A(a = 1, b = 2, c = 3) { /* do something */ } Regarding the issue you have, I can certainly see that as an actual issue and it should probably be dealt with; though, the CLR developers probably had to decide between two opposing and frustrating viewpoints: "What if they want the old default? After all, they did compile against it, knowing that that's what we set it to default"; and, "Maybe they just want the computer to figure out what's best for them..." As a library designer, you'll now have to consider the possibility that they're using the old version of your library. Realistically, they most likely will compile their program again instead of in-place replacing your dll. It's safer that way. All of that said, when I usually use optional parameters, I generally set them to null. You cannot set them to, for example, a new instance of an object, they have to be static values; so, if someone uses a default parameter, my code sees: "oh, it's null. Now I'll use my default parameter that I set internally, because it came from a configuration file and I couldn't set that as a default parameter anyway given their constraints", and I don't have the problem you mention at all. Example: public void A(a = null, b = null, c = null) { a = a ?? new AParam(); b = b ?? SomePropertyFromAConfigFile; c = c ?? DBNull.Value; /* do something */ } The ?? syntax makes this practically the recommended route, I think. (a ?? b is C# shorthand for (a != null? a : b) ). I'm happy, the people using my library are happy, and the issue that you describe doesn't exist in my code because of this. Of course it does make it a bit awkward for some kinds of primitives, for example; but, if they don't want to provide a parameter to my library, that parameter being provided as 'null' seems the most accurate way for my library to receive it anyway.
- sitharus 13y agoEven worse, optional parameters are implemented backwards. That is: public void DoSomething(string required, string optional = null) is actually DoSomething(string, string), but at compile time a call to DoSomething("foo") is compiled to DoSomething("foo", null). Hence optional parameters are not recommended for an external API.
- sukuriant 13y agoSo you need to be mindful and have intelligent overloads for the DoSomething method? Personally, I don't really see that as much of a problem. Having run into that issue before, I think the compiler catches it as as an error because its an ambiguous method signature. Instead, you have to pass something like: "DoSomething("foo", (string)null)" which, in that case, defeats the purpose of the optional parameter altogether.
- sitharus 13y agoYeah, been through that before. We just standardised on using overloads for external APIs, it's cleaner externally. The real issue is if you have DoSomething(string what, autoRetry=true) and you change to DoSomething(string what, autoRetry=false) - DLLs compiled against the old version will call with true even if the authors wanted the default behaviour.
- sukuriant 13y agoThat makes sense. As I said in my other thread, I locally deal with that problem by passing null instead of a primitive (though admittedly, I would probably use a primitive in cases of bool). That said, in this circumstance my method sounds more like a hack and yours the cleaner, correct route.
- estebank 13y ago> Also, any api/library that lets you create an object that is > unusable because specific methods to set up values haven't > been called yet is very error prone. That's what the Builder pattern[1] is for, avoiding the instantiation of incomplete objects. I've thought about the appropriateness of that pattern to Python, and so far what I've come up with is merely to use optional named parameters for private/simple classes and Builder classes for public/brittle/robust classes/APIs. [1]: http://en.wikipedia.org/wiki/Builder_pattern http://en.wikipedia.org/wiki/Builder_pattern