Programming languages 如何用lambda演算术语定义匿名函数(或者我如何说某些语言支持匿名函数)?

Programming languages 如何用lambda演算术语定义匿名函数(或者我如何说某些语言支持匿名函数)?,programming-languages,lambda,computer-science,Programming Languages,Lambda,Computer Science,java是否支持当前版本的6个lambda表达式或“匿名函数”?在java中有什么我做不到的,而在支持lambda表达式的编程语言中我做不到的?我知道java是图灵完备的,所以您可以在其中“做任何事情” 为什么匿名内部类包装函数不能表示lambda演算中定义的函数 什么是真正的匿名函数?您如何说某些语言支持匿名函数?C#中的lambda表达式和Java中的匿名内部类之间的一个重要区别是,内部类中引用的任何局部变量都由值捕获-这就是变量必须是最终变量的原因。该变量的值在构造时复制到内部类中 在C#

java是否支持当前版本的6个lambda表达式或“匿名函数”?在java中有什么我做不到的,而在支持lambda表达式的编程语言中我做不到的?我知道java是图灵完备的,所以您可以在其中“做任何事情”

为什么匿名内部类包装函数不能表示lambda演算中定义的函数


什么是真正的匿名函数?您如何说某些语言支持匿名函数?

C#中的lambda表达式和Java中的匿名内部类之间的一个重要区别是,内部类中引用的任何局部变量都由值捕获-这就是变量必须是最终变量的原因。该变量的值在构造时复制到内部类中

在C#中,变量可以通过lambda表达式或方法中的其他代码进行更改,这些更改也可以在两个位置看到

您可以在Java中通过将原始变量包装在可变包装器中(例如,一个单元素数组)并使包装器变量成为最终变量来模拟这一点。这是一个相当糟糕的黑客

在IMO中使用匿名内部类的最大问题是过于冗长——声明要扩展的类,然后声明要重写的方法等等


有关闭包的更多信息,特别是在这方面比较Java和C,请参见。

正如我在上面的评论中所暗示的,问题实际上取决于如何准确定义“支持”。在您的问题中,您已经提到Java是图灵完备的,因此Java“支持”(对于“支持”的某些定义)所有其他编程语言支持的东西

Java确实支持匿名函数:只需在Java中为λ演算编写一个解释器,并将匿名函数作为字符串传入即可

然而,我发现使用匿名函数需要做太多的工作。因此,对我来说,有趣的问题不是Java是否支持匿名函数,而是当我想使用匿名函数时,Java是否支持我。IOW:Java使匿名函数的使用变得容易了吗?它指导我吗?它帮助我吗

让我们做一个简单的实验:实现
map
函数,并使用它通过
1
增加列表中的每个元素
[1,2,3,4,5]

哈斯克尔 以下是Haskell中的
morph
(我将调用该函数,以避免与现有的内置
map
函数冲突)的实现方式:

morph _ []     = []
morph f (x:xs) = f x : morph f xs
就这些。简短而甜蜜:用任何东西变形空列表就是空列表,而用至少一个元素变形列表就是将变形函数应用于第一个元素,并将其与变形列表其余部分的结果连接起来

如您所见,编写一个接受函数作为参数的函数非常简单,非常轻量级

假设我们有一个列表
l

l = [1, 2, 3, 4, 5]
我们现在可以这样调用变形:

morph (\x -> 1 + x) l
同样,将匿名函数传递给高阶函数非常简单,非常轻量级

它看起来几乎像λ-微积分。事实上,如果您使用Haskell IDE、具有Haskell模式的文本编辑器或Haskell pretty打印机,它将实际显示如下:

morph (λx → 1 + x) l
(int x) -> x + 1
(int x) -> x + 1
如果我们使用运算符部分,它会变得更容易,允许我们传递部分应用的运算符:

morph (1+) l
或者,我们可以传递预定义的
succ
函数,该函数返回整数的后续值:

morph succ l
虽然这当然不是一个匿名函数,但它是一个命名函数

斯卡拉 在Scala中,它看起来非常相似。主要区别在于Scala的类型系统比Haskell的更复杂,因此需要更多的类型注释:

def morph[A, B](l: List[A])(f: A => B): List[B] = l match {
  case Nil     => Nil
  case x :: xs => f(x) :: morph(xs)(f)
}
它仍然很轻。基本上,我们所要做的就是将
f
参数声明为
A=>B
类型(即从
A
类型到
B
类型的函数),这实际上是
函数1[A,B]
的语法糖

现在我们只需要我们的列表:

val l = List(1, 2, 3, 4, 5)
(define l '(1 2 3 4 5))
List<Integer> l = Arrays.asList(1, 2, 3, 4, 5);
并对其进行变形:

morph(l) {_ + 1}
这再次利用了Scala的一些语法优势。在匿名函数中,可以省略参数列表;如果每个参数只使用一次,并且按照定义的顺序使用,则可以简单地将它们称为
\uuuu

但即使是完整的形式也没有太重:

morph(l) {(e) => e + 1}
如果我经历了将
morph
作为某个类的实例方法的麻烦,并根据Pimp-My-Library模式定义了从
List
到该类的隐式转换,我甚至可以编写类似的代码

l morph {_ + 1}
计划 当然,Scheme对于匿名函数和高阶函数应该没有问题。这是变形:

(define (morph f l)
    (if (null? l)
        null
        (cons
            (f (first l))
            (morph f (rest l)))))
morph(l, new Function1<Integer, Integer>() {
    @Override public Integer apply(Integer n) {
        return n + 1;
    }
});
以下是我们的清单:

val l = List(1, 2, 3, 4, 5)
(define l '(1 2 3 4 5))
List<Integer> l = Arrays.asList(1, 2, 3, 4, 5);
以及我们的匿名函数用法:

(morph (lambda (e) (+ e 1)) '(1 2 3 4 5))
红宝石 调用它几乎和Scala一样轻量级

l.morph {|e| e + 1 }
通过获取对
1
+
方法的引用,我可以在某种程度上复制Haskell示例中的运算符部分:

l.morph(&1.method(:+))
Ruby还有一个预定义的整数
succ
方法,我们可以使用
Symbol#to_proc
技巧传递:

l.morph(&:succ)
有些人批评Ruby中的块,因为每个方法只能使用一个块,而使用多个函数的方法要难看得多,但实际上并没有那么糟糕。下面是与上面相同的代码,但不使用块:

module Enumerable
  def morph(f)
    [].tap &-> r { each &-> e { r << f.(e) }}
  end
end

l = [1, 2, 3, 4, 5]

l.morph -> e { e + 1 }
l.morph(1.method(:+))
这里主要的干扰是通常丑陋的语法,而不是高阶函数的处理

让我们建立我们的列表(好的,数组):

并调用
morph
函数(实际上,在本例中是一个方法),将匿名函数作为参数传递:

l.morph(function (e) { return e + 1; });
l.morph(e => e + 1);
interface Action1_T                 { void    apply(T       a); }
interface Action1_byte              { void    apply(byte    a); }
interface Action1_short             { void    apply(short   a); }
interface Action1_int               { void    apply(int     a); }
interface Action1_long              { void    apply(long    a); }
interface Action1_float             { void    apply(float   a); }
interface Action1_double            { void    apply(double  a); }
interface Action1_boolean           { void    apply(boolean a); }
interface Action1_char              { void    apply(char    a); }
interface Function1_T_R             { R       apply(T       a); }
interface Function1_T_byte          { byte    apply(T       a); }
interface Function1_T_short         { short   apply(T       a); }
interface Function1_T_int           { int     apply(T       a); }
interface Function1_T_long          { long    apply(T       a); }
interface Function1_T_float         { float   apply(T       a); }
interface Function1_T_double        { double  apply(T       a); }
interface Function1_T_boolean       { boolean apply(T       a); }
interface Function1_T_char          { char    apply(T       a); }
interface Function1_byte_R          { R       apply(byte    a); }
interface Function1_byte_byte       { byte    apply(byte    a); }
interface Function1_byte_short      { short   apply(byte    a); }
interface Function1_byte_int        { int     apply(byte    a); }
interface Function1_byte_long       { long    apply(byte    a); }
interface Function1_byte_float      { float   apply(byte    a); }
interface Function1_byte_double     { double  apply(byte    a); }
interface Function1_byte_boolean    { boolean apply(byte    a); }
interface Function1_byte_char       { char    apply(byte    a); }
interface Function1_short_R         { R       apply(short   a); }
interface Function1_short_byte      { byte    apply(short   a); }
interface Function1_short_short     { short   apply(short   a); }
interface Function1_short_int       { int     apply(short   a); }
interface Function1_short_long      { long    apply(short   a); }
interface Function1_short_float     { float   apply(short   a); }
interface Function1_short_double    { double  apply(short   a); }
interface Function1_short_boolean   { boolean apply(short   a); }
interface Function1_short_char      { char    apply(short   a); }
interface Function1_int_R           { R       apply(int     a); }
interface Function1_int_byte        { byte    apply(int     a); }
interface Function1_int_short       { short   apply(int     a); }
interface Function1_int_int         { int     apply(int     a); }
interface Function1_int_long        { long    apply(int     a); }
interface Function1_int_float       { float   apply(int     a); }
interface Function1_int_double      { double  apply(int     a); }
interface Function1_int_boolean     { boolean apply(int     a); }
interface Function1_int_char        { char    apply(int     a); }
interface Function1_long_R          { R       apply(long    a); }
interface Function1_long_byte       { byte    apply(long    a); }
interface Function1_long_short      { short   apply(long    a); }
interface Function1_long_int        { int     apply(long    a); }
interface Function1_long_long       { long    apply(long    a); }
interface Function1_long_float      { float   apply(long    a); }
interface Function1_long_double     { double  apply(long    a); }
interface Function1_long_boolean    { boolean apply(long    a); }
interface Function1_long_char       { char    apply(long    a); }
interface Function1_float_R         { R       apply(float   a); }
interface Function1_float_byte      { byte    apply(float   a); }
interface Function1_float_short     { short   apply(float   a); }
interface Function1_float_int       { int     apply(float   a); }
interface Function1_float_long      { long    apply(float   a); }
interface Function1_float_float     { float   apply(float   a); }
interface Function1_float_double    { double  apply(float   a); }
interface Function1_float_boolean   { boolean apply(float   a); }
interface Function1_float_char      { char    apply(float   a); }
interface Function1_double_R        { R       apply(double  a); }
interface Function1_double_byte     { byte    apply(double  a); }
interface Function1_double_short    { short   apply(double  a); }
interface Function1_double_int      { int     apply(double  a); }
interface Function1_double_long     { long    apply(double  a); }
interface Function1_double_float    { float   apply(double  a); }
interface Function1_double_double   { double  apply(double  a); }
interface Function1_double_boolean  { boolean apply(double  a); }
interface Function1_double_char     { char    apply(double  a); }
interface Function1_boolean_R       { R       apply(boolean a); }
interface Function1_boolean_byte    { byte    apply(boolean a); }
interface Function1_boolean_short   { short   apply(boolean a); }
interface Function1_boolean_int     { int     apply(boolean a); }
interface Function1_boolean_long    { long    apply(boolean a); }
interface Function1_boolean_float   { float   apply(boolean a); }
interface Function1_boolean_double  { double  apply(boolean a); }
interface Function1_boolean_boolean { boolean apply(boolean a); }
interface Function1_boolean_char    { char    apply(boolean a); }
interface Function1_char_R          { R       apply(char    a); }
interface Function1_char_byte       { byte    apply(char    a); }
interface Function1_char_short      { short   apply(char    a); }
interface Function1_char_int        { int     apply(char    a); }
interface Function1_char_long       { long    apply(char    a); }
interface Function1_char_float      { float   apply(char    a); }
interface Function1_char_double     { double  apply(char    a); }
interface Function1_char_boolean    { boolean apply(char    a); }
interface Function1_char_char       { char    apply(char    a); }
ECMAScript(2015年后) ECMAScript 2015引入了“fat”
l.Morph(e => e + 1);
l.Morph((e) => { return e + 1; });
static <A, B> List<B> morph(List<A> l, Function1<A, B> f) {
    List<B> r = new ArrayList<>();
    for (A e: l) r.add(f.apply(e));

    return r;
}
List<Integer> l = Arrays.asList(1, 2, 3, 4, 5);
morph(l, new Function1<Integer, Integer>() {
    @Override public Integer apply(Integer n) {
        return n + 1;
    }
});
morph(l, new Function1<Integer, Integer>() { @OVerride public Integer apply(Integer n) { return n + 1; }});
interface Function1<A, B> {
    B apply(A a);
}
interface Action1_T                 { void    apply(T       a); }
interface Action1_byte              { void    apply(byte    a); }
interface Action1_short             { void    apply(short   a); }
interface Action1_int               { void    apply(int     a); }
interface Action1_long              { void    apply(long    a); }
interface Action1_float             { void    apply(float   a); }
interface Action1_double            { void    apply(double  a); }
interface Action1_boolean           { void    apply(boolean a); }
interface Action1_char              { void    apply(char    a); }
interface Function1_T_R             { R       apply(T       a); }
interface Function1_T_byte          { byte    apply(T       a); }
interface Function1_T_short         { short   apply(T       a); }
interface Function1_T_int           { int     apply(T       a); }
interface Function1_T_long          { long    apply(T       a); }
interface Function1_T_float         { float   apply(T       a); }
interface Function1_T_double        { double  apply(T       a); }
interface Function1_T_boolean       { boolean apply(T       a); }
interface Function1_T_char          { char    apply(T       a); }
interface Function1_byte_R          { R       apply(byte    a); }
interface Function1_byte_byte       { byte    apply(byte    a); }
interface Function1_byte_short      { short   apply(byte    a); }
interface Function1_byte_int        { int     apply(byte    a); }
interface Function1_byte_long       { long    apply(byte    a); }
interface Function1_byte_float      { float   apply(byte    a); }
interface Function1_byte_double     { double  apply(byte    a); }
interface Function1_byte_boolean    { boolean apply(byte    a); }
interface Function1_byte_char       { char    apply(byte    a); }
interface Function1_short_R         { R       apply(short   a); }
interface Function1_short_byte      { byte    apply(short   a); }
interface Function1_short_short     { short   apply(short   a); }
interface Function1_short_int       { int     apply(short   a); }
interface Function1_short_long      { long    apply(short   a); }
interface Function1_short_float     { float   apply(short   a); }
interface Function1_short_double    { double  apply(short   a); }
interface Function1_short_boolean   { boolean apply(short   a); }
interface Function1_short_char      { char    apply(short   a); }
interface Function1_int_R           { R       apply(int     a); }
interface Function1_int_byte        { byte    apply(int     a); }
interface Function1_int_short       { short   apply(int     a); }
interface Function1_int_int         { int     apply(int     a); }
interface Function1_int_long        { long    apply(int     a); }
interface Function1_int_float       { float   apply(int     a); }
interface Function1_int_double      { double  apply(int     a); }
interface Function1_int_boolean     { boolean apply(int     a); }
interface Function1_int_char        { char    apply(int     a); }
interface Function1_long_R          { R       apply(long    a); }
interface Function1_long_byte       { byte    apply(long    a); }
interface Function1_long_short      { short   apply(long    a); }
interface Function1_long_int        { int     apply(long    a); }
interface Function1_long_long       { long    apply(long    a); }
interface Function1_long_float      { float   apply(long    a); }
interface Function1_long_double     { double  apply(long    a); }
interface Function1_long_boolean    { boolean apply(long    a); }
interface Function1_long_char       { char    apply(long    a); }
interface Function1_float_R         { R       apply(float   a); }
interface Function1_float_byte      { byte    apply(float   a); }
interface Function1_float_short     { short   apply(float   a); }
interface Function1_float_int       { int     apply(float   a); }
interface Function1_float_long      { long    apply(float   a); }
interface Function1_float_float     { float   apply(float   a); }
interface Function1_float_double    { double  apply(float   a); }
interface Function1_float_boolean   { boolean apply(float   a); }
interface Function1_float_char      { char    apply(float   a); }
interface Function1_double_R        { R       apply(double  a); }
interface Function1_double_byte     { byte    apply(double  a); }
interface Function1_double_short    { short   apply(double  a); }
interface Function1_double_int      { int     apply(double  a); }
interface Function1_double_long     { long    apply(double  a); }
interface Function1_double_float    { float   apply(double  a); }
interface Function1_double_double   { double  apply(double  a); }
interface Function1_double_boolean  { boolean apply(double  a); }
interface Function1_double_char     { char    apply(double  a); }
interface Function1_boolean_R       { R       apply(boolean a); }
interface Function1_boolean_byte    { byte    apply(boolean a); }
interface Function1_boolean_short   { short   apply(boolean a); }
interface Function1_boolean_int     { int     apply(boolean a); }
interface Function1_boolean_long    { long    apply(boolean a); }
interface Function1_boolean_float   { float   apply(boolean a); }
interface Function1_boolean_double  { double  apply(boolean a); }
interface Function1_boolean_boolean { boolean apply(boolean a); }
interface Function1_boolean_char    { char    apply(boolean a); }
interface Function1_char_R          { R       apply(char    a); }
interface Function1_char_byte       { byte    apply(char    a); }
interface Function1_char_short      { short   apply(char    a); }
interface Function1_char_int        { int     apply(char    a); }
interface Function1_char_long       { long    apply(char    a); }
interface Function1_char_float      { float   apply(char    a); }
interface Function1_char_double     { double  apply(char    a); }
interface Function1_char_boolean    { boolean apply(char    a); }
interface Function1_char_char       { char    apply(char    a); }
interface Function1_int_int {
    int apply(int x)
}
(int x) -> x + 1
new Function1_int_int {
    @Override public int apply(int x) {
        return x + 1;
    }
}
(int x) -> x + 1
interface * {
    int *(int *)
}
class * {
    int *(int *) // abstract!
}
static <A, B> List<B> morph(List<A> l, Function<A, B> f) {
    List<B> r = new ArrayList<>();
    for (var e: l) r.add(f.apply(e));

    return r;
}
List<Integer> l = Arrays.asList(1, 2, 3, 4, 5);
morph(l, new Function<Integer, Integer>() {
    @Override public Integer apply(Integer n) {
        return n + 1;
    }
});
morph(l, n -> n + 1);