Ruby 中 ActiveSupport 的 Object.try 的 Scala 等价物

Scala equivalent for ActiveSupport's Object.try in Ruby

try method 是核心 Ruby 的常见扩展。例如,它在 Rails 中默认可用。 try 仅当对象不是 nil(Ruby 的 null)时才在对象上执行方法或代码块。它的用法分为三种:

  1. 在非nil对象上调用方法并返回结果:
    customer_or_nil.try(:save).

  2. 如果到目前为止的结果不是 nil:
    ,则在表达式中链接任意代码块 obj.try { |non_nil_obj| do_something(non_nil_obj) }

  3. (2) 的扩展不用于可选处理,而是作为一种继续链式表达式的方式,其中步骤 n+1 中的方法需要一个参数,该参数必须根据步骤 n:
    data.analyze.try { |result| result.compress(optimal_settings(result)) }.save

我对 (3) 的 Scala 等价物或替代的 Scala 习语特别感兴趣,例如,此代码与 Apache Spark 的 DataFrame:

相关
val df = ctx.sql("select * from my_table")
df.
  repartition(max(1, df.rdd.partitions.size / 4)).
  saveAsTable("repartitioned_table")

重构为如下所示(使用 Ruby 语法)

ctx.
  sql("select * from my_table").
  try { |df| df.repartition(max(1, df.rdd.partitions.size / 4)) }.
  saveAsTable("repartitioned_table")

重构的目标是通过维护单个方法链来提高可读性,并通过将 df 范围严格限定在链中绝对需要的步骤来减少范围污染。

注: 我对讨论使用 Option 进行可选处理的优缺点特别不感兴趣,因为这不是 [= 的主要用例14=]这个问题是关注的。

标准库中没有,但是等价于3好写(try是关键字,所以改名为apapply的缩写)):

implicit class TryOp[A](x: A) {
  def ap[B](f: A => B): B = f(x)
}

ctx.
  sql("select * from my_table").
  ap { df => df.repartition(max(1, df.rdd.partitions.size / 4)) }.
  saveAsTable("repartitioned_table")