是否可以在 Scala 中对提取器(不应用)的参数使用隐式转换?

发布于 2024-08-13 11:20:50 字数 1654 浏览 2 评论 0原文

我创建了一个名为 CaseInsensitive 的类,它包装了一个字符串(请参阅 实现一个在 Scala 中进行不区分大小写比较的字符串类)。

我创建了一个 case 类,它有一个 CaseInsensitive 类型的成员变量,因此它有一个默认的 unapply 方法,该方法提取 CaseInsensitive 类型的变量,但我希望像这样使用它:

case class PropertyKey( val name : CaseInsensitive )

val foo = new PropertyKey("foo")
val result = foo match {
  case PropertyKey("foo") => true
  case _ => false
}

此代码无法编译:(在提取器行,而不是构造函数行)

type mismatch;
 found   : java.lang.String("foo")
 required: com.acme.CaseInsensitive 

但我认为我从 String 到 CaseInsensitive 的隐式转换将使这个能够编译,而不是我必须输入更详细的内容:

case class PropertyKey( val name : CaseInsensitive )

val foo = new PropertyKey("foo")
val result = foo match {
  case PropertyKey(CaseInsensitive("foo")) => true
  case _ => false
}

这是 CaseInsensitive 的实现:

/** Used to enable us to easily index objects by string, case insensitive
 * 
 * Note: this class preserve the case of your string!
 */
case class CaseInsensitive ( val _s : String ) extends Proxy {
  require( _s != null)

  val self = _s.toLowerCase
  override def toString = _s

  def i = this // convenience implicit conversion
}

object CaseInsensitive {
  implicit def CaseInsensitive2String(c : CaseInsensitive) = if ( c == null ) null else c._s
  implicit def StringToCaseInsensitive(s : String) = CaseInsensitive(s)

  def fromString( s : String ) = s match {
    case null => None
    case _ => Some(CaseInsensitive(s))
  }
}

I have created a class called CaseInsensitive which wraps a string (see Implementing a string class that does case insensitive comparisions in Scala).

I've created a case class which has a member variable of type CaseInsensitive, so it gets a default unapply method, which extracts a variable of type CaseInsensitive, but I was hoping to use it like this:

case class PropertyKey( val name : CaseInsensitive )

val foo = new PropertyKey("foo")
val result = foo match {
  case PropertyKey("foo") => true
  case _ => false
}

This code fails to compile: (on the extractor line, not the constructor line)

type mismatch;
 found   : java.lang.String("foo")
 required: com.acme.CaseInsensitive 

But I thought my implicit conversions from String to CaseInsensitive would enable this to compile, rather than me having to type the more verbose:

case class PropertyKey( val name : CaseInsensitive )

val foo = new PropertyKey("foo")
val result = foo match {
  case PropertyKey(CaseInsensitive("foo")) => true
  case _ => false
}

Here is the implementation of CaseInsensitive:

/** Used to enable us to easily index objects by string, case insensitive
 * 
 * Note: this class preserve the case of your string!
 */
case class CaseInsensitive ( val _s : String ) extends Proxy {
  require( _s != null)

  val self = _s.toLowerCase
  override def toString = _s

  def i = this // convenience implicit conversion
}

object CaseInsensitive {
  implicit def CaseInsensitive2String(c : CaseInsensitive) = if ( c == null ) null else c._s
  implicit def StringToCaseInsensitive(s : String) = CaseInsensitive(s)

  def fromString( s : String ) = s match {
    case null => None
    case _ => Some(CaseInsensitive(s))
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

如歌彻婉言 2024-08-20 11:20:50

您始终可以定义一个方便的提取器并导入它(随意使用更短的名称):

object PropertyKeyCI {
  def unapply(p: PropertyKey): Option[String] = Some(p.name.self)
}

然后,提取是:(

  val foo = new PropertyKey("foo")
  val result = foo match {
    case PropertyKeyCI("foo") => true
    case _ => false
  }

错误语义警报)

尽管请注意,这对于 PropertyKeyCI("Foo") 来说会匹配为 false,因为您的“CaseInsensitive” " 类实际上是一个“LowerCase”类。我这样说是因为我很难想象 unapply() 方法所需的行为是什么。从您的案例类默认值中,您将返回原始(非小写)字符串的 Option[String],这给出了这种不直观的行为:

  // result == false !!!!
  val foo = new CaseInsensitive("Foo")
  val result = foo match {
    case CaseInsensitive("foo") => true
    case _ => false
  }
  val CaseInsensitive(s) = "aBcDeF"
  assertFalse(s == "abcdef")

Awwww.... 扔掉它。只需使用DOS即可。

You could always define a convenience extractor and import it (feel free to use a shorter name):

object PropertyKeyCI {
  def unapply(p: PropertyKey): Option[String] = Some(p.name.self)
}

Then, extraction is:

  val foo = new PropertyKey("foo")
  val result = foo match {
    case PropertyKeyCI("foo") => true
    case _ => false
  }

(Bad Semantics Alert)

Although note that this would match as false for PropertyKeyCI("Foo"), because your "CaseInsensitive" class is really a "LowerCase" class. I say this because it is hard for me to imagine what the desired behavior would be for the unapply() method otherwise. From your case class default, you are returning an Option[String] of the original (unlowercased) string, which gives this unintuitive behavior:

  // result == false !!!!
  val foo = new CaseInsensitive("Foo")
  val result = foo match {
    case CaseInsensitive("foo") => true
    case _ => false
  }
  val CaseInsensitive(s) = "aBcDeF"
  assertFalse(s == "abcdef")

Awwww.... toss it. Just use DOS.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文