Сложность текущего предложения Lambda в Java 7? (Август 2010)

Вы можете использовать этот проект: http://code.google.com/p/anywhereindb

Это приведет к поиску всех данных во всей таблице.

21
задан soc 5 August 2010 в 11:58
поделиться

5 ответов

Я не следил за процессом и развитием лямбда-выражения Java 7. предложение, я даже не уверен, какова последняя формулировка предложения. Считайте это высказыванием / мнением, а не утверждением истины. Также, Я давно не использовал Java, поэтому синтаксис может быть ржавым и местами некорректно.

Во-первых, что такое лямбда-выражения для языка Java? Синтаксический сахар. Пока в общем, лямбды позволяют коду создавать небольшие функциональные объекты в место, эта поддержка уже была предустановлена ​​- до некоторой степени - в Java язык за счет использования внутренних классов.

Так насколько лучше синтаксис лямбда-выражений? Где он превосходит предыдущие языковые конструкции? Что может быть лучше?

Для начала мне не нравится тот факт, что есть два доступных синтаксиса для лямбда-функций (но это относится к строке C #, поэтому я думаю, что мой мнение не является широко распространенным. Я думаю, если мы хотим приукрасить, то # (int x) (x * x) слаще, чем # (int x) {return x * x; } даже если двойной синтаксис больше ничего не добавляет. Я бы предпочел второй синтаксис, более общий за счет дополнительных затрат на написание return и ; в сокращенных версиях.

Чтобы быть действительно полезными, лямбда-выражения могут принимать переменные из области видимости в где они определены и из замыкания . В соответствии с Внутренние классы, лямбда-выражения ограничены , эффективно захватывая ' final 'переменные. Соответствие предыдущим характеристикам язык - приятная функция, но для сладости было бы неплохо возможность захвата переменных, которые можно переназначить.Для этой цели, они считают, что переменные присутствуют в контексте и аннотированный @Shared будет записан ссылкой , что позволит задания. Мне это кажется странным, поскольку лямбда может использовать переменную определяется в месте объявления переменной, а не где определена лямбда. Одна переменная может использоваться в нескольких чем одна лямбда, и это приводит к одинаковому поведению во всех из них.

Лямбды пытаются имитировать реальные функциональные объекты, но предложение делает не попасть туда полностью: чтобы синтаксический анализатор оставался простым, поскольку до сих пор идентификатор обозначает либо объект, либо метод, который был сохранен согласованный и вызов лямбды требует использования ! после лямбды name: # (int x) (x * x)! (5) вернет 25 . Это приносит новый синтаксис использовать для лямбда-выражений, которые отличаются от остального языка, где ! стоит каким-то образом как синоним для .execute на виртуальном универсальном interface Lambda но почему бы не завершить его?

Можно создать новый общий (виртуальный) интерфейс Lambda . Было бы должны быть виртуальными, поскольку интерфейс - это не настоящий интерфейс, а семейство таких: Lambda , Lambda , Лямбда ...Они могли определить единственное исполнение метод, который я хотел бы быть похожим на C ++ operator () , но если это бремя, тогда подойдет любое другое имя, включающее ! как ярлык для выполнения метода:

 interface Lambda<R> {
    R exec();
 }
 interface Lambda<R,A> {
    R exec( A a );
 }

Тогда компилятору нужно только преобразовать идентификатор! (args) в identifier.exec (args) , это просто. Перевод лямбда-синтаксис потребует от компилятора определения правильного интерфейс реализуется и может быть сопоставлен как:

 #( int x )(x *x)
 // translated to
 new Lambda<int,int>{ int exec( int x ) { return x*x; } }

Это также позволит пользователям определять внутренние классы, которые могут использоваться как лямбды, в более сложных ситуациях. Например, если лямбда функция, необходимая для захвата переменной, аннотированной как @Shared в только для чтения, или поддерживать состояние захваченного объекта в место захвата, ручное выполнение лямбды было бы доступно:

 new Lambda<int,int>{ int value = context_value;
     int exec( int x ) { return x * context_value; }
 };

Аналогично текущему определению внутренних классов, и, таким образом, естественен для нынешних пользователей Java. Это можно было бы использовать, например, в цикле для генерации лямбда-множителей:

 Lambda<int,int> array[10] = new Lambda<int,int>[10]();
 for (int i = 0; i < 10; ++i ) {
    array[i] = new Lambda<int,int>{ final int multiplier = i;
       int exec( int x ) { return x * multiplier; }
    };
 }
 // note this is disallowed in the current proposal, as `i` is
 // not effectively final and as such cannot be 'captured'. Also
 // if `i` was marked @Shared, then all the lambdas would share
 // the same `i` as the loop and thus would produce the same
 // result: multiply by 10 --probably quite unexpectedly.
 //
 // I am aware that this can be rewritten as:
 // for (int ii = 0; ii < 10; ++ii ) { final int i = ii; ...
 //
 // but that is not simplifying the system, just pushing the
 // complexity outside of the lambda.

Это позволит использовать лямбда-выражения и методы, которые принимают лямбда-выражения. с новым простым синтаксисом: # (int x) {return x * x; } или более комплексный ручной подход для конкретных случаев, когда сахарная глазурь вмешивается в предполагаемую семантику.

В целом, я считаю, что предложение лямбда можно улучшить, разные направления, то, как он добавляет синтаксический сахар, утечка абстракции (вы имеете дело с внешними проблемами, в частности, лямбда) и не обеспечивая более низкий уровень интерфейс делает код пользователя менее читаемым в случаях использования, которые не идеально подходят для простого случая использования. :

3
ответ дан 29 November 2019 в 22:12
поделиться

Это не намного сложнее, чем лямбда-выражения в других языках.

Рассмотрим...

int square(x) {
    return x*x;
}

Java:

#(x){x*x}

Python:

lambda x:x*x

C#:

x => x*x

Я думаю, что подход C# немного более интуитивен. Лично я бы предпочел...

x#x*x
1
ответ дан 29 November 2019 в 22:12
поделиться

По модулю некоторых конструкций разрешения неоднозначности, почти все эти методы вытекают из фактического определения лямбда-абстракции:

λx.E

Чтобы ответить на ваши вопросы по порядку:

Я не думаю, что есть какие-то конкретные вещи, которые делают предложения сообщества Java лучше или хуже, чем что-либо еще. Как я уже сказал, это следует из математического определения, и поэтому все точные реализации будут иметь почти точно такой же вид.

Анонимные первоклассные функции, привязанные к императивным языкам, как правило, в конечном итоге становятся функцией, которую некоторые программисты любят и часто используют, а другие полностью игнорируют, поэтому, вероятно, будет разумным выбором дать ей некоторый синтаксис, который не запутает типы людей, которые предпочитают игнорировать наличие этой конкретной языковой особенности. Я думаю, что они пытались скрыть сложность и особенности реализации, используя синтаксис, который хорошо сочетается с Java, но не имеет реальной коннотации для Java-программистов.

Вероятно, для них желательно использовать некоторые части синтаксиса, которые не усложняют существующие определения, и поэтому они немного ограничены в символах, которые они могут использовать в качестве операторов и т.п. Конечно, настойчивое стремление Java к обратной совместимости немного ограничивает развитие языка, но я не думаю, что это обязательно плохо. Подход PHP находится на другом конце спектра (то есть «эй, ребята, давайте ломать все каждый раз, когда будет новый выпуск!»).Я не думаю, что эволюция Java по своей сути ограничена, за исключением некоторых фундаментальных принципов ее дизайна - например, соблюдение принципов ООП, на базе ВМ.

Я думаю, что очень сложно сделать четкие заявления об эволюции языка с точки зрения Java. Он находится в достаточно уникальном положении. Во-первых, он очень, очень популярен, но относительно старый. У Microsoft было как минимум 10-летнее наследие Java, прежде чем они решили даже начать разработку языка под названием «C #». Язык программирования C практически вообще перестал развиваться. В C ++ было внесено несколько существенных изменений, которые нашли широкое признание. Java продолжала развиваться через медленный, но последовательный процесс - во всяком случае, я думаю, что он лучше оснащен для дальнейшего развития, чем любые другие языки с такими же огромными установленными базами кода.

3
ответ дан 29 November 2019 в 22:12
поделиться

Возможно, это не совсем ответ на ваш вопрос, но это может быть сопоставимо с тем, как objective-c (который, конечно, имеет очень узкую базу пользователей в отличие от Java) был расширен с помощью блоки ( примеры ). Хотя синтаксис не соответствует остальному языку (IMHO), это полезное дополнение, и дополнительная сложность с точки зрения языковых функций вознаграждается, например, более низкой сложностью параллельного программирования (простые вещи, такие как параллельная итерация по массиву или сложные методы, такие как Grand Central Dispatch ).

Кроме того, многие общие задачи упрощаются при использовании блоков, например, создание одного объекта в качестве делегата (или - в жаргоне Java - «слушателя») для нескольких экземпляров одного и того же класса. В Java анонимные классы уже могут использоваться для этой цели, поэтому программисты знают концепцию и могут просто сэкономить несколько строк исходного кода, используя лямбда-выражения.

В objective-c (или в фреймворках Cocoa / Cocoa Touch) новые функции теперь часто доступны только с использованием блоков, и кажется, что программисты быстро внедряют их (учитывая, что они должны отказаться от обратной совместимости со старыми версиями ОС. ).

1
ответ дан 29 November 2019 в 22:12
поделиться

Это очень близко к лямбда-функциям, предложенным в новом поколении C++ (C++0x). поэтому я думаю, что ребята из Oracle посмотрели на другие реализации, прежде чем создавать свою собственную.

http://en.wikipedia.org/wiki/C%2B%2B0x

[](int x, int y) { return x + y; }
1
ответ дан 29 November 2019 в 22:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: