Подтвердить что ты не робот

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

Некоторые люди говорят, что каждый язык программирования имеет свой "бюджет сложности", который он может использовать для достижения своей цели. Но если бюджет сложности исчерпан, все незначительные изменения становятся все более сложными и трудными для реализации с обратной совместимостью.

После чтения текущего предварительного синтаксиса для лямбда (≙ Лямбда-выражения, прозрачность исключений, методы защитника и ссылки на методы) с августа 2010 года. Интересно, люди в Oracle полностью игнорировали бюджет сложности Java при рассмотрении таких изменений.

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

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

Спасибо!

4b9b3361

Ответ 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; } или с большим количеством комплексный ручной подход для конкретных случаев, когда сахарное покрытие мешает предполагаемой семантике.

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

Ответ 2

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

λx.E

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

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

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

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

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

Ответ 3

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

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

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

Java:

#(x){x*x}

Python:

lambda x:x*x

С#:

x => x*x

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

x#x*x

Ответ 4

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

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

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

Ответ 5

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

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

[](int x, int y) { return x + y; }