D (dlang) передает лямбда-функцию в качестве аргумента - PullRequest
2 голосов
/ 04 октября 2019

С D, как я могу передать функцию (возможно, ссылку на функцию) в качестве аргумента для выполнения внутри другой функции?

import std.stdio : writeln;

class Event {}

class EventTarget
{
    void addEventListener(string eventName, void delegate(Event event) callback)
    {
        // TODO: add to slice to execute later, for now execute directly
        callback();
    }
}

void main()
{
    auto variableFromParentScope = "lorem ipsum";
    auto target = new EventTarget();
    target.addEventListener("load", (Event event) => { writeln(variableFromParentScope, event); }, true);
}

Дает мне ошибку:

onlineapp.d(10): Error: delegate callback(Event event) is not callable using argument types ()
onlineapp.d(10):        missing argument for parameter #1: Event event
onlineapp.d(18): Error: function onlineapp.EventTarget.addEventListener(string eventName, void delegate(Event event) callback) is not callable using argument types (string, void delegate() @system delegate(Event event) pure nothrow @safe, bool)
onlineapp.d(18):        cannot pass argument __lambda1 of type void delegate() @system delegate(Event event) pure nothrow @safe to parameter void delegate(Event event) callback

Я настроил пример здесь: https://run.dlang.io/is/FnQoId


РЕШЕНИЕ, с помощью ответов я исправил это так:

import std.stdio : writeln;

class Event {}

class EventTarget
{
    void addEventListener(string eventName, void delegate(Event event) callback)
    {
        // TODO: add to slice to execute later, for now execute directly
        callback(new Event());
    }
}

void main()
{
    auto variableFromParentScope = "lorem ipsum";
    auto target = new EventTarget();
    target.addEventListener(
        "load", 
        (Event event) {
            writeln(variableFromParentScope, event);
        }
    );
}

Рабочий пример: https://run.dlang.io/is/6aDRoU

Ответы [ 2 ]

4 голосов
/ 04 октября 2019

Вы используете неверный синтаксис для делегата, как вы также можете увидеть в сообщении об ошибке, у которого нет ожидаемого типа.

Чтобы объяснить более подробно, я покажу вам, как он изменится, если вырасширить его до более длинной формы делегата, вместо того чтобы использовать сокращение =>:

(Event event) => { writeln(variableFromParentScope, event); }

становится

(Event event) { return { writeln(variableFromParentScope, event); }; }

Как видите, вы возвращаете делегата без параметров внутриваш фактический делегат. Если вы удалите =>, ваш делегат будет работать должным образом.

Альтернативные допустимые формы для вашего параметра делегата будут:

(event) { ... }
delegate (Event event) { ... }
delegate (event) { ... }
&someMemberMethod // some object member method taking in Event as first parameter
toDelegate(&someGlobalFunction) // from std.functional

Только если вы хотите что-то вернуть, вы используете=> стрелка. Вариант использования для () => { something } будет делегатом, возвращающим делегата (как делегат, генерирующий делегатов для заданного ввода)

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

2 голосов
/ 04 октября 2019

target.addEventListener("load", (Event event) => { writeln(variableFromParentScope, event); }, true);

(Args) => {} - это лямбда, которая возвращает лямбда.

Правильные формы:

  • target.addEventListener("load", (Event event) { writeln(variableFromParentScope, event); }, true);

  • target.addEventListener("load", (Event event) => writeln(variableFromParentScope, event), true);

...