I'm working on a Scala API (for Twilio, by the way) where operations have a pretty large amount of parameters and many of these have sensible default values. To reduce typing and increase usability, I've decided to use case classes with named and default arguments. For instance for the TwiML Gather verb:
case class Gather(finishOnKey: Char = '#',
numDigits: Int = Integer.MAX_VALUE, // Infinite
callbackUrl: Option[String] = None,
timeout: Int = 5
) extends Verb
The parameter of interest here is callbackUrl. It is the only parameter which is really optional in the sense that if no value is supplied, no value will be applied (which is perfectly legal).
I've declared it as an option in order to do the monadic map routine with it on the implementation side of the API, but this puts some extra burden on the API user:
Gather(numDigits = 4, callbackUrl = Some("http://xxx"))
// Should have been
Gather(numDigits = 4, callbackUrl = "http://xxx")
// Without the optional url, both cases are similar
Gather(numDigits = 4)
As far as I can make out, there are two options (no pun intended) to resolve this. Either make the API client import an implicit conversion into scope:
implicit def string2Option(s: String) : Option[String] = Some(s)
Or I can redeclare the case class with a null default and convert it to an option on the implementation side:
case class Gather(finishOnKey: Char = '#',
numDigits: Int = Integer.MAX_VALUE,
callbackUrl: String = null,
timeout: Int = 5
) extends Verb
My questions are as follows:
- Are there any more elegant ways to solve my particular case?
- More generally: Named arguments is a new language feature (2.8). Could it turn out that Options and named default arguments are like oil and water? :)
- Might using a null default value be the best choice in this case?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…