1
votes

I want to write a variadic function that should have 1 parameter that is not optional of type string and a second string that is optional. I have read the language spec about variadic functions but considering D's many options I would like to know which is the appropriate solution for my problem.

Also how should I use cast and pointer for copying the string pointed by the void* _argptr (the fact that strings are immutable in D confuses me I guess).

Edit: What I want is something like:

string foo (string nonopt, ...) { /*code*/ }

//...
string a = "[email protected]", b = "a.t";
auto s = foo(a);
auto s2 = foo(a, b);
5
Please improve your question title and .. write a question. This isn't a "gimme teh codez" website. - Lightness Races in Orbit
Was there really a good reason for downvoting? Whoever did it - this is the main reason why people are afraid of asking questions here... I do not care about other groups, but in D I will try to answer any question, no matter how good/bad quality it is. - DejanLekic
@TomalakGeret'kal I don't know what is wrong with the title, except for the fact that it is maybe ambiguous because I was on the going on the wrong track with my code. I wrote 2 questions in fact witch were clear enough given that everyone gave basically the same answer and clarified this stuff for me. I did not asked for the codes. This was stuff I did for fun and learning programming [in D] and I could easily just post my entire code here if I wanted someone to fix it for me or to 'gimme teh codez'. By your standards every noob is a cargo cult programmer. - Byakkun
Also I won't edit the question to make me look less stupid/ignorant. People usually learn from mistakes not only from smart questions and examples of challenging engineering problems. - Byakkun
@Byakkun: What's wrong with the title is that it doesn't describe the question. It just consists of two words describing a language feature, and thus is completely useless in a list of questions. And By your standards every noob is a cargo cult programmer is just flat-out wrong, but nice strawman. - Lightness Races in Orbit

5 Answers

7
votes

What you're asking for doesn't sound variadic at all. You know exactly how many arguments there are supposed to be - either 1 or 2. In that case, just use a default argument for the second parameter. e.g.

void func(string required, string optional = null) {}

If what you want is a string followed by an unknown number of strings, then you'd probably want to do something like

void func(string required, string[] optional...)

If, on the other hand, what you want is something which takes a string followed by an unknown number of arguments of a variety of types, then what you want is a variadic template.

void func(T...)(string required, T optional) {}
4
votes

Do you wan't something like:

void foo(string required, string optional = "") {}

Or maybe like (not tested):

class Optional(T) {
  private T _val;
  public this(in T val) { _val = val; }
  @property public T get() { return _val; }
}

void foo(string required, Optional!(string) = null) {}
3
votes

Here is an example with foo() that does exactly what you asked in the OP, plus the foovar() function which can take arbitrary number of parameters. In this case I accept only string arguments, but you may change the code to accept anything.

import std.stdio;
import core.vararg;

string foo (string nonopt, string opt = "") {
  string ret;
  if (opt.length == 0)
    ret = nonopt;
  else
    ret = nonopt ~ ";" ~ opt;

  return ret;
} // foo() function

string foovar(string nonopt, ...) {
  string ret = nonopt ~ "/";
  for (int i = 0; i < _arguments.length; i++) {
    // we want to use only string arguments to build the result
    if (_arguments[i] == typeid(string)) {
      ret ~= va_arg!(string)(_argptr) ~ "/";
    } // if
  } // for
  return ret;
} // foovar() function

int main() {
  string a = "[email protected]", b = "a.t";
  auto s = foo(a);
  auto s2 = foo(a, b);
  auto s3 = foovar(a, "D", "rules");
  writeln(s);   // [email protected]
  writeln(s2);  // [email protected];a.t
  writeln(s3);  // [email protected]/D/rules/
  return 0;
} //  main() function
3
votes

You can do a C-style variadic function, in which case check out core.vararg. The preferred D solution is to use a templated function:

import std.stdio;

void foo(Args...)(string first, Args args)
{
    writeln("First argument is ", first);
    foreach (i, A; Args)
    {
        writefln("Type of %s argument is %s, value is %s",
                    i, A.stringof, args[i]);
    }
}

void main(){
    foo("bar", 1, 4.0, false);
}     
2
votes

Would the following not do?

void myFunction(string nonOptionalParameter, string optionalParameter="default value")
{
  // Your code here
}