Scala中非布尔类型的逻辑运算符
发布时间:2020-12-16 18:11:55 所属栏目:安全 来源:网络整理
导读:我喜欢可以使用布尔运算符编写的简洁代码,而不是像Lisp,Python或 JavaScript这样的(通常是动态的)语言中的条件,就像典型的: x = someString or "default string" VS if someString: x = someStringelse: x = "default string" 在Scala中,我想到了类似的东西
我喜欢可以使用布尔运算符编写的简洁代码,而不是像Lisp,Python或
JavaScript这样的(通常是动态的)语言中的条件,就像典型的:
x = someString or "default string" VS if someString: x = someString else: x = "default string" 在Scala中,我想到了类似的东西: object Helpers { case class NonBooleanLogic[A](x: A) { // I could overload the default && and || // but I think new operators are less 'surprise prone' def |||(y: => A)(implicit booleanConversion: A => Boolean) = if (x) x else y def &&&(y: => A)(implicit booleanConversion: A => Boolean) = if (!x) x else y } implicit def num2bool(n : Int) = n != 0 implicit def seq2bool(s : Seq[Any]) = !s.isEmpty implicit def any2bool(x : Any) = x != null implicit def asNonBoolean[T](x: T) = NonBooleanLogic(x) } object SandBox { // some tests cases... 1 ||| 2 //> res2: Int = 1 val x : String = null //> x : String = null x ||| "hello" //> res3: String = hello //works promoting 2 to Float 1.0 &&& 2 //> res4: Double = 2.0 //this doesn't work :( 1 &&& 2.0 } 但是出现了两个问题: >如何使它适用于具有共同祖先而不恢复为任何类型的类型? 解决方法
我将坚持使用Option [T] …这对Scala更为惯用.我也经常在验证中使用它,例如:在Web表单中,有时不应将空字符串视为有效的用户输入.
例如,如果您认为零长度(“”)的null String / String为false,则任何空引用也为false,并且任何数字零都为false,您可以编写以下隐式defs. object MyOptionConverter { implicit def toOption(any: AnyRef) = Option(any) implicit def toOption(str: String) = { Option(str).filter(_.length > 0) } implicit def toOption[T](value: T)(implicit num: Numeric[T]): Option[T] = { Option(value).filter(_ != 0) } } import MyOptionConverter._ println(1 getOrElse 10) // 1 println(5.5 getOrElse 20) // 5.5 println(0 getOrElse 30) // 30 println(0.0 getOrElse 40) // 40 println((null: String) getOrElse "Hello") // Hello println((null: AnyRef) getOrElse "No object") // No object println("World" getOrElse "Hello") 如果您确实需要定义自己的运算符,请将其转换为包含Option [T]的类,并向其添加运算符. object MyOptionConverter { class MyBooleanLogic[T](x: Option[T],origin: T) { def |||(defaultValue: T) = x.getOrElse(defaultValue) def &&&(defaultValue: T) = x.isDefined match { case true => defaultValue case false => origin } } implicit def toOption(any: AnyRef) = { new MyBooleanLogic(Option(any),any) } implicit def toOption(str: String) = { new MyBooleanLogic(Option(str).filter(_.length > 0),str) } implicit def toOption[T](value: T)(implicit num: Numeric[T])= { new MyBooleanLogic(Option(value).filter(_ != 0),value) } } import MyOptionConverter._ println(1 ||| 10) // 1 println(5.5 ||| 20) // 5.5 println(0 ||| 30) // 30 println(0.0 ||| 40) // 40 println((null: String) ||| "Hello") // Hello println((null: AnyRef) ||| "No object") // No object println("World" ||| "Hello") println(1 &&& 10) // 10 println(5.5 &&& 20) // 20 println(0 &&& 30) // 0 println(0.0 &&& 40) // 0.0 println((null: String) &&& "Hello") // null println((null: AnyRef) &&& "No object") // null println("World" &&& "Hello") // Hello (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |