• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
関数型志向Python - LLまつり2013
 

関数型志向Python - LLまつり2013

on

  • 10,669 views

 

Statistics

Views

Total Views
10,669
Views on SlideShare
10,021
Embed Views
648

Actions

Likes
32
Downloads
36
Comments
0

10 Embeds 648

https://twitter.com 372
http://moraprogramming.hateblo.jp 166
http://syobochim.hatenablog.com 102
http://nuevospowerpoints.blogspot.com 2
https://tweetdeck.twitter.com 1
http://hashtagsjp.appspot.com 1
http://nuevospowerpoints.blogspot.com.au 1
http://cloud.phpfoxapps.com 1
http://tweetedtimes.com 1
https://www.google.co.jp 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    関数型志向Python - LLまつり2013 関数型志向Python - LLまつり2013 Presentation Transcript

    • 関数型指向 Python LLまつり2013 / @esehara
    • お前 誰だ
    • Esehara Shigeo(29) 言語:Python OS:Ubuntu + Amesome(タイル型) 好きなMonad: Maybe 気になる言語: Prolog 所属: 株式会社マリーチ
    • このスライドは以下に、 既にアップされているので スライドを手元でみたいときは http://www.slideshare.net/esehara/ から見てください
    • ところで 皆さんに 質問が あります
    • 関数型言語 使って ますか?
    • そもそも 「関数型言語」 ってなんですか?
    • (eq? functional lisp) => #t / #f ?
    • (eq? functional lisp)
    • 『計算機プログラムの構造と解釈』 特徴のもっとも著しいのは プロセスの手続き (procedures) というLispによる記述自体が Lispデータとして表現, 処理出 来ることである. (p. 2)
    • プロセスの手続き というLispによる 記述……?
    • 手続きって 関数型 と違うものなの?
    • 抜き打ち調査
    • (eq? functional X_language)
    • ERROR: Unbound valiable: functional
    • type 関数型言語 = Maybe BuzzWord
    • ここまで 前置き
    • なぜ関数型「指向」としたか ●ここでは「関数型言語」の正 確な定義については考えな い (定義的には透明参照性があり、その ことによって副作用を封じ込める云々 があるが、そこまで厳密に考えると Maybe Me = 死ぬ | 殺される)
    • 正直、 OCaml Meeting Proof Summitが 同日で助かった
    • なぜ関数型「指向」としたか ●そこで、あえて「関数型言語」とは別に 「プログラムの書き方」として「関数型 指向」を使う →「関数型指向」と定義するものは、「関数を連鎖さ せることによって、手続き=プロセスを記述する」に 着目をすることとする。 →数学的な意味での「関数」の意味と、Pascal以降 の「プログラム」的な意味での「関数」を分離する
    • Pythonでの例 from __future__ import print_function one = lambda: 1 two = lambda: 2 to_list = lambda *fs: [f() for f in fs] do = lambda *args: args[0](*args[1:]) do(print, do(sum, do(to_list, one, two)))
    • 素直に書くと…… one = 1 two = 2 test_data = [one, two] result_sum = sum(test_data) print result_sum
    • ところで 皆さんに 質問が あります
    • 「代入」って 簡単ですか?
    • よくある代入の説明 変数は「箱」です。 代入は、変数という「箱」に 値を保管するということです。
    • よくある代入の説明 変数は「箱」です。 代入は、変数という「箱」に 値を保管するということです。 どういう ことだ?
    • 抜き打ちテスト
    • def test(origin_list): result = origin_list result[0] = "FooBar" return result a = [1, 2, 3] # リストの最初を # Foobarにする print test(a) # [1, 2, 3]を出したい print a
    • [“Foobar”, 2, 3] [“Foobar”, 2, 3] 結果
    • 代入の難しさ ● 値渡しと参照渡しがある ● 「何が値渡し」か「何が参照 渡し」かは、言語の仕様に よって変化する
    • 真夏の怪談
    • 「代入の恐怖」
    • あれは 某プロジェクトの ことでした
    • プロジェクトは PHPで 書かれて いたんですよ……
    • フレームワークは CakePHP
    • コントローラを 開いたら……
    • メソッド 2500行
    • あなたの隣にも、ほら……
    • 代入の難しさ ● 代入は「データ」をとりあえずおいておく 場所として機能する ● そうすると、代入しまくってなんとかしよ うとする ● 何も考えないとメソッドや関数が肥大化 する
    • 代入の難しさ
    • 「Object Calisthenics」 インスタンス 変数は二つまで
    • 「関数」を意識する ● 細かく「関数」(or メソッド)に することで、その操作が何を 目的にしているのかというの を意識的に命名できる
    • 例:Fizzbuzz ルール ● 1..100の数が入力される ● 3で割り切れる数は”Fizz” ● 5で割り切れる数は”Buzz” ● 3と5で割り切れる数は”FizzBuzz” ● 上記に当てはまらない場合、数を返す
    • 素直に書くと…… def fizzbuzz(x): if x % 15 == 0: return "FizzBuzz" if x % 3 == 0: return "Fizz" if x % 5 == 0: return "Buzz" return x for x in range(1, 100): print fizzbuzz(x)
    • ここで 問題です
    • 問題: lambda_fizzbuzz from __future__ import print_function def function_fizzbuzz(x): #fizzとbuzzの関数を定義すること #ただし、lambdaだけで定義せよ return fizz(buzz(x)) [print(function_fizzbuzz(x)) for x in range(1, 100)]
    • lambda とは
    • Pythonにおけるlambda origin = lambda x: x # <function __main__.<lambda>> def _lambda(x): return x custom = _lambda #要するにfunction objectを渡している # >>> (lambda x: x * 2)(3) # 6
    • 考え方 ● 出力結果の可能性は、入力された数, “Fizz”, “Buzz”, “FizzBuzz” ● 結果は「数」か「文字」 ● 「文字」の場合は、3で割り切れる、5で割り切れ る、15で割り切れるときに出力する ● 15で割り切れる = 3で割り切れ、かつ5で割り切れる ● 3, 5 をフラグで管理し、3で割り切れるときは”Fizz”、 5で割り切れるときは”Buzz”に置換し、両方に当ては まる場合は、二つをあわせる。
    • 条件演算子を使おう _buzz = lambda x: “” if x % 3 else “Buzz” # ある値の後に “if” が入ると、 # あいだの値がFalseだと、else以降の値が # 採用される # ちなみに、Pythonは 0, “”, [], () を 判定すると # False が返ってくるので、割り切れるときは # False になると理解する
    • 条件演算子を使おう _fizz = lambda x: “” if x % 3 else “FIzz” _buzz = lambda x: “” if x % 5 else “Buzz” # 同じような式を省略できないのか
    • クロージャと 和解せよ
    • クロージャを使おう 変数のスコープは ソースコード内の位置に よって決定され 入れ子にされた関数は 外側のスコープで宣言された 変数にアクセスする https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Closures
    • 外側に スコープが ある変数?
    • クロージャを使おう def closure(x): def _function(): return x return _function one = closure(1) print one() lambda_closure = lambda x: lambda: x two = lambda_closure(2) print two()
    • クロージャを使おう ポイント ●関数内部で定義された関 数は、その関数を定義しよ うとしている関数に渡され た引数を参照できる
    • クロージャを使おう ポイント ●関数内部で定義された関 数は、その関数を定義しよ うとしている関数に渡され た引数を参照できる お前は 何を 言っている
    • 想像してごらん…… クロージャ関数は 「箱」である
    • 想像してごらん…… クロージャ関数 「xって値を この関数に入れておき ましたので、呼び出せ ば取り出せますよ」
    • あれ、この説明 どこかで……
    • よくある代入の説明 変数は「箱」です。 代入は、変数という「箱」に 値を保管するということです。
    • よくあるクロージャ関数の説明 クロージャ関数は「箱」です。 クロージャ関数は、 関数という「箱」に 値を保管するということです。
    • 抜き打ちテスト
    • closure = lambda x: lambda: x foo = closure([1, 2, 3]) print foo() foo()[0] = "Foobar" print foo()
    • あ、ここ代入で やったところだ! (by. 受験生)
    • [1, 2, 3] [“Foobar”, 2, 3] 結果
    • 「代入」は 何度でも 蘇る
    • 変数が死んでも 第二、 第三の代入 が現れるだろう
    • 「関数」を 渡していると いって 油断するな
    • deepcopy と和解せよ
    • from copy import deepcopy closure = lambda x: lambda: deepcopy(x) array = closure([1, 2, 3]) array()[0] = "Foobar" print array()
    • [1, 2, 3] 結果
    • deepcopyと和解せよ ポイント ●深いコピー(deep copy)は新たな複 合オブジェクトを作成し、その後元の オブジェクト中に見つかったオブジェ クトのコピーを挿入します。 http://docs.python.jp/2/library/copy.html?highlight=deepcopy
    • 「似非原さん」
    • 「先ほどから 色々と 説明して いますが」
    • 「lambda fizzbuzz 進捗どうですか」
    • ウッ
    • 問題: lambda_fizzbuzz from __future__ import print_function def function_fizzbuzz(x): #fizzとbuzzの関数を定義すること #ただし、lambdaだけで定義せよ return fizz(buzz(x)) [print(function_fizzbuzz(x)) for x in range(1, 100)]
    • 解答: lambda_fizzbuzz from __future__ import print_function _div_to_str = lambda x, y: lambda _x: "" if _x % x else y _buzz = _div_to_str(5, "Buzz") buzz = lambda x: [_buzz(x), x] __fizz = _div_to_str(3, "Fizz") _fizz = lambda x: [__fizz(x[1]) + x[0], x[1]] fizz = lambda x: print(_fizz(x)[0]) if (_fizz(x)[0]) else print(x[1]) fizzbuzz = lambda x: fizz(buzz(x)) [fizzbuzz(x) for x in range(1, 100)]
    • これが lambdaの 力である
    • 関数型指向 Python LLまつり2013 / @esehara
    • 関数型指向 Python LLまつり2013 / @esehara 改め
    • Lambda型 指向Python LLまつり2013 / @esehara
    • 「似非原さん」
    • 「先ほどから 色々と 説明して いますが」
    • 「プレゼンの 納期(20分) どうですか」
    • ウッ
    • 課題
    • decorator と和解せよ
    • 問題: decorator_fizzbuzz from __future__ import print_function @fizz @buzz def decorator_fizzbuzz(x): pass [print(decorator_fizzbuzz(x)) for x in range(1, 100)]
    • Pythonにおけるdecorator PEP 318 Decorators for Functions and Methods
    • Pythonにおけるdecorator @dec2 @dec1 def func(arg1, arg2, ...): pass def func(arg1, arg2, ...): pass func = dec2(dec1(func))
    • 例: lambda_fizzbuzz fizzbuzz = lambda x: fizz(buzz(x))
    • 例: decorator_fizzbuzz decorator_fizzbuzz = fizz(buzz(func))
    • ご静聴 ありがとう ございました
    • PyConの成功 心からお祈り しています