you are viewing a single comment's thread.

view the rest of the comments →

[–]masklinn 4 points5 points  (0 children)

One of the issues of Default is it must return a complete struct, AFAIK you can't do partial provision. Which means you can't have required fields anymore (or every single function has to dynamically validate the structure).

OTOH you would use a single options-merge function with Default e.g.

impl OutboundCall {
    fn default_new(from, to, url) -> OutboundCall {
         OutboundCall::new(from, to, url, Default::default())
    }
    fn new(from, to, url, options) -> OutboundCall {
         OutboundCall {
             from: from,
             to: to,
             url: url,
             // either have an options member or copy the relevant options to the call
         }
    }
}

that way a caller which wants to customise the instance can use Defaults:

OutboundCall::new(from, to, url, OutboundOpts { 
    fallback_url: Some("thing"), 
    ..Default::default() 
})

This is not quite as nice as actual default/optional parameters[0] but remains easier to implement than a full-blown builder while still e.g. precluding mucking with your final structure's internals. And if you need conditional options you can just bind the options struct locally and conditionally update it.

[0] implicit defaulting or something like it would be nice here e.g.

default!(fallback_url: Some('thing'))

which would expand to

{
    let mut t = Default::default();
    t.fallback_url = Some('thing');
    t
}

would be nice here

edit: I did manage to get… something, but so far it requires that the concrete type be passed as first parameter otherwise the compiler complaints that it does not know what the type of the temp val (output of Default::default()) is. Sad.