PROPOSAL: Named and Optional parameters, "Java-style"

Paul Benedict pbenedict at apache.org
Thu Aug 18 08:06:41 PDT 2011


I believe recording the name of argument methods would require a class
file update. That might be against the spirit of a "coin" enhancement.

2011/8/18 Frédéric Martini <frederic.martini at gmail.com>:
> Hello,
>
> (before to start, sorry for my poor english)
>
>
> I'd like to propose the implementation of named & optional method
> parameters, similar to the Java 5.0 varargs.
>
>
>
>
> PROPOSAL: Named and Optional parameters, "Java-style"
>
> AUTHOR(S): Frédéric Martini
>
> OVERVIEW
>
> FEATURE SUMMARY:
>
> Named parameters free you from the need to remember or to look up the
> order of parameters in the parameter lists of called methods. The
> value for each parameter will be specified by name (instead of by
> order).
>
>
> Optional parameters allow methods to specity a default value for
> parameters, that allow caller to omit theses. If no value is sent for
> theses parameters, the default value is used.
>
>
>
> MAJOR ADVANTAGE:
>
> Generally, this is implemented via syntactic sugar and affects only
> the compilation step. But this would make a lot of limitation in a
> language like Java :
>
>  * The widespread use of "Named parameter" will put the parameter
> names in the method's signature. So any changes at this level could
> potentially break compatibility.
>
>  * The use of "Optional parameter" limits the method's evolution :
> Adding an optional parameter causes incompatibilities (break at runtime).
> Default values are limited to constant, and fixed at compile-time.
> Their changes involve a recompilation of callers codes, and they can
> not be modified by overriding...
>
> (See reference "Use Optional Parameters to Minimize Method Overloads"
> for détail of these problems on C# implementation)
>
>
> This proposal opts for another approach similar to the Java 5.0
> varargs, which impacts both the compilation and runtime steps : all
> "named & optional" parameters will be stored in a sort of map, an
> retrieved or set to default-value at runtime .
>
>
>
>
> MAJOR BENEFIT:
>
> Allows the creation of clearer and precise API.
> They can easily replace most of "builder pattern" and method's
> overloading, using a single method...
>
> Without any impact on existing code or method signature that don't use
> "named & optional parameters".
>
>
> MAJOR DISADVANTAGE:
>
> Method's call will be slowest when using named & optional args.
>
>
>
> ALTERNATIVES:
>
> Method's overloading and/or "builder pattern". But this is boring :(
>
>
>
>
> EXAMPLES
>
> SIMPLE EXAMPLE:
>
> // Method declaration
> // The named & optional parameters are distinguished by brackets {}
>
> public void method(int standardArg, {int namedArg, int namedAndOptionalArg=0}) {
>        System.out.printf("%d;%d;%d", standardArg, namedArg, namedAndOptionalArg);
> }
>
>
> // Method call
> // The named & optional parameters MUST be called by name.
>
> method( 1, namedArg:2, namedAndOptionalArg=3 ); // output: 1;2;3
> method( 1, namedAndOptionalArg=3, namedArg:2 ); // output: 1;2;3
> method( 1, namedArg:2 );                        // output: 1;2;0
>
> // Of course compiler will check that the call is correct :
> // + Non-optional parameters MUST be present.
> // + Invalid parameter's name will generate error.
>
> method( 1 );                            // COMPIL ERROR : "namedArg" is required
> method( 1, namedArg:2, invalidName:3 ); // COMPIL ERROR :
> "invalidName" is not a valid name
>
>
>
>
> ADVANCED EXAMPLE:
>
>
> // Optional parameters can use contant OR statement :
>
> public void method({String separator=";", Locale
> locale=Locale.getDefault(), String
> lineSeparator=System.getProperty("line.separator")}) {
>
> }
>
>
> // Method declaration can use varargs, that allow the usage of any
> name/value without compile error
> // Each implementation can check for theses parameters...
>
> public void method({String filename, ...} options);
>
> // all these call are valid :
> method(filename:"file.txt");
> method(filename:"file.txt", encoding:"utf-8");
> method(filename:"file.txt", encoding:"utf-8", append:true);
> method(filename:"file.txt", encoding:"utf-8", append:true, anything:anyValue);
>
>
> DETAILS
>
> SPECIFICATION:
>
>
> The use of Named & Optionnal paramters MUST be specified on the method
> signature.
> Named parameters will be distinguished by brackets {}, and MUST be
> passed by name at call time.
> Any named parameter can have a default value, that can be a
> compile-time constant OR a statement.
>
>
> // exemple01 : use of named parameter :
>
> public void exemple01({int foo, String bar}) {
>        System.out.printf("exemple01(foo=%d, bar=%s)%n", foo, bar);
> }
>
> // exemple02 : use of named & optional parameter using constant :
>
> public void exemple02({int foo=30, String bar="hi"}) {
>        System.out.printf("exemple02(foo=%d, bar=%s)%n", foo, bar);
> }
>
> // exemple03 : use of named & optional parameter using constant AND statement :
>
> public void exemple03({int foo=30, String bar=System.getProperty("os.name")}) {
>        System.out.printf("exemple03(foo=%d, bar=%s)%n", foo, bar);
> }
>
>
> // exemple04 : use of named & optional parameter using constant AND statement,
> //             AND use varargs to allow any name/value parameters.
>
> public void exemple04({int foo=30, String
> bar=System.getProperty("os.name"), ...} args) {
>        System.out.printf("exemple04(foo=%d, bar=%s) + %s%n", foo, bar, args);
> }
>
>
> // Calling example :
>
> exemple01(foo:10, bar:"hello");
>
> System.out.println();
>
> exemple02(foo:10, bar:"hello");
> exemple02(foo:10);
> exemple02(bar:"hello");
> exemple02();
>
> System.out.println();
>
> exemple03(foo:10, bar:"hello");
> exemple03(foo:10);
> exemple03(bar:"hello");
> exemple03();
>
> System.out.println();
>
> exemple04(foo:10, bar:"hello", any=100, name="value");
>
>
> COMPILATION:
>
> At compile time, each "named & optional" method will be converted to a
> method using a parameters of type "OptArgs". The type is contains a
> Map with all parameters name/value. Theses methods will be annoted to
> describe parameters names/types, and a basic code willbe generated to
> initialise parameters as local variables
>
>
>
>
> // exemple01 : use of named parameter :
>
> @OptArgsInfo({
>        @OptArg(name="foo", type=int.class),
>        @OptArg(name="bar", type=String.class),
> })
> public void exemple01(OptArgs $generated$) {
>        final int foo = $generated$.retrieve("foo", int.class);
>        final String bar = $generated$.retrieve("bar", String.class);
>
>        System.out.printf("exemple01(foo=%d, bar=%s)%n", foo, bar);
> }
>
>
> The annotation @OptArgsInfo will describe all parameters that the
> method can receive in the "OptArgs" parameters.
> The "OptArgs" object contains a retrieve(String,Class) method in order
> to get the parameter value for the specified name/type.
>
>
>
>
> // exemple02 : use of named & optional parameter using constant :
>
> @OptArgsInfo(value={
>        @OptArg(name="foo", type=int.class, optional=true),
>        @OptArg(name="bar", type=String.class, optional=true),
> })
> public void exemple02(OptArgs $generated$) {
>        final int foo = $generated$.retrieve("foo", int.class, 30);
>        final String bar = $generated$.retrieve("bar", String.class, "hi");
>
>        System.out.printf("exemple02(foo=%d, bar=%s)%n", foo, bar);
> }
>
>
> Here the named parameters are optionals (because they have a default value).
> If parameter is absent, the method retrieve(String,Class<T>,T) return
> the default constant value.
>
>
>
>
> // exemple03 : use of named & optional parameter using constant AND statement :
>
> @OptArgsInfo(value={
>        @OptArg(name="foo", type=int.class, optional=true),
>        @OptArg(name="bar", type=String.class, optional=true),
> })
> public void exemple03(OptArgs $generated$) {
>        final int foo = $generated$.retrieve("foo", int.class, 30);
>        final String bar = $generated$.contains("bar", String.class)
>                ? $generated$.retrieve("bar", String.class)
>                : System.getProperty("os.name");
>
>        System.out.printf("exemple03(foo=%d, bar=%s)%n", foo, bar);
> }
>
>
> For optional parameters that use statement as default value, we use
> the ternary operator "?" to correctly initialize the variable when
> parameter is absent.
>
>
>
>
>
> // exemple04 : use of named & optional parameter using constant AND statement,
> //             AND use varargs to allow any name/value parameters.
>
> @OptArgsInfo(acceptUnknownArgs=true, value={
>        @OptArg(name="foo", type=int.class, optional=true),
>        @OptArg(name="bar", type=String.class, optional=true),
> })
> public void exemple04(OptArgs args) {
>        final int foo = args.retrieve("foo", int.class, 30);
>        final String bar = args.contains("bar", String.class)
>                ? args.retrieve("bar", String.class)
>                : System.getProperty("os.name");
>
>        System.out.printf("exemple04(foo=%d, bar=%s) + %s%n", foo, bar, args);
> }
>
>
> The annotation contains the value acceptUnknownArgs=true in order to
> inform the compiler that this method accept any name/value in addition
> to its declared parameters. In the body of the method, it may be
> possible to use the object "OptArg" in order to access to these
> additional parameters...
>
>
>
>
>
> // Calling example :
>
>
> exemple01(OptArgs.make("foo", 10, "bar", "hello"));
>
> System.out.println();
>
> exemple02(OptArgs.make("foo", 10, "bar", "hello"));
> exemple02(OptArgs.make("foo", 10));
> exemple02(OptArgs.make("bar", "hello"));
> exemple02(OptArgs.empty());
>
> System.out.println();
>
> exemple03(OptArgs.make("foo", 10, "bar", "hello"));
> exemple03(OptArgs.make("foo", 10));
> exemple03(OptArgs.make("bar", "hello"));
> exemple03(OptArgs.empty());
>
> System.out.println();
>
> exemple04(OptArgs.make("foo", 10, "bar", "hello", "any", 100, "name", "value"));
>
>
>
>
>
> This solution propose a less-disturbing choise :
>
>
>  * The "named and optional" parameters block must be at the end of the
> method's parameter list (like varargs).
>  * Named parameters can only be used with specific method that
> contains a "named & optional" block.
>  * There are no impact on method that don't use "named & optional parameters".
>  * We can override an "named and optional" method.
>  * We can add an optional parameter to an existant "named and
> optional" method (or on an overrided method).
>  * We can remove an optional parameter on an overrided method (if
> present it will be ignored)
>  * We can modify the default value of an optional parameter withour
> having to recompile all the caller's code.
>  * Renaming a "named parameter", removing a default-value or adding a
> non-optional parameter is an incompatible change.
>
>
>
> TESTING:
>
>
> A basic implementation can be found here (source-code) :
> http://adiguba.developpez.com/coin-optargs/
>
>
> LIBRARY SUPPORT:
>
> No.
>
> REFLECTIVE APIS:
>
> java.lang.reflect.Method and java.lang.reflect.Constructor could be
> enhanced with new methods that return informations about "named &
> optional parameters" :
>
>
> isOptArgs()
>        return true if method use "named & optional parameters"
>
> getOptArgs()
>        return an array of OptArg annotation, that describe the "named &
> optional parameters".
>
> isOptArgsAcceptUnknownArgs()
>        return this if method accept unknown name/value args (varargs-like).
>
>
> OTHER CHANGES:
>
> Javadoc must be updated in order to accept @param that match the named
> parameters, and indicate optional parameter.
>
> MIGRATION:
>
> This is a new syntax for new method.
>
>
> COMPATIBILITY
>
> BREAKING CHANGES:
>
> No (new syntax).
>
>
> EXISTING PROGRAMS:
>
> The changes required by this feature should be transparent to existing
> source and class files.
> It only consist to a method with a new and specific type.
>
> Overriding is still possible.
>
> REFERENCES
>
> Use Optional Parameters to Minimize Method Overloads :
> http://msdn.microsoft.com/en-us/vcsharp/ff467291
>
>
> EXISTING BUGS:
>
> ?
>
> URL FOR PROTOTYPE :
>
> A basic implementation with demo that represent the code generated by
> the compileur (I do not have sufficient expertise to offer a modified
> version of javac) :
> http://adiguba.developpez.com/coin-optargs/
>
>
>
>
>
>
> Thanks for reading :)
>
>



More information about the coin-dev mailing list