是否可以/应该在 Scala 中添加/创建从 T 到 Option[T] 的隐式转换?

发布于 2024-08-11 00:55:30 字数 208 浏览 11 评论 0原文

这是一个让事情变得更高效的机会吗(对于程序员来说):我发现将东西包装在 Some 中有点烦人,例如 Some(5) 。像这样的事情怎么样:

implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)

Is this an opportunity to make things a bit more efficient (for the prorammer): I find it gets a bit tiresome having to wrap things in Some, e.g. Some(5). What about something like this:

implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)

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

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

发布评论

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

评论(6

七颜 2024-08-18 00:55:30

你会失去一些类型安全性并可能导致混乱。
例如:

  val iThinkThisIsAList = 2 
  for (i <- iThinkThisIsAList) yield { i + 1 }

我(无论出于何种原因)认为我有一个列表,当我迭代它时它没有被编译器捕获,因为它被自动转换为 Option[Int]。

我应该补充一点,我认为这是显式导入的一个很好的隐式,只是可能不是全局默认值。

You would lose some type safety and possibly cause confusion.
For example:

  val iThinkThisIsAList = 2 
  for (i <- iThinkThisIsAList) yield { i + 1 }

I (for whatever reason) thought I had a list, and it didn't get caught by the compiler when I iterated over it because it was auto-converted to an Option[Int].

I should add that I think this is a great implicit to have explicitly imported, just probably not a global default.

梦幻的心爱 2024-08-18 00:55:30

请注意,您可以使用 显式隐式 模式,这样可以避免混淆并保留代码同时简洁。

我所说的显式隐式的意思是,您可以转换为包装器对象,而不是直接从 TOption[T] 转换,该包装器对象提供了执行以下操作的方法:从 TOption[T] 的转换。

class Optionable[T <: AnyRef](value: T) {
  def toOption: Option[T] = if ( value == null ) None else Some(value)
}

implicit def anyRefToOptionable[T <: AnyRef](value: T) = new Optionable(value)

...我可能会找到一个比 Optionable 更好的名称,但现在您可以编写如下代码:

val x: String = "foo"
x.toOption // Some("foo")

val y: String = null
x.toOption // None

我相信这种方式是完全透明的,有助于理解编写的代码 - 消除所有检查以一种很好的方式为 null 。

请注意 T <: AnyRef - 您应该只对允许 null 值的类型执行此隐式转换,根据定义,这些值是引用类型。

Note that you could use the explicit implicit pattern which would avoid confusion and keep code terse at the same time.

What I mean by explicit implicit is rather than have a direct conversion from T to Option[T] you could have a conversion to a wrapper object which provides the means to do the conversion from T to Option[T].

class Optionable[T <: AnyRef](value: T) {
  def toOption: Option[T] = if ( value == null ) None else Some(value)
}

implicit def anyRefToOptionable[T <: AnyRef](value: T) = new Optionable(value)

... I might find a better name for it than Optionable, but now you can write code like:

val x: String = "foo"
x.toOption // Some("foo")

val y: String = null
x.toOption // None

I believe that this way is fully transparent and aids in the understanding of the written code - eliminating all checks for null in a nice way.

Note the T <: AnyRef - you should only do this implicit conversion for types that allow null values, which by definition are reference types.

浊酒尽余欢 2024-08-18 00:55:30

隐式转换的一般准则如下:

  • 当您需要向类型添加成员时(“开放类”;又名“拉皮条我的库”模式),转换为新类型,该类型扩展 AnyRef 并且仅定义您需要的成员。
  • 当您需要“更正”继承层次结构时。因此,您有一些类型A,它应该具有子类B,但由于某种原因没有。在这种情况下,您可以定义从 AB 的隐式转换。

这些是唯一适合定义隐式转换的情况。任何其他转换都会很快遇到类型安全和正确性问题。

T 扩展 Option[T] 确实没有任何意义,显然转换的目的不仅仅是添加成员。因此,这种转换是不可取的。

The general guidelines for implicit conversions are as follows:

  • When you need to add members to a type (a la "open classes"; aka the "pimp my library" pattern), convert to a new type which extends AnyRef and which only defines the members you need.
  • When you need to "correct" an inheritance hierarchy. Thus, you have some type A which should have subclassed B, but didn't for some reason. In that case, you can define an implicit conversion from A to B.

These are the only cases where it is appropriate to define an implicit conversion. Any other conversion runs into type safety and correctness issues in a hurry.

It really doesn't make any sense for T to extend Option[T], and obviously the purpose of the conversion is not simply the addition of members. Thus, such a conversion would be inadvisable.

浮光之海 2024-08-18 00:55:30

当其他开发人员阅读您的代码时,这似乎会让他们感到困惑。

一般来说,隐式似乎可以帮助从一个对象转换到另一个对象,以消除可能使代码混乱的混乱转换代码,但是,如果我有一些变量并且它以某种方式变成了一些 那么这似乎很麻烦。

您可能想要放置一些显示它正在使用的代码,看看它会多么令人困惑。

It would seem that this could be confusing to other developers, as they read your code.

Generally, it seems, implicit works to help cast from one object to another, to cut out confusing casting code that can clutter code, but, if I have some variable and it somehow becomes a Some then that would seem to be bothersome.

You may want to put some code showing it being used, to see how confusing it would be.

时光是把杀猪刀 2024-08-18 00:55:30

您还可以尝试重载该方法:

def having(key:String) = having(key, None)

def having(key:String, default:String) = having(key, Some(default))

def having(key: String, default: Option[String]=Option.empty) : Create = {
  keys += ( (key, default) )
  this
}

You could also try to overload the method :

def having(key:String) = having(key, None)

def having(key:String, default:String) = having(key, Some(default))

def having(key: String, default: Option[String]=Option.empty) : Create = {
  keys += ( (key, default) )
  this
}
罪歌 2024-08-18 00:55:30

这对我来说看起来不错,但它可能不适用于原始 T (它不能为空)。我想非专用泛型总是会得到盒装原语,所以可能没问题。

That looks good to me, except it may not work for a primitive T (which can't be null). I guess a non-specialized generic always gets boxed primitives, so probably it's fine.

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