カリー化された関数
qiitaの週間ランキング?の上位に、カリー化された関数の話が出ていたけど、分かりにくいなぁと思ったので、自分なりに記事を書いてみる。
ちなみにカリー化された関数は英語訳するとcurried functionになる。
Standard ML of New Jersey という言語がある。その言語は、メジャーな言語と比べるとなんか癖が強いと思うけど、言語として、いろんな特徴が実装されているように思える。その 1 つにカリー化がある。
smlnjをインストールすると、インタープリタが実行できるようになる。
% sml Standard ML of New Jersey v110.85 [built: Sat Dec 22 16:51:02 2018] - val a: int = 2 + 3; val a = 5 : int
例えばこんな風に。
関数の定義は、
- fun add a b: int = a + b;
こういう構文になる。
呼び出しはこう。
- add 2 4; val it = 6 : int
ところで、smlnjは、静的な型付言語で、関数を定義すると、型が出力される。
- fun increment (a:int) : int = a+1; val increment = fn : int -> int
この場合、incrementという変数に、ラムダ式を代入したような、表記が出力されており、int型の引数を渡すとint型の値が帰ってくるようなのが書かれているのがわかると思う。
引数が増えると、どうなるのか予想して見て欲しい。 最初、僕は
- fun add a b: int = a + b; val add = fn : int, int -> int
こうかと思ってた。でも、違った。
- fun add a b: int = a + b; val add = fn : int -> int -> int
実際はこうだった。 int -> int -> int は、わかりやすく書くと、int -> (int -> int)のことで、これは、実際に、1 つの引数でも呼べることを意味している。
- val add2 = add 3; val add2 = fn : int -> int
これを宣言しておくと、
- add2 5; val it = 8 : int - add2 19; val it = 22 : int
こんな風な呼び出しができるようになる。つまり、部分適用ができるようになる。
もちろん、僕が最初に思ったような書き方もできる。
- fun add (a,b) = a+b; val add = fn : int * int -> int
タプル(tuple)を使用すると最初に思ったような関数を宣言することができる。
こんな風に、部分的な動作をする関数を返すことができる関数をキャリー化された関数というらしい。
正確には、wikiとかをみると、写像とかの詳しい話が出ていて、部分適用が行いやすくなるという程度にとどまっている。
wikiを読むと、カリー化と部分適用を混同するなよって書いてある。
部分適用は、あくまで、add(3)でも呼べるようにすることで、カリー化は、add(x)とした時の動作を規定することって書いてある(ように感じた)。
pythonでのファイルサイズの取得
os.path.getsize(path)を使えばいいらしい。
ファイルサイズ出力のスクリプト作った。
""" print_size.py """ import os import sys if __name__ == '__main__': try: size = os.path.getsize(sys.argv[1]) f = "" if 10**3 <= size < 10**6: f = f"{size//10**3: 4} kB" elif 10**6 <= size < 10**9: f = f"{size//10**6: 4} MB" elif 10**9 <= size < 10**12: f = f"{size//10**9: 4} GB" elif 10**12 <= size < 10**15: f = f"{size//10**12: 4} TB" else: f = f"{size: 4} B" print(f) except OSError: print("The file doesn't exit.", file=sys.stderr) except: print("USAGE: print_size.py path", file=sys.stderr)
% for i in `ls`; for> python ../print_size.py ${i} 640 B 47 B 79 B 11 kB 21 kB 1 MB 1 MB 1 MB 31 kB 3 MB 22 kB 1 MB 3 MB 6 MB 597 kB
すぐ作った割に使えるので、載せずにはいられなかったw
smlnjの中値演算子のやつ
タイガーブックやってたら、中値演算子を定義するものが見つかったので、試してみた。
Standard ML of New Jersey v110.85 [built: Sat Dec 22 16:51:02 2018] - (* 演算子 plus を定義 *) - infix 6 plus; infix 6 plus - (* 演算子 plus2 を定義 *) - infix 8 plus2; infix 8 plus2 - (* 演算子の振る舞いの定義 *) - fun x plus y = x + y; val plus = fn : int * int -> int - fun x plus2 y = x + y; val plus2 = fn : int * int -> int - 2 * 3 plus 4; val it = 10 : int - 2 * 3 plus2 4; val it = 14 : int
plus2は*(結合度6)よりも高く設定してあるので、2 * 3 plus2 4 は2 * (3 + 4)として計算される。infixは左結合の演算子の定義らしいので、右結合の場合は、infixrを使えばいいみたい。右結合というのは、例えば、a = b = c;という文があった場合、多くの言語でb = cが先に実行されるでしょう?それ。
- (* 仮の代入演算子 equal の設定 *); - infixr 4 equal; infixr 4 equal - fun a equal b = ( = print (a^"に"^b^"を代入したとする\n"); = b); - "a" equal "b" equal "c" equal "3"; cに3を代入したとする bに3を代入したとする aに3を代入したとする val it = "3" : string - (* 左結合バージョン *) - infix 4 equal2; infix 4 equal2 - fun x equal2 y = ( = print (x^"から"^y^"\n"); = x); val equal2 = fn : string * string -> string - "2" equal2 "a" equal2 "b"; 2からa 2からb val it = "2" : string
ということになる。
1ss178の考察
定本トランジスタ回路の設計をすすめる。
1ss176(ショットキーバリアダイオード)の代替品を探した。
google先生に頼んだら秋月の1ss178が見つかった。
176~178は同じ?っぽい。違うのは最大定格。使用の際は、圧倒的に最大定格を下回っているので、大丈夫。
If-Vf図を見ると、100mAでVfが0.9V。本に書いてあるのは0.01mAなので、10^-2A@25℃であるので、Vfは0.4V?。まぁダイオードを入れないよりかはマシかなとは思う。これは実験してみたい項目だなぁと思った。
逆電流も考える必要は特にない。今回の回路は。
今回のダイオードは、電圧を無理やり下げるために用いている。
ちょっとしたメモでした。
poj3280 cheapest palindrome
区間DPらしい。 蟻本の練習問題。 基本的なDPって書いてあったのに、できなかったけど()
普通に文字列周りの問題が壊滅的にできないと思った。全然できんし。
これがわかってたらという事柄をあげる
- 全探索の方向
- 最小条件のクリア
解答はこの方のを見れば、かなりわかりやすいと思う。
全探索の方向
"abcdef"という文字列があった時、この問題の場合は、c, bc, cd, bcd, abcd, bcde, abcdeっていうのを先頭からやっていく感じだった。わかんなかったな〜
最小条件のクリア
これは、リンク先の解説に書いてあるんだけど、"abcba"というのがあって、cをみたとき、bcを回文にするには、cの左を消すか、bを右に新たに付け足すという動作をすることになって、結局それのどちらがコストが小さいのかというと付け足すコストと消すコストの小さい方になる、このことは、具体的にメモしないとわかんなかったな。もちろんすでに左右対称ならコストは0になる。
区間DPできるようになりテェな
djangoの時間まわり
以前に、djangoのコードからローカライズされた時間を取得する方法をやったけど、それを含めて整理する。
まず、プロジェクトを立ち上げた時、時間まわりの設定は、
TIME_ZONE = 'UTC' USE_TZ = True
になっている。
djangoのコード内で、日付時間を取得する場合は、以下の二つ?
- datetimeモジュール
- django.utils.timezoneモジュール
この状態で、とりあえず今日の日付と時間を取るならば、
>>> from django.utils import timezone >>> timezone.now() datetime.datetime(2019, 3, 13, 19, 45, 1, 21127, tzinfo=<UTC>) >>> from datetime import datetime >>> datetime.now() datetime.datetime(2019, 3, 13, 19, 45, 15, 660571)
になる。この場合は、TIME_ZONEとUSE_TZの影響で同じ出力になった。
次に、
TIME_ZONE = 'Asia/Tokyo'
に変えると
>>> from django.utils import timezone >>> print(timezone.now()) 2019-03-13 19:43:00.744599+00:00 >>> from datetime import datetime >>> print(datetime.today()) 2019-03-14 04:43:23.253193
datetimeモジュールだけTIME_ZONEの影響を受ける。
だから、基本的に、時間取得なら設定を変えてdatetimeモジュールを使用する?
じゃあ、timezoneは何に使うんだよっていう話になる。
これは、憶測だけど、憶測だけど、憶測だけど、テンプレートを通して取得した場合にのみ使用するのかもしれない。 上のは、manage.pyのshell。
タイガーブック(3)
ml-lexのレキサーを書いていた。
この方のがとてもわかりやすいと思う。 これの 2 章。
tiger.lexを書く。
%s COMMENT
正確には%stateらしい。
COMMENTという状態をあらかじめ定義しておく。
var type function break of end in nil let do to for while else then if array := | & >= > <= < <> = / * - + { } ( ) [ ] . , ; : abcdefg 12345 "ABCDEFG" /* comment has started */
こんな感じのtiger(作るプログラミング言語の名前)のソースコードらしきものを用意しておく。
tiger.lexを修正して、
% sml Standard ML of New Jersey v110.85 [built: Sat Dec 22 16:51:02 2018] - CM.make "sources.cm"; 略 - Parse.parse "test.tig"; VAR 2 TYPE 6 FUNCTION 11 BREAK 20 OF 26 END 29 IN 33 NIL 36 LET 40 DO 44 TO 47 FOR 50 WHILE 54 ELSE 60 THEN 65 IF 70 ARRAY 73 ASSIGN 80 OR 83 AND 85 GE 87 GT 90 LE 92 LT 95 NEQ 97 EQ 100 DIVIDE 102 TIMES 104 MINUS 106 PLUS 108 LBRACE 110 RBRACE 112 LPAREN 114 RPAREN 116 LBRACK 118 RBRACK 120 DOT 122 COMMA 124 SEMICOLON 126 COLON 128 ID(abcdefg) 130 INT(12345) 138 STRING("ABCDEFG") 144 skipping comment skipping comment c skipping comment o skipping comment m skipping comment m skipping comment e skipping comment n skipping comment t skipping comment skipping comment h skipping comment a skipping comment s skipping comment skipping comment s skipping comment t skipping comment a skipping comment r skipping comment t skipping comment e skipping comment d skipping comment EOF 179 val it = () : unit
これで字句解析ができてそうなことを確認できた。 tokens.smlに関数は、定義されているので、tiger.lexを完成させればいいだけ。