Любая или беда с последовательностью функций - PullRequest
3 голосов
/ 20 октября 2019

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

struct FunctionSequence {

    var callbacks = [Any]() //how to restrict Any to only functions?

    init(with functions: Any...){
        self.callbacks = functions
    }

    func callAll(){
        for f in callbacks {
            f()
        }
    }
}

Компиляция прерывается с помощью:

error: cannot call value of non-function type 'Any'

Поэтому я прошу людей, которые глубоко в Swift, помочь. PS Мне нужен следующий результат:

var printer = FunctionSequence
    .init(with: {print("Hello,")}, {print("world!")})
printer.callbacks.insert({print("I hate you,")}, at: 1)
printer.callAll()
//outputs "Hello, I hate you, world!"

Ответы [ 3 ]

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

Не существует общего «типа функции» - функции с разными аргументами или разными типами возвращаемых данных являются разными типами.

В вашем случае вы, очевидно, хотите получить массив функций типа () -> Void, то есть функций, которые принимаютбез аргументов и не возвращают значение:

struct FunctionSequence {

    var callbacks = [() -> Void]()

    init(with functions: (() -> Void)...){
        self.callbacks = functions
    }

    // ...
}

Или с псевдонимом типа:

typealias SimpleFunction = () -> Void

struct FunctionSequence {

    var callbacks = [SimpleFunction]()

    init(with functions: SimpleFunction...){
        self.callbacks = functions
    }

    // ...
}

Если callbacks определен как массив Any, вы можете поместитьвсе, что в нем: функции, не имеющие аргументов, функции, принимающие одно целое число, ..., целые числа, строки, что угодно. и вызвать функции соответственно. Пример:

struct FunctionSequence {

    var callbacks = [Any]()

    init(with functions: Any...){
        self.callbacks = functions
    }

    func callAll() {
        for f in callbacks {
            switch f {
            case let f0 as () -> Void:    f0()
            case let f1 as (Int) -> Void: f1(17)
            default: break // Other function signature, or not a function at all.
            }
        }
    }
}

let printer = FunctionSequence(with:
        { print("Hello,") },
        { (i: Int) in print(i)} )
printer.callAll()
1 голос
/ 20 октября 2019

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

Это просто [() -> Void]. Нет необходимости в другом типе.

var printer = [{print("Hello,", terminator: " ")}, {print("world!")}]
printer.insert({print("I hate you,", terminator: " ")}, at: 1)
for p in printer {p()}
//outputs "Hello, I hate you, world!"
1 голос
/ 20 октября 2019

Используйте сигнатуру функции

struct FunctionSequence {
    var callbacks = [()->Void]() 

    init(with functions: ()->Void...){
        self.callbacks = functions
    }

    func callAll(){
        for f in callbacks {
            f()
        }
    }
}

или с псевдонимом типа

typealias VoidFunction = () -> Void
struct FunctionSequence {
    var callbacks = [VoidFunction]()

    init(with functions: VoidFunction...){
        self.callbacks = functions
    }

    func callAll(){
        for f in callbacks {
            f()
        }
    }
}

Рядом с вопросом, но если вы хотите вывод в одну строку, вы, вероятно, хотите функциюкоторый возвращает строку и что callAll выполняет печать. Например

typealias StringFunction = () -> String
struct FunctionSequence {
    var callbacks = [StringFunction]()

    init(with functions: StringFunction...){
        self.callbacks = functions
    }

    func callAll(){
        print(callbacks.map {$0()}.joined(separator: " "))
    }
}

var printer = FunctionSequence
    .init(with: {"Hello,"}, {"world!"})
printer.callbacks.insert({"I hate you,"}, at: 1)
printer.callAll()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...