Механизмы Java при использовании в лямбдай-замыканиях - PullRequest
6 голосов
/ 24 октября 2009

Lamdbaj позволяет определять замыкания в языке Java, можно найти различные примеры здесь

Мой вопрос касается используемых Java-механизмов, например, для определения закрытия println, используется следующий код:

Closure println = closure(); 
{ of(System.out).println(var(String.class)); }

Это замыкание может быть впоследствии выполнено через:

println.apply("foobar");

Мне любопытно, какие механизмы в Java позволят вызову of(...).println(...) ассоциироваться с самим экземпляром println.

Естественно, исходный код lambdaj доступен для чтения, но я надеялся получить объяснение чуть более высокого уровня, если оно есть у кого-либо. Мои навыки рефлексии доходят до самоанализа и динамического выполнения методов.

Ответы [ 2 ]

10 голосов
/ 24 октября 2009

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

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

http://ctpjava.blogspot.com/2009/10/lambdaj-new-trends-in-java.html

Я тоже счастливый разработчик Scala. Но иногда вы просто обязаны разрабатывать на Java (по моему опыту, в реальном мире, примерно в 80% случаев вы не можете выбрать, на каком языке вы должны писать свой код), и в этом случае некоторые из функций lambdaj могут быть полезно (или я надеюсь на это). Я просто хотел привнести в Java некоторые функциональные возможности, которые полностью отсутствуют. Конечно, результат не является полностью удовлетворительным в основном из-за ограничений, наложенных самой Java.

Что касается внутреннего механизма lambdaj, да, он использует ThreadLocal для достижения этого результата. Если у вас есть другие вопросы, курьезы или даже лучшие предложения и конструктивная критика о lambdaj, возможно, вам будет интересно зарегистрироваться в списке рассылки lambdaj здесь:

http://groups.google.com/group/lambdaj

Bye Mario

2 голосов
/ 24 октября 2009

Ну, of - это, вероятно, метод static, который импортируется статически, поэтому его можно вызывать без имени включающего класса. Я ожидаю, что var то же самое. Оба метода должны возвращать некоторый тип, который впоследствии будет вызываться методами:

public class Printable {
  public void println(Var var);
}

public class Fac {
  public static Printable of(Object o) {
    return new Printable(o);
  }

  public static Var var(Class<?> clazz) {
    return new Var(clazz);
  }

} 

Внезапно:

Fac.of(System.out).println(Fac.var(String.class));

Действительна Java. Используя статический импорт, привет presto:

import static Fac.*;

of(System.out).println(var(String.class));

Фигурные скобки, очевидно, являются допустимыми Java, так как вы можете добавить их в любой метод, чтобы помочь в определении лексической ссылки. Этот стиль разработки API называется свободно и лучше всего демонстрируется библиотекой тестирования JMock .

Кстати, если предполагается ввести замыкания в Java, это довольно смешно - синтаксис нечитаемо ужасен . Их пример ввода / вывода на самом деле заставил меня смеяться вслух. Попробуйте Scala !

EDIT - два вызова println связаны, я полагаю, потому что первая последовательность вызовов позволяет библиотеке захватывать переменные, которые вы передали в качестве параметров. Они, вероятно, зафиксированы в некоторой структуре ThreadLocal. Когда вы затем вызываете (также предположительно статический) метод println, библиотека использует эти захваченные данные для фактического выполнения поведения на более позднем этапе. Кроме того, в тестовой среде EasyMock используется аналогичный механизм (использующий прокси-серверы Java в фоновом режиме) для сбора ожидаемых значений.

...