Swift. Функция в качестве входного и возвращаемого значений

From AsIsWiki
Jump to: navigation, search

Назад · Оглавление · Дальше


Возвращаемое значение функционального типа

Функция b() возвращает функцию a():

func a() {
    print("Done!")
}

func b() -> () -> () {  // тип возвращаемого значения () -> ()
    return a
}

let f = b()  // результат функции b() присваивается в константу f
             // тип данных f неявно определяется как () -> ()

f()  // вызов хранимой в константе функции a()

Консоль:
Done!

В функцию a() добавляем возвращаемое значение:

func a() -> String {
    return "Done!"
}

func b() -> () -> String {  // тип возвращаемого значения () -> String
    return a
}

let f = b()  // константа f хранит функцию a() - результат функции b()

a()  // "Done!"
b()  // () -> String
f()  // "Done!"

Входное значение функционального типа

Функция newWallet передается в качестве входного аргумента функции walletSum:

// Генератор массива банкнот
// banknoteCount - требуемое количество банкнот
//
func newWallet(banknoteCount: Int) -> [Int] {

    let banknoteTypes = [50, 100, 500, 1000, 5000]
    var wallet: [Int] = []

    for _ in 1...banknoteCount {
        let index = Int.random(in: 0 ... banknoteTypes.count - 1)
        wallet.append(banknoteTypes[index])
    }
    return wallet
}

// Аргумент wallet имеет функциональный тип (Int) -> [Int]
// wallet используется для передачи функции newWallet в функцию walletSum
// generate - внешнее имя аргумента wallet
//
func walletSum(generate wallet: (Int) -> [Int]) -> Int? {

    let n = Int.random(in: 1...10)  // количество банкнот
    let banknotes = wallet(n)       // [100, 5000, 50, 5000]
    var sum = 0

    for banknote in banknotes {
        sum += banknote
    }
    return sum
}

walletSum(generate: newWallet)  // 10150

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

Функция walletSum(generate:) может принять на вход любую функцию с типом (Int) -> [Int], например:

newWallet1000(banknoteCount:)  // генератор массива тысячных купюр

Параметры функционального типа для ленивых вычислений

Ленивые вычисления позволяют получить некоторое значение не в момент передачи параметра,
а при попытке доступа к хранящемуся в нем значению.

Рассмотрим три функции:

let n = 1000000

getPiNum(n)   // возвращает n-знак после запятой в числе Pi

getFibNum(n)  // возвращает старшую цифру n-числа в ряду Фибоначчи

returnSomeNum(getPiNum(n), getFibNum(n))

Функция returnSomeNum(_:_:) имеет функциональный тип:

(Int, Int) -> Int

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

Приведем функцию returnSomeNum(_:_:) к типу:

((Int) -> Int, (Int) -> Int)) -> Int

Теперь в returnSomeNum(_:_:) передаются не готовые значения, а функции, которые рассчитывают их.

В теле returnSomeNum будет использована требуемая функция,
а ресурсы на подсчет второго значения затрачены не будут.

Необходимое значение рассчитывается по факту обращения к нему,
а не в момент передачи во входном аргументе.



Назад · Оглавление · Дальше

Personal tools
Namespaces

Variants
Actions
Navigation
Tools