2016-08-03 70 views
2

我定义为一个函数:斯卡拉如何使用默认设置,而不重新定义他们

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) 
} 

在使用这个我在选项中传为par PARAMS另一个函数。我想允许par使用它自己的默认值,但没有看到如何在Scala中做到这一点(没有丑陋的逻辑),所以我必须重新定义这种默认值。

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)) 

如果默认不断改变,这将传递错误默认为minexact。使用复杂的逻辑,我可以根据哪个Option params为nonEmptyminParexactPar来决定调用par的哪个版本,但这是相当丑陋的,并且对于每个带有默认参数的函数都必须以不同的方式写入。这种情况几乎发生在每个Scala lib。如果他们更改默认值,但我没有注意到,我的代码将会中断。

上面的例子说明了这个问题,但我正在寻找一个涵盖每个的情况,其中一个函数具有可能会改变的默认值的Scala成语。我想编写独立于lib函数中默认参数更改的代码。

+0

您可以为每个默认值使用一个常量,即'val MinParDefault = -1'。然后,你可以在'minPar.getOrElse(MinParDefault)'中使用它。 –

+0

我无法更改'par'函数,它在一个lib中。 – pferrel

+0

我的错误 - 我的意思是'minPar'等。 –

回答

0

所以,据我了解,你有三个Option s,你需要解包并发送作为传递的参数,除非有任何选项是None那么被调用的方法应该使用其缺省参数的默认值。

在我看来,你唯一的选择就是蛮力。

(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() 
} 

使用2个参数很容易。 3可以管理。之后......痛苦。

+1

真理表 - 至少他们不骗你。 – bash0r

+0

是的,这是我的意思是关于丑陋的逻辑,但你已经做得很好,所以我会接受这是最好的方式来做到这一点。我希望斯卡拉神灵正在倾听;-) – pferrel

0

您可以将逻辑提取到单独的case class,其中有zeroempty状态。

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) 
} 

下面是该休息:

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) 
} 

现在,所有你需要更新是空的状态,并完成。你甚至可以得到一个免费的Monoid。

+0

@KevinMeredith是的,我同意,在那里键入的太快。 – flavian

+0

但这并没有解决问题,它只是移动它。问题是,似乎没有办法在Scala中表示,如果'minPar == None'我想使用par的默认值,无论它们是什么。换句话说,我正在寻找的解决方案不包含“-1”或“false”。我认为可能有一个特殊的值,说:“使用被调用的函数的默认值”或一种功能性的方式来隐藏任何情况下的逻辑,因为这似乎经常出现在使用Scala库时。 – pferrel

+0

@pferrel更新,希望我不会错过任何东西,但这应该解决您的问题。 – flavian