今日の内容 高階関数 関数を値として扱う 関数を引数にとる 関数を返す関数 プログラミングの例題 クイックソート 関数を値と扱う 関数を引数にとれる (define (f x) (x 10)) (define (f g) (g 10)) (f add1) 関数を値とする (define (g x) add1) g はadd1という関数を返す (注意:この場合xは使われていない) 温度CからFへの変換 ;; convertCF : lon -> lon 摂氏(Celsius, ℃) 華氏(Fahrenheit, °F) (define (convertCF alon) F = 9/5 * C + 32 (cond [(empty? alon) empty] [else (cons (C->F (first alon)) (convertCF (rest alon)))])) 関数C->F は自分で定義すること. 在庫品(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)))])) プログラムの比較 1 (define (convertCF alon) (define (names aloIR) (cond (cond [(empty? alon) empty] [(empty? aloIR) empty] [else [else (cons (C->F (first alon)) (cons (IR-name (first aloIR)) (convertCF (rest alon)))])) (names (rest aloIR)))])) プログラムの比較 2 (define (convertCF G alon) (cond [(empty? alon) empty] [else (cons (G (first alon)) (convertCF G (rest alon)))])) (define (names G aloIR) (cond [(empty? aloIR) empty] [else (cons (G (first aloIR)) (names G (rest aloIR)))])) プログラムの比較 3 (define (convertCF G x) (cond [(empty? x) empty] [else (cons (G (first x)) (convertCF G (rest x)))])) (define (names G x) (cond [(empty? x) empty] [else (cons (G (first x)) (names G (rest x)))])) プログラムの比較 4 (define (g G x) (cond [(empty? x) empty] [else (cons (G (first x)) (g G (rest x)))])) (define (names G x) (cond [(empty? x) empty] [else (cons (G (first x)) (names G (rest x)))])) 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) => (my-filter >= (list 3 -1 0 5 6 3) 0) => (list 3 5 6 3) (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は自分で定義すること!
© Copyright 2024 ExpyDoc