#1303 Some way to obtain Param's default value through reflection

tonsky Tue 9 Nov 2010

When calling Func#callList I can get list of params through Func#params, I can determine if Param has default value or not (via Param#hasDefault), but I cannot keep default values if I don't want to override them.

For example:

class HttpResponse {
  new make(Str body, Str contentType := 'text/plain', Int responseCode := 200)
}

now I can do (last param kept defautl):

HttpResponse#make.func.callList(["some body", "text/html"])

but I cannot do (override last but keep second):

HttpResponse#make.func.callList(["some body", ___keep default value___, 404])

It's needed in some heavy reflection-based code (dispatchers etc).

Maybe smth like Obj? Param#defaultValue?

brian Tue 9 Nov 2010

I definitely understand your plight, but unfortunately the problem is that there is no such thing as a default value, rather it is a default expression.

So in some cases you actually have to have an instance and all the other parameters to actually figure out what the default should be. Here is a simple example:

class Foo
{
  Str foo(Int x, Str y := "$this $x") { y }
  Void main() { echo(foo(3)) }
}

tonsky Tue 9 Nov 2010

Some kind of smart Func#call([Param:Obj] params) then maybe?

brian Tue 9 Nov 2010

Maybe I don't understand your problem, but you know you can just leave off the arguments to call or callList which you want to fallback to the default?

fansh> f := Int#toHex.func
fan.sys.Method$MethodFunc@120cc56
fansh> f.callList([100])
64
fansh> f.callList([100, 4])
0064

In your example you are trying to keep a default in the middle of the argument list - you can't do that though (in either Fantom or via reflection).

tonsky Wed 10 Nov 2010

Yes, that's exactly what I want — to keep default value in the middle of the arguments list. Is it possible to make it possible :) ?

brian Wed 10 Nov 2010

Sorry, don't think it is really feasible. Consider what happens under the covers:

Void foo(Str a := "a", Str b := "b", Str c := "c")

Compiles into Java like this:

void foo() { foo("a", "b", "c""); }
void foo(Str a) { foo(a, "b", "c"); }
void foo(Str a, Str b) { foo(a, b, "c"); }
void foo(Str a, Str b, Str c) { ... }

So you can see that everything is pretty optimized based on parameter ordering. I have some ideas for named parameters and how that would work. But that is a future thing.

One "hack" you might try is to get the docs from the method via sys::Slot.doc. The documentation contains meta-data about the defaults used for display purposes. In the cast of literals this might be decodable. No guaratees of course, but will probably work for basic cases.

Login or Signup to reply.