Lambda Expression

Made by 12527 Brine

Lambda Expression

Make by 12527 鄭竣陽

大綱 Outline

  • 函式」複習
  • 什麼是 lambda expression?
  • 一些酷酷的小知識

Made by 12527 Brine

Function

函式

  • 就是將一堆指令包在一起
  • 簡化重複結構
  • 透過命名提升程式可讀性
  • 函數內變數出來後就會消失
  • 來看些特殊的用法吧

基本介紹&複習

函式的特殊用法

可能是常識然後我是井底之蛙

函式多載 Function Overloading

#include <iostream>

using namespace std;

void print(int input) {
    cout << input << '\n';
}

void print(double input) {
    cout << input << '\n';
}

void print(string input) {
    cout << input << '\n';
}

void print() {
    cout << '\n';
}

int main() {
    print();
    print(15);
    print(1.5);
    print("16");
}
# PRESENTING CODE

建構函式 Constructor

#include <iostream>

using namespace std;

class Domain {
public:
    Domain() {}

    Domain(int sideLength, int middle): 
           l(middle - sideLength), r(middle + sideLength),
           u(middle - sideLength), d(middle + sideLength) {}
    Domain(int left, int right, int up, int down):
           l(left), r(right), u(up), d(down) {}

    long long getArea() { return (r - l) * (d - u); }
    void print() {
        cout << "l: " << l << '\n';
        cout << "r: " << r << '\n';
        cout << "u: " << u << '\n';
        cout << "d: " << d << '\n';
    }

private:
    int l = 0;
    int r = 0;
    int u = 0;
    int d = 0;
};

int main() {
    Domain defaultDomain;
    Domain squareDomain(12, 5);
    Domain rectangleDomain(5, 13, 2, 12);
    Domain* declareWithNew = new Domain(2, 3);

    cout << defaultDomain.getArea();
    cout << squareDomain.getArea();
    rectangleDomain.print();
    declareWithNew->print();
}
# PRESENTING CODE

解構函式 Destructor

#include <iostream>
#include <climits>
#include <vector>

using namespace std;

struct Temp {
    Temp(int v): value(v) {}
    Temp(int v, int p): value(v), priority(p) {}

    ~Temp() { cout << "deleted object with priority " << this->priority << '\n'; }

    int value;
    int priority = 0;
};

int main() {
    Temp(5, INT32_MAX);
    if (true) {
        vector<Temp> myList;
        for (int i = 10; i > 0; i--) myList.push_back(Temp(5, i));
        cout << "done\n";
    }
    Temp current(15, 0);
    cout << current.value << '\n';
    cout << "hello world!\n";
}
# PRESENTING CODE

一般函式的問題

  • 在程式邊緣
  • 很浪費空間
  • 引數不能使用 auto

Lambda Expression

進入正題

匿名函式 aka λ

  • since C++ 11
  • 直接宣告在程式碼內
  • 像是變數

一個 λ 的結構

[]() mutable throw() -> TYPE {
    doSomething();
    return aTYPEObject;
}

[] Capture Clause

  • 抓取範圍內變數用
  • 開始一個 lambda 的關鍵
[&] [=] 

[&, a] [=, &a]

[a, &b]

[]

() Parameter List

  • 宣告丟在函式內的變數
  • 長度不可變
  • 全部都得命名
  • 可省略
(int &x)

(string name, int age)

(auto output)

(vector<int> v)

mutable

  • 說明可不可修改傳值外部變數
  • 可省略

throw()

  • 說明是否會輸出例外
  • 可省略

-> TYPE

  • 回傳值類別
  • 可省略

{} body

  • 跟一般函式一樣

範例 Examples

  • 講那麼多誰記得起來
  • 來看實作比較快
  • 來看看他的威力多強大吧

範例 Examples(1)

#include <iostream>

using namespace std;

int main() {
    []{ cout << "hello world!\n"; }();
}

蛤?

範例 Examples(1)

#include <iostream>

using namespace std;

int main() {
    auto sayHi = []{ cout << "hello world!\n"; };
    sayHi();
}

範例 Examples(2)

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<int> v;
    auto initializeVector = [&](int length, int value) {
        v.resize(length);
        for (int& n: v) n = value++;
    };
    
    initializeVector(4, 6);

    for (int& n: v) cout << n << ' ';
}

範例 Examples(3)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    vector<int> v{60,12,30,21,71,50,48,90,87,69,47};

    int standard;
    cin >> standard;

    stable_partition(v.begin(), v.end(), [&](int x) {
        return x < standard;
    });

    for (int& n: v) cout << n << ' ';
}

範例 Examples(4)

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

void quicksort(vector<int>::iterator head, vector<int>::iterator tail) {
    if (tail - head <= 1) return;

    int pivot = *head;
    auto mid = stable_partition(head, tail, [&](int x) {
        return x < pivot;
    });

    quicksort(head, mid);
    quicksort(mid + 1, tail);
}

int main() {
    vector<int> v{60,12,30,21,71,50,48,90,87,69,47};

    quicksort(v.begin(), v.end());

    for (int& n: v) cout << n << ' ';
}

範例 Examples(5)

#include <iostream>

using namespace std;

int main() {
    auto print = [](auto x) -> void {
        cout << x << '\n';
    };

    print("hello");
    print(420.69);
    print(true);
}

範例 Examples(6)

#include <iostream>

using namespace std;

int main() {
    string a, b;
    cin >> a >> b;

    auto sum = [](auto a, auto b) {
        return a + b;
    };

    cout << sum(a, b);
}

範例 Examples(7)

#include <iostream>

using namespace std;

int main() {
    int m, n;
    cin >> m >> n;

    int o = [&, n]() mutable { return ++m + ++n; }();

    cout << m << ", " << n << ", " << o;
}

小知識時間

一些酷酷的知識

Why lambda?

所以為什麼要叫這個名字?

Lambda Calculus

  • 不是微積分
  • Alonzo Church, 1936
  • 圖靈完備
  • 所以原因是什麼?
  • 偶然啦

Lambda Calculus

x ↦ f(x)
(x, y) ↦ x^2 + y^2
x ↦ 2^x \small(5) = 32
(x, y) ↦ x^y \small(3, 2) = 9
  • 基本上就是和程式裡面的寫法長差不多

課程結束

感謝聆聽~

建中電研 42nd Lambda Expression

By Brine

建中電研 42nd Lambda Expression

Made in 2022

  • 221