在红宝石中,可以这样做:
first ||= number
和 first 只有在 nil
时才会获得数字的值如何在scala中做类似的事情?
到目前为止,我已经想出了这个并且看起来不像红宝石那么好。
var first: Option[Int] = None
...
first = if (first == None) Option(number) else first
// or
first = Some(first.getOrElse(number))
答案 0 :(得分:5)
有一个scalaz
运算符:
import scalaz._, Scalaz._
none[Int] <+> 1.some
// Some(1)
2.some <+> 1.some
// Some(2)
您可以使用a <+>= b
代替a = a <+> b
:
var i = none[Int] // i == None
i <+>= 1.some // i == Some(1)
i <+>= 2.some // i == Some(1)
另请参阅scalaz cheatsheet中的加[F [_]] 。
Option
plus
implemented为orElse
。
对于集合(List
,Vector
,Stream
等),Plus
实现为append
:
Vector(1, 2) <+> Vector(3, 4)
// Vector(1, 2, 3, 4)
我找不到按照你想要的方式组合Option[T]
和T
的方法,但你可以这样编写这样的方法:
implicit class PlusT[T, M[_]: Plus : Applicative](m: M[T]) {
def ?+?(t: T) = m <+> t.point[M]
}
none[Int] ?+? 1
// Some(1)
2.some ?+? 1
// Some(2)
var i = none[Int] // i == None
i ?+?= 1 // i == Some(1)
i ?+?= 2 // i == Some(1)
您可以将此方法重命名为||
并像||=
一样使用它,就像在Ruby
中一样,但此名称可能会让其他开发者感到困惑 - 已经有方法||
Boolean
。
答案 1 :(得分:3)
这不是最佳做法或任何事情,但这里可以做类似的事情:
scala> implicit class RubyFriend[T](val value: Option[T]) extends AnyVal {
| def ||=(alt: T): Option[T] = value orElse Some(alt)
| }
defined class RubyFriend
scala> var something: Option[Int] = None
something: Option[Int] = None
scala> something = something ||= 5
something: Option[Int] = Some(5)
scala> something ||= 4
res11: Option[Int] = Some(5)
scala> (None: Option[Int]) ||= 3
res12: Option[Int] = Some(3)
我们创建了从Option
到RubyFriend
的隐式转换,其中||=
方法。这是一个皮条客我的图书馆模式。据我所知,在Scala赋值中它无法真正分配给原始变量的唯一区别是不能重载。
总体上尽量避免Scala中的变种。
这是另一种尝试,使其更像Ruby:
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> implicit class RubyFriend[T](var value: Option[T]) {
| def ||=(alt: T): Unit = value = value orElse Some(alt)
| }
defined class RubyFriend
scala> implicit def ruby2Option[T](smth: RubyFriend[T]): Option[T] = smth.value
ruby2Option: [T](smth: RubyFriend[T])Option[T]
scala> var ropt: RubyFriend[Int] = None
ropt: RubyFriend[Int] = RubyFriend@2d483fef
scala> ropt.value
res0: Option[Int] = None
scala> val opt: Option[Int] = ropt
opt: Option[Int] = None
scala> ropt ||= 6
scala> ropt.value
res2: Option[Int] = Some(6)
scala> val opt: Option[Int] = ropt
opt: Option[Int] = Some(6)
scala> ropt ||= 7
scala> ropt.value
res4: Option[Int] = Some(6)
这使得包装类围绕Option
并且隐式地来回转换。同时,可选值显示为可变字段(yikes)。
这两个例子只是为了展示Scala中可能的不是一个好方法:)。
@senia建议的第一个例子的“改进”:
scala> implicit class RubyFriend[T](val value: Option[T]) extends AnyVal {
| def ||(alt: T): Option[T] = value orElse Some(alt)
| }
defined class RubyFriend
scala> var something: Option[Int] = None
something: Option[Int] = None
scala> something ||= 5
scala> something
res1: Option[Int] = Some(5)
scala> something ||= 6
scala> something
res3: Option[Int] = Some(5)
答案 2 :(得分:3)
我不知道为什么其他海报删除了他的答案,但我会采取评论中建议的方法:
first = first orElse Some(number)