instead of using string type #1 to define parameters, you also can use list @() as parameters :

body common control
{
      bundlesequence => {
                          "test_vars",
                          test(@(test_vars.params)),
                        };
}

bundle common test_vars
{

  vars:

   # declare
   "types"
     slist  => { "show", "action" };
   "params"
     slist  => maplist("$(this.bundle).$(this)", "types");

   # define
   "$(types)[version]"
     string => "$(types)_0.1";
   "show[other]"
     string => "other_value";
}

bundle agent test(params)
{

  vars:

   "bundle[$(params)]"
     string => lastnode("$(params)", "\.");

  services:

    "function_$(bundle[$(params)])"
      service_policy => "start",
      service_method => bundle_handler("$(params)");
  reports:

    linux::
      "params : $(params)";
}

body service_method bundle_handler(s)
{
    service_bundle            => $(this.promiser)("$(s)");
}
bundle agent function_show(a)
{

  vars:

    "index"
      slist => getindices("$(a)");

  reports:

    cfengine_3::
      "$(this.bundle) :: $(index) = $($(a)[$(index)])";
}

bundle agent function_action(a)
{

  reports:

    cfengine_3::
      "$(this.bundle) :: version = $($(a)[version])";
}

In action :

# cf-agent -f ./test_listdynparam.cf
R: function_show :: other = other_value
R: function_show :: version = show_0.1
R: function_action :: version = action_0.1
R: params : test_vars.show
R: params : test_vars.action