在 Scala 中是否可以用相反的方式进行柯里化?

发布于 2024-08-14 16:01:23 字数 361 浏览 7 评论 0原文

让我们假设这个函数:

def autoClosing(f: {def close();})(t: =>Unit) = {
    t
    f.close()
}

和这个片段:

val a = autoClosing(new X)(_)
a {
 println("before close")
}

是否可以柯里化第一部分?像这样:

val a = autoClosing(_) { println("before close") }

这样我就可以发送应该执行关闭的对象,并在它们上执行相同的块?

Let's assume this function:

def autoClosing(f: {def close();})(t: =>Unit) = {
    t
    f.close()
}

and this snippet:

val a = autoClosing(new X)(_)
a {
 println("before close")
}

is it possible to curry the first part? Something like:

val a = autoClosing(_) { println("before close") }

so that I could send the objects on which close should be performed, and have the same block executed on them?

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

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

发布评论

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

评论(3

小巷里的女流氓 2024-08-21 16:01:23

是的,只要您给出占位符字符的类型,您给出的代码片段就可以工作。

因此,您正在寻找的代码是:

val a = autoClosing(_: {def close();}) { println("before close") }

它可以按预期编译和工作:)。

一些注意事项:

  • 如果为具有 close 方法的 AnyRef 类型定义类型别名,例如 type Closeable = AnyRef { def close()},或适当的接口。
  • 代码片段 autoClosing(_: Closeable){ ... } 实际上相当于以下扩展的匿名函数: c: Closeable =>自动关闭(c){...}。通配符只是部分应用函数的简写。您需要提供 _ 的类型,因为类型推断器在这种情况下无法推断类型。

希望有帮助,

-- Flaviu Cipcigan

Yes, the snippet you have given works, as long as you give the type of the placeholder character.

Therefore, the code you are looking for is:

val a = autoClosing(_: {def close();}) { println("before close") }

which compiles and works as expected :).

A couple of notes:

  • You can make your life easier if you define a type alias for an AnyRef type having a close method, something like type Closeable = AnyRef {def close()}, or an appropriate interface.
  • The code snippet autoClosing(_: Closeable){ ... } is actually equivalent to the following expanded anonymous function: c: Closeable => autoClosing(c){ ... }. The wildcard character is just shorthand for a partially applied function. You need to give the type of the _ as the type inferer unfortunately cannot infer the type in this case.

Hope it helps,

-- Flaviu Cipcigan

书信已泛黄 2024-08-21 16:01:23

或者,您可以翻转参数:

def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1)

在您的情况下:

val a = flip(autoClosing){ println("before close") }

编辑:
我添加了一些大括号来帮助人类解析器:

def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = {
    x1 => (x2 => f(x2)(x1))
}

Flip 将函数 (A1 => (A2 => B)) 转换为 (A2 => (A1 => B))

scala> def x(x1 : Int)(x2 : Long) = 1.0 * x1 / x2
x: (Int)(Long)Double

scala> val f = flip(x)
f: (Long) => (Int) => Double = <function>

scala> val g = f(1)
g: (Int) => Double = <function>

scala> val h = g(2)
h: Double = 2.0

scala> x(1)(2)
res0: Double = 0.5

Alternatively you can flip the parameters:

def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1)

In your case:

val a = flip(autoClosing){ println("before close") }

Edit:
I've added some braces to help the human parser:

def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = {
    x1 => (x2 => f(x2)(x1))
}

Flip converts a function (A1 => (A2 => B)) to (A2 => (A1 => B)).

scala> def x(x1 : Int)(x2 : Long) = 1.0 * x1 / x2
x: (Int)(Long)Double

scala> val f = flip(x)
f: (Long) => (Int) => Double = <function>

scala> val g = f(1)
g: (Int) => Double = <function>

scala> val h = g(2)
h: Double = 2.0

scala> x(1)(2)
res0: Double = 0.5
征棹 2024-08-21 16:01:23

我很高兴看到现在有这么多人回答 Scala 问题。然而,这确实让我更难想出一些东西。这是 Flaviu解决方案中采用另一种方法

val a: {def close();} => Unit = autoClosing(_) { println("before close") }

当然,正确的解决方案是以与您将如何使用它兼容的方式定义 autoClosing。

I'm happy to see so many people answering Scala questions nowadays. It does make it harder for me to come up with something, however. Here's an alternative to Flaviu's solution.

val a: {def close();} => Unit = autoClosing(_) { println("before close") }

Of course, the proper solution is to define autoClosing in a way compatible with how you are going to use it.

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