270 likes | 392 Views
今日の内容. 高階関数 関数を値として扱う 関数を引数にとる 関数を返す関数 プログラミングの例題 クイックソート. 関数を値と扱う. 関数を引数にとれる (define (f x) (x 10)) (define (f g ) ( g 10)) (f add1) 関数を値とする (define (g x) add1) g は add1 という関数を返す (注意:この場合 x は使われていない). 温度 C から F への変換. ;; convertCF : lon -> lon (define (convertCF alon)
E N D
今日の内容 • 高階関数 • 関数を値として扱う • 関数を引数にとる • 関数を返す関数 • プログラミングの例題 • クイックソート
関数を値と扱う • 関数を引数にとれる • (define (f x) (x 10)) • (define (f g) (g 10)) • (f add1) • 関数を値とする • (define (g x) add1) • g はadd1という関数を返す • (注意:この場合xは使われていない)
温度CからFへの変換 ;; convertCF : lon -> lon (define (convertCF alon) (cond [(empty? alon) empty] [else (cons (C->F(first alon)) (convertCF (rest alon)))])) 関数C->F は自分で定義すること. 摂氏(Celsius, ℃) 華氏(Fahrenheit, °F) F = 9/5 * C + 32
在庫品(inventory-record) • 在庫品は構造体として次のように定義する. • (def-struct IR (name nitems price) • name は品名 (シンボル) • nitemsはこの在庫品の在庫量 (数) • priceは価格 (数)
在庫品目名リスト ;; names : loIR -> los (define (names aloIR) (cond [(empty? aloIR) empty] [else (cons (IR-name (first aloIR)) (names (rest aloIR)))]))
(define (convertCF alon) (cond [(empty? alon) empty] [else (cons (C->F (first alon)) (convertCF (rest alon)))])) (define (names aloIR) (cond [(empty? aloIR) empty] [else (cons (IR-name (first aloIR)) (names(rest aloIR)))])) プログラムの比較 1
(define (convertCFGalon) (cond [(empty? alon) empty] [else (cons (G(first alon)) (convertCFG(rest alon)))])) (define (names GaloIR) (cond [(empty? aloIR) empty] [else (cons (G(first aloIR)) (namesG(rest aloIR)))])) プログラムの比較 2
(define (convertCFG x) (cond [(empty? x) empty] [else (cons (G (first x)) (convertCFG (rest x)))])) (define (names G x) (cond [(empty? x) empty] [else (cons (G (first x)) (namesG (rest x)))])) プログラムの比較 3
(define (gG x) (cond [(empty? x) empty] [else (cons (G (first x)) (gG (rest x)))])) (define (namesG x) (cond [(empty? x) empty] [else (cons (G (first x)) (namesG (rest x)))])) プログラムの比較 4
map (define (map f x) (cond [(empty? x) empty] [else (cons (f (first x)) (map f (rest x)))]))
Mapを用いた再定義 ;; convertCF-from-map : lon -> lon (define (convertCF-from-map alon) (map C->F alon)) ;; names-from-map : loIR -> los (define (names-from-map aloIR) (map IR-name aloIR))
多相型(polymorphism) • map : (number -> number) (listof number) -> (listof number) • map : (IR -> symbol) (listof IR) -> (listof symbol) • f : X -> Y • map : (X -> Y) (listof X) -> (listof Y)
Filter(my-filter) (define (my-filter rel-op alon t) (cond [(empty? alon) empty] [(rel-op (first alon) t) (cons (first alon) (my-filter rel-op (rest alon) t))] [else (my-filter rel-op (rest alon) t)]))
Filter (my-filter) • (define (my-filter rel-op alon t) .... ) • ;; (rel-op elem t) がtrueになる要素をリストalonから • ;; 取り出し,新たなリストを作る • (my-filter > (list 3 -1 0 5 6 3) 0) => • (list 3 5 6 3) • (my-filter >= (list 3 -1 0 5 6 3) 0) => • (list 3 0 5 6 3) • (my-filter eq? (list 2 5 3 8 6 3) 3) => • (list 3 3)
Filter(my-filter)を使う例: find ;; find : (listof IR) symbol -> (listof IR) (define (find aloir t) (define (eq-IR? ir p) (symbol=? (IR-name ir) p) (my-filter eq-IR? aloir t))
ラムダ式 • 関数を表す表現 • <exp> ::= … | (lambda (<var> ... <var>) <exp>) • (lambda (x y) (+ (* x x) (* y y))) • (lambda (x) x) • (lambda (x y) x) • (lambda (x y) (x y y))
ラムダ式の例 • (lambda (x c) (> (* x x) c)) • (lambda (ir p) (< (IR-price ir) p)) • (lambda (ir p) (symbol=? (IR-name ir) p))
例 • ((lambda (x y) (+ (* x y)3)) 1 2) • ((lambda (f x) (f x x)) + 10)
Quick sortの作成:ラムダ式を使う例 ;; quick-sort : (listof number) -> (listof number) ;; to create a list of numbers with the same numbers as ;; alon sorted in ascending order (define (quick-sort alon) (cond [(empty? alon) empty] [else (append (quick-sort (smaller-items alon (first alon))) (list (first alon)) (quick-sort (larger-items alon (first alon))))]))
quick-sortの動き • (quick-sort (list 3 4 2 6 5 1)) • 3を取り出す • 3より小さい要素2,1 を選び出し(list 2 1)を作る • (quick-sort (list 2 1)) => (list 1 2) • (list 3)を作る • 3より大きい要素4,6,5を選び出し (list 4 6 5)を作る • (quick-sort (list 4 6 5)) => (list 4 5 6) • (list 1 2) (list 3)(list 4 5 6)を結合(append)する • (list 1 2 3 4 5 6)
larger-items ;; larger-items : (listof number) number -> (listof number) ;; to create a list with all those numbers on alon ;; that are larger than threshold (define (larger-items alon threshold) (cond [(empty? alon) empty] [else (if (> (first alon) threshold) (cons (first alon) (larger-items (rest alon) threshold)) (larger-items (rest alon) threshold))]))
smaller-items ;; smaller-items : (listof number) number -> (listof number) ;; to create a list with all those numbers on alon ;; that are smaller than threshold (define (smaller-items alon threshold) (cond [(empty? alon) empty] [else (if (< (first alon) threshold) (cons (first alon) (smaller-items (rest alon) threshold)) (smaller-items (rest alon) threshold))])) my-filterを使うと簡単
システム組み込み関数 filter • 注意 システム組み込み関数 filterがある. • (filter rel-op alist) • rel-opは一引数の述語 (真理値を返す関数) • alistはリスト • (filter even? (list 1 2 3))
larger-items, smaller-itemsの再定義 (define (larger-items alon threshold) (my-filter > alon threshold)) (define (smaller-items alon threshold) (my-filter < alon threshold))
filterを使ったmy-filterの再定義 (define (my-filter rel-op alon threshold) (filter (lambda (x) (rel-op x threshold)) alon))
最初のquick-sortの問題点 (quick-sort (list 3 2 2 5 5 6 1 3 2)) • (list 1 2 2 2 3 3 5 5 6)が答えであってほしい • (list 2 2 1 2) (list 3) (list 5 5 6)に分割されてしまう (quick-sort (list 3 2 2 5 5 6 1 3 2)) => (list 1 2 3 5 6) • ここで,2,3,5,6がひとつになってしまう
正しいquick-sort (define (quick-sort alon) (cond [(empty? alon) empty] [else (append (quick-sort (not-larger-items (rest alon) (first alon))) (list (first alon)) (quick-sort (larger-items (rest alon) (first alon))))])) not-larger-itemsは自分で定義すること!