为什么擦除会使函数类型的实现变得复杂?

发布于 2024-12-04 23:50:17 字数 566 浏览 0 评论 0原文

我从对 Neal Gafter 的采访中读到:

“例如,使用 Erasure 作为泛型的一部分,向编程语言添加函数类型要困难得多。”

编辑: 我遇到类似声明的另一个地方是 Brian Goetz 的 Lambda Dev 邮件列表中的消息,他说当 lambda 只是带有语法糖的匿名类时,它们更容易处理:

但我对函数类型的反对并不是因为我不喜欢函数类型——我喜欢函数类型——而是函数类型与 Java 类型系统的现有方面(擦除)发生了激烈的冲突。擦除的函数类型是两全其美的。所以我们从设计中删除了它。

谁能解释这些说法?为什么我需要 lambda 的运行时类型信息?

I read from an interview with Neal Gafter:

"For example, adding function types to the programming language is much more difficult with Erasure as part of Generics."

EDIT:
Another place where I've met similar statement was in Brian Goetz's message in Lambda Dev mailing list, where he says that lambdas are easier to handle when they are just anonymous classes with syntactic sugar:

But my objection to function types was not that I don't like function types -- I love function types -- but that function types fought badly with an existing aspect of the Java type system, erasure. Erased function types are the worst of both worlds. So we removed this from the design.

Can anyone explain these statements? Why would I need runtime type information with lambdas?

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

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

发布评论

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

评论(4

暗喜 2024-12-11 23:50:17

我的理解是,他们认为,由于擦除,走“函数类型”的路会很混乱,例如 C# 中的委托,他们只能使用lambda 表达式,这只是单一抽象方法类语法的简化。

C# 中的委托:(

public delegate void DoSomethingDelegate(Object param1, Object param2);
...
//now assign some method to the function type variable (delegate)
DoSomethingDelegate f = DoSomething;
f(new Object(), new Object());

这里是另一个示例
http://geekswithblogs.net/joycsharp/archive /2008/02/15/simple-c-delegate-sample.aspx

他们在 Lambda 项目文档中提出的一个论点:

泛型类型被删除,这会暴露其他地方
开发人员面临被删除的风险。例如,它不会是
可以重载方法 m(T->U) 和 m(X->Y),这将是
令人困惑。

第 2 节:
http://cr.openjdk.java.net/~briangoetz /lambda/lambda-state-3.html

(最终的 lambda 表达式语法与上述文档略有不同:
http://mail.openjdk.java.net/pipermail /lambda-dev/2011-September/003936.html

(x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); }

总而言之,我最好的理解是,只有一部分语法内容实际上可以是 用过的。
Neal Gafter 最有可能的意思是,无法使用委托将使标准 API 更难以适应函数式风格,而不是 javac/JVM 更新将更难完成。

如果有人比我更理解这一点,我会很乐意阅读他的帐户。

The way I understand it, is that they decided that thanks to erasure it would be messy to go the way of 'function types', e.g. delegates in C# and they only could use lambda expressions, which is just a simplification of single abstract method class syntax.

Delegates in C#:

public delegate void DoSomethingDelegate(Object param1, Object param2);
...
//now assign some method to the function type variable (delegate)
DoSomethingDelegate f = DoSomething;
f(new Object(), new Object());

(another sample here
http://geekswithblogs.net/joycsharp/archive/2008/02/15/simple-c-delegate-sample.aspx)

One argument they put forward in Project Lambda docs:

Generic types are erased, which would expose additional places where
developers are exposed to erasure. For example, it would not be
possible to overload methods m(T->U) and m(X->Y), which would be
confusing.

section 2 in:
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-state-3.html

(The final lambda expressions syntax will be a bit different from the above document:
http://mail.openjdk.java.net/pipermail/lambda-dev/2011-September/003936.html)

(x, y) => { System.out.printf("%d + %d = %d%n", x, y, x+y); }

All in all, my best understanding is that only a part of syntax stuff that could, actually will be used.
What Neal Gafter most likely meant was that not being able to use delegates will make standard APIs more difficult to adjust to functional style, rather than that javac/JVM update would be more difficult to be done.

If someone understands this better than me, I will be happy to read his account.

迷路的信 2024-12-11 23:50:17

Goetz 在 State of the Lambda 第四版中扩展了推理。< /a>:

函数类型的替代(或补充)方法,
根据一些早期提案的建议,应该引入一种新的、
结构功能类型。类似“来自 String 和 an 的函数”的类型
对象到 int" 可以表示为 (String,Object)->int。这
至少目前,由于几个原因,这个想法被考虑并被拒绝了
缺点:

  • 这会增加类型系统的复杂性,并进一步混合结构类型和名义类型。
  • 这将导致库风格的分歧——一些库将继续使用回调接口,而另一些库将使用结构
    函数类型。
  • 语法可能不太好用,尤其是在包含已检查异常时。
  • 每种不同的函数类型不太可能有运行时表示,这意味着开发人员将进一步接触到
    并受到擦除的限制。例如,这是不可能的(也许
    令人惊讶的是)重载方法 m(T->U) 和 m(X->Y)。

所以,我们反而选择走“用你所用”的道路
知道”——因为现有的库广泛使用函数式接口,
我们整理并利用这种模式。

为了说明这一点,以下是 Java SE 7 中的一些函数式接口
非常适合与新的语言功能一起使用;
下面的示例说明了其中一些示例的用法。

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.util.Comparator
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener
  • ...

请注意,擦除只是考虑因素之一。一般来说,Java lambda 方法与 Scala 的方向不同,而不仅仅是在类型问题上。它非常以 Java 为中心。

Goetz expands on the reasoning in State of the Lambda 4th ed.:

An alternative (or complementary) approach to function types,
suggested by some early proposals, would have been to introduce a new,
structural function type. A type like "function from a String and an
Object to an int" might be expressed as (String,Object)->int. This
idea was considered and rejected, at least for now, due to several
disadvantages:

  • It would add complexity to the type system and further mix structural and nominal types.
  • It would lead to a divergence of library styles—some libraries would continue to use callback interfaces, while others would use structural
    function types.
  • The syntax could be unweildy, especially when checked exceptions were included.
  • It is unlikely that there would be a runtime representation for each distinct function type, meaning developers would be further exposed to
    and limited by erasure. For example, it would not be possible (perhaps
    surprisingly) to overload methods m(T->U) and m(X->Y).

So, we have instead chosen to take the path of "use what you
know"—since existing libraries use functional interfaces extensively,
we codify and leverage this pattern.

To illustrate, here are some of the functional interfaces in Java SE 7
that are well-suited for being used with the new language features;
the examples that follow illustrate the use of a few of them.

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.util.Comparator
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener
  • ...

Note that erasure is just one of the considerations. In general, the Java lambda approach goes in a different direction from Scala, not just on the typed question. It's very Java-centric.

半衬遮猫 2024-12-11 23:50:17

也许是因为您真正想要的是类型 Function,它使用返回类型和一些参数类型序列进行参数化。但由于擦除,你不能有像 P... 这样的构造,因为它只能变成 Object[],它太松散而没有多大用处在运行时。

这纯粹是猜测。我不是一个类型理论家;我是一个类型理论家。我什至都没在电视上玩过。

Maybe because what you'd really want would be a type Function<R, P...>, which is parameterised with a return type and some sequence of parameter types. But because of erasure, you can't have a construct like P..., because it could only turn into Object[], which is too loose to be much use at runtime.

This is pure speculation. I am not a type theorist; i haven't even played one on TV.

ぇ气 2024-12-11 23:50:17

我认为他在那句话中的意思是,在运行时Java无法区分这两个函数定义之间的区别:

void doIt(List<String> strings) {...}
void doIt(List<Integer> ints) {...}

因为在编译时,有关List包含的数据类型的信息被删除,因此运行时环境将无法区分以确定您要调用哪个函数。

尝试在同一个类中编译这两个方法将引发以下异常:

doIt(List<String>) clashes with doIt(List<Integer); both methods have the same erasure

I think what he means in that statement is that at runtime Java cannot tell the difference between these two function definitions:

void doIt(List<String> strings) {...}
void doIt(List<Integer> ints) {...}

Because at compile time, the information about what type of data the List contains is erased, so the runtime environment wouldn't be able to determine which function you wanted to call.

Trying to compile both of these methods in the same class will throw the following exception:

doIt(List<String>) clashes with doIt(List<Integer); both methods have the same erasure
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文