Могу ли я ввести псевдоним функции с параметрами по умолчанию?

avatar
Pétur Ingi Egilsson
8 апреля 2018 в 08:06
947
1
2

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

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

  • executeCommands, функция, которая выполняет список команд. Эта функция может дополнительно получать в качестве аргумента другую функцию, которая выбирает команды для выполнения.
  • fetchCommandsFromDisk, функция по умолчанию, которая извлекает команды с диска.
  • Executioner.executeCommands(), точка входа программы.

    /* An attempt to typealias:Executioner\fetchCommandsFromDisk( (String)->[String] ) */
    typealias commandFetcherType = (String) -> [String]
    
    class Executioner {
        /* The function whose signature is to have a typealias. */
        func fetchCommandsFromDisk(fromFile file: String = "foobar") -> [String] {
            ...
        }
    
        /* A function which if called without arguments,
         * will fall back to a default argument which is
         * the above function. */
        static public func executeCommands(commandFetcher = fetchCommandsFromDisk) {
            /* This does not work, xcode reports:
               "ERROR: Missing argument for parameter #1 in call" */
            let commands = commandFetcher()
            ... /* execute commands */ ...
        }
    }
    
    ...
    
    /*
     * Calling executeCommands without parameters.
     * This results in commands being fetched from disk, then executed.
     */
    Executioner.executeCommands()
    
Источник
Nerdy Bunz
8 апреля 2018 в 08:33
0

этот код заставляет мою игровую площадку Xcode использовать 170% процессора

Nerdy Bunz
8 апреля 2018 в 08:59
0

Это очень сбивает с толку (для меня). Кто-то гораздо более осведомленный, чем я, может дать теоретический ответ, но... Я думаю, вы можете перепутать функцию и закрытие... это "псевдокод"?

Nerdy Bunz
8 апреля 2018 в 09:41
0

Вы имеете в виду: «выполнить команды (arg1: commandFetcherType = fetchCommandsFromDisk)» ??

Pétur Ingi Egilsson
8 апреля 2018 в 09:52
0

@BooberBunz да

Nerdy Bunz
8 апреля 2018 в 10:00
0

Уэлп, это настоящий сногсшибатель... я думаю, что я не в своей лиге. Я чувствую, что ответ Ахмада действительно полезен?

Ответы (1)

avatar
Ahmad F
8 апреля 2018 в 09:16
2

В вашем коде есть некоторые проблемы:

1- Чтобы использовать fetchCommandsFromDisk по умолчанию для статического метода executeCommands, вы также должны объявить fetchCommandsFromDisk как метод

8 instance

83,39133static23,3,913>static23

>
static func fetchCommandsFromDisk(fromFile file: String = "foobar") -> [String] {
    print("\(#function): file value is: \(file)")
    return [""]
}

2- Объявление подписи executeCommands как:

static public func executeCommands(commandFetcher = fetchCommandsFromDisk)

является invalid, вам не хватает имени параметра, поэтому вместо него должно быть:

static public func executeCommands(parameter: @escaping commandFetcherType = fetchCommandsFromDisk)

таким образом, весь метод будет, например, таким:

static public func executeCommands(parameter: @escaping commandFetcherType = fetchCommandsFromDisk) {
    let commands = parameter

    commands("testing")
}

Обратите внимание, что вызов parameter должен выполняться с параметрами, по какой-то причине он не распознает fetchCommandsFromDisk значения по умолчанию для своего параметра ("foobar"), вместо этого он будет искать parameter ("тестирование" ) значение.

Вкратце, весь код будет таким:

typealias commandFetcherType = (String) -> [String]

class Executioner {
    static func fetchCommandsFromDisk(fromFile file: String = "foobar") -> [String] {
        print("\(#function): file value is: \(file)")
        return [""]
    }

    static public func executeCommands(parameter: @escaping commandFetcherType = fetchCommandsFromDisk) {
        let commands = parameter

        commands("testing")
    }
}

Вывод:

Основываясь на приведенном выше коде, давайте рассмотрим выходные данные для каждого метода:

--- Вызов fetchCommandsFromDisk без передачи параметра:

Executioner.fetchCommandsFromDisk()
/* fetchCommandsFromDisk(fromFile:): file value is: foobar */

--- Вызов fetchCommandsFromDisk и передача параметра:

Executioner.fetchCommandsFromDisk(fromFile: "hello!")
/* fetchCommandsFromDisk(fromFile:): file value is: hello! */

--- Вызов executeCommands без передачи функции параметр:

Executioner.executeCommands()
/* fetchCommandsFromDisk(fromFile:): file value is: testing */

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

--- Вызов executeCommands и передача параметра -функции:

func customHandle(file: String) -> [String] {
    print(#function)
    return ["Hello", "World!"]
}

Executioner.executeCommands(parameter: customHandle)
/* customHandle(file:) */

Pétur Ingi Egilsson
8 апреля 2018 в 09:34
0

Я только что обновил код в вопросе новыми именами, чтобы его было легче понять. Я также исправил 1. Вы не возражаете, если я изменю ваш ответ, чтобы отразить мои изменения?

Ahmad F
8 апреля 2018 в 11:57
0

@PéturIngiEgilsson Готово :)