applyDynamicParamLists and applyDynamicParamListsNamedfor scala.Dynamic

After trying to write my own Proxy in Scala with scala.Dynamic and macros, I stumbled upon the pitfalls of scala.Dynamic (for scala version 2.11.12) in combination with multiple parameter lists.
The proposal is to just add two new methods which handle parameter lists explicitly

def applyDynamicParamLists(name: String)(args: Seq[Seq[Any]])

def applyDynamicParamListsNamed(name: String)(args: Seq[Seq[(String, Any)]])

All parameter lists should be combined into args (as with the other Dynamic methods, we don’t need to care about implicit parameters)

The following arguments for this mainly arrive from the aim to implement a Proxy using Dynamic and macros:

  1. Naturally mydynamic.multiParamListsMethod(1,2)(3,4)(5,6) gets splitted to ((mydynamic.multiParamListsMethod((1,2))(3,4))(5,6) which unfortunately is still buggy in combination with macros (see https://github.com/scala/bug/issues/11108).

  2. The way to map such nested calls to a corresponding true myoriginal.multiParamListsMethod(1,2)(3,4)(5,6) is by manually eta expanding the very first partial application. However we cannot use abbreviated eta-expansion, but need to know the precise number of required parameters –myoriginal.multiParamListsMethod(1,2)(_,_) will give us the partially applied function. Note that we don’t need to expand all parameter lists, but only the second parameter list. But how to know how many parameters are there? Reflections! Tedious, and even super tedious if there are multiple overloaded definitions of the same myoriginal.multiParamListsMethod.

  3. Finally there is the possibility to include default arguments in second and later parameter lists within myoriginal.multiParamListsMethod. Anonymous functions have no default arguments, so we cannot use eta-expansion. The alternative is to construct manual closure by constructing a new object. It’s apply function must include those default values as well (normal eta expansion won’t work). This is super tedious currently, see for instance https://stackoverflow.com/questions/14034142/how-do-i-access-default-parameter-values-via-scala-reflection.
    [Additional Note: anyway, this won’t work currently due to the bug https://github.com/scala/bug/issues/7914]

I hope I could show, that for the use case of constructing a Proxy for another object, the current design of Dynamic brings enormous complications when dealing with multiple parameter lists. Furthermore, it is even not working currently, due to the mentioned bugs.

As you probably have already noticed, with both new methods implemented, the old applyDynamic and applyDynamicNamed will no longer be needed in principle, however I assume that they have to be retained anyway for backwards compatibility. A simple way to support both would be to create these two new methods on a new Subclass of Dynamic, which offers default implementation for applyDynamic and applyDynamicNamed in terms of the new ParamLists versions.

1 Like

I think the current behavior of dynamic multiple parameter lists is simply a bug, as reported at https://github.com/scala/bug/issues/10307