How does a Relay OP support variable length parameter list?

In relay, number of inputs is fixed

inline OpRegistry& OpRegistry::set_num_inputs(int32_t n) {  // NOLINT(*)
  get()->num_inputs = n;
  return *this;
}

While in nnvm, the number of inputs can be changed through a callback

inline Op& Op::set_num_inputs(std::function<uint32_t (const NodeAttrs& attr)> fn) {  // NOLINT(*)
  this->get_num_inputs = fn;
  return *this;
}

I found a comment here:

 /*!
   * \brief number of input arguments to the operator,
   * -1 means it is variable length
   */
  int32_t num_inputs = -1;

But num_inputs is used to later to handle arg_types so it can’t be left as -1 actually

 // Add inputs.
  std::string input_name_prefix = "in";
  for (int i = 0; i < get()->**num_inputs**; i++) {
    auto name = input_name_prefix + std::to_string(i);
    auto param = TypeVarNode::make(name, Kind::kType);
    type_params.push_back(param);
    arg_types.push_back(param);
  }

@lixiaoquan Did you find a way around ? I have similar problem.

CC: @tqchen @jroesch can you shed some light if variable number of inputs is possible ?

I think the relay’s convention is to convert multiple parameters into a tuple.