Funkce jako hodnoty

V Lua je funkce hodnota, stejně jako číslo, text nebo tabulka. Potvrdí to i type: type(print) je "function". A jako každou hodnotu můžete funkci uložit do proměnné. local function dvakrat(n) je vlastně jen kratší způsob, jak vytvořit funkci a uložit ji do lokální proměnné, takhle:

local dvakrat = function(n)
    return n * 2
end

local dvojnasobek = dvakrat
print(dvakrat(4), dvojnasobek(10))
print(type(dvakrat), type(dvakrat(4)))

Vypíše:

8	20
function	number

function(n) … end bez názvu vytvoří funkci a local dvakrat = ji uloží do proměnné. local dvojnasobek = dvakrat nic nevolá, protože tam nejsou závorky: uloží stejnou funkci pod druhým názvem. type(dvakrat) se ptá na samotnou funkci, kdežto type(dvakrat(4)) na číslo, které funkce vrátila.

A teď to nejužitečnější: funkci můžete předat jiné funkci jako argument. Tato funkce projde seznam a každý prvek upraví funkcí, kterou dostane jako parametr:

local function upravVse(seznam, uprava)
    local vysledek = {}
    for _, hodnota in ipairs(seznam) do
        table.insert(vysledek, uprava(hodnota))
    end
    return vysledek
end

local function dvakrat(n)
    return n * 2
end

local ceny = {2, 3, 5}
print(table.concat(upravVse(ceny, dvakrat), " "))
print(table.concat(upravVse(ceny, function(n) return n + 1 end), " "))

Vypíše:

4 6 10
3 4 6

Uvnitř funkce upravVse je uprava parametr jako každý jiný, jen je v něm funkce, a tak ji upravVse volá: uprava(hodnota). upravVse neví, jaká úprava to bude, o tom rozhoduje volající. Druhé volání svou funkci ani nepojmenuje, napíše ji rovnou do závorek volání. Funkci bez názvu se říká anonymní funkce. Hodí se pro krátké funkce, které potřebujete jen na jednom místě, a krátká se vejde i na jeden řádek.

Když funkci předáváte, pište ji bez závorek: dvakrat, ne dvakrat(5). Se závorkami byste ji rovnou zavolali a předali její výsledek, číslo 10:

local function upravVse(seznam, uprava)
    local vysledek = {}
    for _, hodnota in ipairs(seznam) do
        table.insert(vysledek, uprava(hodnota))
    end
    return vysledek
end

local function dvakrat(n)
    return n * 2
end

local ceny = {2, 3, 5}
print(table.concat(upravVse(ceny, dvakrat(5)), " "))

Program skončí chybou:

main.lua:4: attempt to call a number value (local 'uprava')

upravVse dostala v parametru uprava číslo 10 a pokusila se ho zavolat. Funkce předávané jiným funkcím uvidíte často: v dalším cvičení jednu předáte funkci table.sort.

Pokyny

V sobotu je každá cena v Emině stánku o 2 mince vyšší. Napište funkci sobotniCena s parametrem cena, která vrátí cena + 2. Pak ji spolu s ceny předejte funkci upravVse a výsledek vypište spojený pomocí table.concat(…, " "). Program vypíše 7 10 22 14 5.

Na konci dne Ema prodává všechno za poloviční cenu. Vypište ceny vydělené 2 pomocí //, ale tentokrát nepište pojmenovanou funkci: napište anonymní funkci přímo do volání upravVse. Program vypíše 2 4 10 6 1.

Teď napište funkci, která dostává funkci: lokální funkci spocitejPokud se dvěma parametry, seznam a podminka. Vrátí, pro kolik prvků seznamu seznam vrátí funkce podminka hodnotu true.

Pomocí spocitejPokud a anonymních funkcí zjistěte, kolik cen je vyšších než 7 mincí a kolik nižších než 5. Program vypíše:

Dražší než 7: 3
Levnější než 5: 1

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

7/11