Занялся написанием лямбда-функций.
Когда нужно написать очень небольшую функцию, в одну-две строчки, и вызвать ее только в одном месте, то не хочется прописывать метод у класса, потом реализовывать код в implementation-части, и только после этого его вызывать. Хотелось бы эту жалкую строку с кодом прописать сразу в месте вызова.
Именно эту проблему и решают мои лямбда-функции:
FButton.OnClick := #l(Button: TButton) FWindow.Close;
Конструкция #l создает метод у класса, внутри которого она вызывается. Так записывается вызов процедуры и функции соответственно:
ObjectUpdate := #l(Obj: TMyObject) Obj.Update;
ObjectFilter := #l(Obj: TMyObject): Boolean = Obj is TSuperObject;
Внутри можно писать и несколько операторов, разделенных символом ;
Есть так же возможность создать лямбду на классовый метод или даже просто функцию, делается это заменой l на lsimple.
lsimple уже реализовано и работает.
При реализации сразу же я столкнулся с множеством проблем.
Во-первых, сигнатуру функции: параметры и возвращаемое значение, - в теории можно опустить, т.к. они очевидно восстанавливаются по левой части выражения. На практике же, определить какой тип имеет левая часть выражения - весьма трудоемкая задача и в рамках моей небольшой утилитки dpp ее реализация не представляется возможной.
Во-вторых, есть более серьезная проблема при использовании локальных переменных. Например, сейчас такой код не заработает:
for I := 0 to 3 do
FButtons[I].OnClick := #l(Button: TButton) FWindows[I].Show;
хотя очень хотелось бы.
Даже если отбросить тот факт, что это сложно реализовать технически (нужно создавать промежуточный класс, который запомнит значение переменной I в момент вызова, и у этого класса могут начаться трудности в получении доступа к приватному полю FWindows, да и вообще к FWindows нужно будет каким-то макаром приписать что-то типа FOwner.FWindows), даже отбросив - совершенно непонятно сколько этот класс должен жить в памяти. Узнать когда кнопка перестанет ссылаться на метод этого класса невозможно.
Кроме того, хочется в дальнейшем делать встроенные лямбы, а не только в конце строк:
RegistHandler($10, $32, #l(Packet: TPacket) DoSomething#);
А в этом плане символ # очень неудачен, трудно определить кто из них открывающий, а кто закрывающий, и при вложенностях получится путаница.
Поэтому, наверно, будет введена конструкция [# ... #] для встроенных в строки команд.
Комментариев нет:
Отправить комментарий