2016-08-03 12 views
2

zu Neudefinition habe ich eine Funktion wie folgt definiert:Scala wie Standardeinstellungen zu verwenden, ohne sie

def par(min: Int = -1, exact: Int = -1, auto: Boolean = false) = { 
    require(min > 0 || exact > 0 || auto, "Invalid argument") 
    OpPar(drm, minSplits = min, exactSplits = exact) 
} 

In einer anderen Funktion, die diese gebe ich in den Optionen für die par params verwendet. Ich möchte par erlauben, seine eigenen Standardeinstellungen zu verwenden, aber sehe nicht, wie man das in Scala macht (ohne hässliche Logik), also muss ich die Standardeinstellungen wie diese neu definieren.

drmARaw.par(
    min = minPar.getOrElse(-1),// if par changes this may the be wrong default 
    exact = exactPar.getOrElse(-1),// if par changes this may the be wrong default 
    auto = autoPar.getOrElse(true)) 

Wenn die Standardwerte immer dies die falschen Vorgaben zu min und exact passieren wird sich ändern. Mit komplizierter Logik kann ich entscheiden, welche Version von par aufrufen, basierend auf Option Parameter sind nonEmpty für minPar und exactPar aber das ist ziemlich hässlich und müsste für jede Funktion mit Standard-Parameter anders geschrieben werden. Diese Situation tritt bei praktisch jeder Scala-Bibliothek auf. Wenn sie die Standardeinstellungen ändern und ich es nicht merke, bricht mein Code ab.

Das obige Beispiel veranschaulicht das Problem, aber ich suche nach einem Scala-Idiom, das jeden Fall abdecken würde, in dem eine Funktion Standardwerte hat, die sich ändern könnten. Ich möchte Code schreiben, der von Standardparamänderungen in lib-Funktionen unabhängig ist.

+0

Sie könnten eine Konstante für jeden Standardwert verwenden, d. H. 'Val MinParDefault = -1'. Dann könnten Sie das in 'minPar.getOrElse (MinParDefault)' verwenden. –

+0

Ich kann die Par-Funktion nicht ändern, sie befindet sich in einer Lib. – pferrel

+0

Mein Fehler - ich meinte für 'minPar' usw. –

Antwort

0

So, wie ich es verstehe, haben Sie drei Option s, die Sie als übergebene Parameter entpacken und senden müssen, außer wenn eine Option None ist, dann sollte die aufgerufene Methode ihren eigenen Standardwert für den fehlenden Parameter verwenden.

Es scheint mir Ihre einzige Wahl ist rohe Gewalt.

(minPar, exactPar, autoPar) match { 
    case (Some(m),Some(e),Some(a)) => par(min=m, exact=e, auto=a) 
    case (Some(m),Some(e),None) => par(min=m, exact=e  ) 
    case (Some(m),None, Some(a)) => par(min=m,   auto=a) 
    case (Some(m),None, None) => par(min=m    ) 
    case (None, Some(e),Some(a)) => par(  exact=e, auto=a) 
    case (None, Some(e),None) => par(  exact=e  ) 
    case (None, None, Some(a)) => par(    auto=a) 
    case (None, None, None) => par() 
} 

Mit 2 Parametern ist es einfach. Mit 3 ist es überschaubar. Danach ... schmerzhaft.

+1

Wahrheitstabellen - zumindest lügen sie dich nicht an. – bash0r

+0

Ja, das ist es, was ich mit hässlicher Logik gemeint habe, aber du hast es so schön wie möglich gemacht. Ich akzeptiere, dass dies der beste Weg ist, es zu tun. Ich hoffe, die Scala-Götter hören zu ;-) – pferrel

0

Sie könnten die Logik in einen separaten case class extrahieren, der einen zero oder empty Zustand hat.

case class ParInput(min: Int, exact: Int, auto: Boolean) 

object ParInput { 
    def apply(min: Option[Int], exact: Option[Int], auto: Option[Boolean]) = { 

    ParInput(
     min.getOrElse(empty.min), 
     exact.getOrElse(empty.exact), 
     auto.getOrElse(empty.auto) 
    ) 
    } 
    val empty = ParInput(-1, -1, false) 
} 

Hier ist der Rest dieses:

def par(input: ParInput = ParInput.empty) = { 
    require(min > 0 || exact > 0 || auto, "Invalid argument") 
    OpPar(drm, minSplits = input.min, exactSplits = input.exact) 
} 

def par(
    min: Option[Int] = None, 
    exact: Option[Int] = None, 
    auto: Option[Boolean] = None 
): OpPar = { 
    val input = ParInput(min, exact, auto) 
    // now call the original library method. 
    par(drm, input.min, input.exact) 
} 

Alles was Sie jetzt aktualisieren müssen die leeren Zustand ist, und fertig. Du bekommst sogar einen kostenlosen Monoid.

+0

@KevinMeredith Ja stimme ich zu, tippte ein wenig zu schnell dort. – flavian

+0

Aber das löst das Problem nicht, es bewegt es nur. Das Problem ist, dass es in Scala anscheinend keine Möglichkeit gibt, auszudrücken, dass, wenn 'minPar == None', ich 'pars Standardwerte verwenden möchte, was auch immer sie sein mögen. Mit anderen Worten, die Lösung, die ich suche, enthält nicht "-1" oder "falsch". Ich dachte, es könnte einen speziellen Wert geben, der sagt: "Benutze die Standardfunktion der aufgerufenen Funktion" oder eine funktionale Methode, um diese Logik für jeden Fall zu verbergen, da dies oft auftaucht, wenn Scala-Bibliotheken verwendet werden. – pferrel

+0

@pferrel Aktualisiert, hoffe, ich vermisse nichts, aber das sollte Ihr Problem lösen. – flavian

Verwandte Themen