加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读