Ответ 1
Я не следил за процессом и развитием Java 7 лямбда предложение, я даже не уверен в том, что такое последняя формулировка предложения. Подумайте об этом как о выражении/мнении, а не о утверждении истины. Также, Я не использовал Java целую вечность, поэтому синтаксис может быть ржавым и неверно в местах.
Во-первых, что такое lambdas для языка Java? Синтаксический сахар. В то время как в общем случае lambdas позволяет коду создавать небольшие объекты функции в место, эта поддержка была уже задана - в некоторой степени - в Java языка посредством использования внутренних классов.
Итак, насколько лучше синтаксис лямбда? Где он превосходит предыдущие языковые конструкции? Где это может быть лучше?
Во-первых, мне не нравится тот факт, что есть два доступных синтаксиса
для лямбда-функций (но это идет в строке С#, поэтому я думаю, что мой
мнение не распространено. Я думаю, если мы хотим сахарного пальто, тогда
#(int x)(x*x)
слаще, чем #(int x){ return x*x; }
, даже если
двойной синтаксис ничего не добавляет. Я бы предпочел
второй синтаксис, более общий за дополнительную плату написания return
и
;
в коротких версиях.
Чтобы быть действительно полезным, lambdas может принимать переменные из области действия в
где они определены и от закрытия. Согласование
Внутренние классы, лямбды ограничены захватом "эффективно
конечных "переменных. Согласованность с предыдущими особенностями
язык - приятная особенность, но для сладости было бы неплохо быть
способный захватывать переменные, которые можно переназначить. Для этой цели,
они рассматривают, что переменные, присутствующие в контексте и
аннотированный с помощью @Shared
, будет записан по ссылке, что позволяет
задания. Мне кажется странным, как лямбда может использовать переменную
определяется в месте объявления переменной, а не
где определена лямбда. Одна переменная может использоваться в более
чем одна лямбда, и это приводит к одинаковому поведению во всех них.
Lambdas пытается имитировать действительные объекты функции, но это предложение
не получить полностью там: держать парсер простым, так как до сих пор
идентификатор обозначает либо объект, либо метод, который был сохранен
согласованный и вызывающий лямбда требует использования !
после лямбды
name: #(int x)(x*x)!(5)
вернется 25
. Это привносит новый синтаксис
использовать для лямбда, которые отличаются от остальной части языка, где
!
стоит как-то как синоним для .execute
на виртуальном родовом
интерфейс Lambda<Result,Args...>
, но почему бы не завершить его?
Можно создать новый общий (виртуальный) интерфейс Lambda
. Это
должны быть виртуальными, поскольку интерфейс не является реальным интерфейсом, а
семейство таких: Lambda<Return>
, Lambda<Return,Arg1>
,
Lambda<Return,Arg1,Arg2>
... Они могут определить одно выполнение
метод, который я хотел бы быть как С++ operator()
, но если это
бремя, то любое другое имя будет прекрасным, охватывая !
как
ярлык для выполнения метода:
interface Lambda<R> {
R exec();
}
interface Lambda<R,A> {
R exec( A a );
}
Затем компилятору нужно перевести только identifier!(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. Это может быть использовано, например, в цикле для генерации множителя lambdas:
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; }
или с большим количеством
комплексный ручной подход для конкретных случаев, когда сахарное покрытие
мешает предполагаемой семантике.
В целом, я считаю, что предложение лямбда может быть улучшено в в разных направлениях, что способ добавления синтаксического сахара является утечка абстракции (вы имеете дело с внешними проблемами особенно для лямбда), и что, не обеспечивая более низкий уровень интерфейс делает код пользователя менее читаемым в случаях использования, которые не идеально подходят для простого использования.