Page 1
型なき言語に付ける型
Type in untyped languages
#virtual_study_group バーチャル空間勉強会#0
公開日:
by USAMI Kenta @tadsan
にClusterのバーチャル空間で開催された『バーチャル空間勉強会#0』でライトニングトーク(5分)として発表しました。
型なき言語に付ける型
Type in untyped languages
#virtual_study_group バーチャル空間勉強会#0
お前誰よ
うさみけんた (@tadsan)
/ Zonu.EXE
近況
話しました
仕方がないので全 然違う話をします
本日のお題
型、ついて ますか?
型については結構 雑な印象で見解を
語るひとが多い
俺も俺も
型があるから変更に強い
というひとも居れば、
型がないから変更に強い
というひとも居る
???
型
よくわからん
私もだ
intとboolとか
でしょ
読むがよい
‒Benjamin C. Pierce 著/住井英二郎 監訳/遠藤侑介・酒井政裕・今井敬吾・黒木裕介・
今井宜洋・才川隆文・今井健男 訳 『型システム入門 プログラミング言語と型の理論』
(オーム社、978-4-274-06911-6、2013年)サンプル
‒Benjamin C. Pierce 著/住井英二郎 監訳/遠藤侑介・酒井政裕・今井敬吾・黒木裕介・
今井宜洋・才川隆文・今井健男 訳 『型システム入門 プログラミング言語と型の理論』
(オーム社、978-4-274-06911-6、2013年)サンプル
(一章はサンプルとし てPDFが無料でダウ
ンロードできます)
正しい、完璧に 正しいのだが
最初から
用語多すぎ
説明の抽象度が
高すぎて現実との ギャップ大きすぎ
この1章の内容を解き ほぐして説明するだけ
で何時間も話せそう
そのほかの型とかプロ グラミング言語論の本 を読むと数式みたいな
のが出てきてワケワカラン
型について
ちょっと知りたい
だけなのに
世の中の
人と型
型を使っているが 思索の対象として
向き合ってないひと
特定の言語の型とだ
け向き合ってる人
抽象概念の型と
向き合ってるひと
いろんな
背景の人が居る
動的言語を使っていると 静的型付き言語利用者か ら冷ややかに見られがち
やーい
型なし型なし
型はあるんだ!
実行時にあるんだ!
そういうことをまじめに 主張すると憐れみを湛え
た目で見られはじめる
真の型なし言語も 複数あるが今回は
割愛しました
型
わかりたく ないですか
このトークに
結論はない
実際の言語の型から
いきましょう
C言語
よくわからんけど型がだるい
#include <stdio.h>
long add(long a, long b) {
return a + b;
}
int main(void) {
unsigned int x = 1, y = 2;
printf("%d + %d = %d\n", x, y, add(x, y));
}
私たちFラン情報科学生は 情弱なのでまともな説明 もないカビの生えた教科
書でC言語を叩き込まれる
私の入門者時代のC
言語理解は曖昧
なので曖昧なままで
次の話に進めます
さておき
短くなってべんり
// JavaScript
function add(a, b) {
return a + b;
}
const x = 1, y = 2;
console.log(`${x} + ${y} + ${add(x, y)}`);
もっと短くなってべんり
# Ruby
def add(a, b)
a + b
end
x = 1; y = 2
puts "#{x} + #{y} + #{add x, y}"
そういう俺たちが
動的言語に触れると
こうなる
型とか
要らんやろw
そうだな
見ればわかるだろ
# Ruby
オブジェクトが生えてたら何でもいい
# to_s
def show(obj)
puts obj.to_s
end
常識的に考えて
# Ruby
足し算できるものならなんでもいいし
#
ジェネリクスとかなくてもいいw
#
def add(a, b)
a + b
end
def show(obj)
puts obj.to_s
end
引数が少ないうちはな…
# Ruby
user = User.findBy(id: params[:user_id])
引数が増えてくると
# Ruby
obj = palpunte(
user_id,
????, ????, ????,
)
p obj
実装を直接見に
行く機会が増える
引数が増えてくると
# Ruby
実装を見ないと期待するオプションに何を渡せばいいのか
#
def palpunte (id, foo, bar, buz)
p [id, foo, bar, buz]
end
というか見てもよくわからない
#
素朴に書くと引数がわからん
# Ruby
実際にはキーワード引数だけで表現できる
#
def palpunte (id: nil, **options)
raise TypeError if id.nil?
foo ||= "default foo" bar ||= "default bar" buz ||= "default buz"
p [id, foo, bar, bar]]
end
だんだん型チェックが増えてく
# Ruby
raise TypeError unless foo.instance_of?(String) raise TypeError unless bar.instance_of?(String) raise TypeError unless buz.instance_of?(String)
いわゆる動的言語 にも型が付く流れ
Flowtype TypeScript
PEP484
mypy
Ruby3 rbi
Sorbet Steep
PHP型宣言
PHPDoc
PhpStorm,Phan
身体は型を
求める
型が付いていない
ということは
どういうことか
可能性は無限大
<?php
/**
可能性は無限大
* @param mixed $a * @param mixed $b
* @return mixed
*/
function add($a, $b)
{
return $a + $b;
}
仮引数宣言がない言語
<?php
function add()
{
$args = func_get_args();
return array_pop($args) + array_pop($args);
}
無限大じゃ 困るんだよ
とはいえ+できる
値という前提がある
ので案外困らない
ほんとに?
PHPの演算子の暗黙的型変換
<?php
error_reporting(0);
想定通り
var_dump(add(1, 2)); // => int(3)
許容範囲
var_dump(add(1.0, 2.0)); // => float(3.0)
許容範囲
var_dump(add('1', '2')); // => int(3)
var_dump(add('', '')); // => int(0) ????? var_dump(add(1, 2, 3)); // => int(3) ?????
えっ
var_dump(add([], [])); // => [] ?????
var_dump(add(PHP_INT_MAX, 1));
// => float(9.2233720368548E+18)
実行時に
型を調べよう
いわゆる動的言語は 実行時に型があるの でそれを検査できる
JavaScriptでは typeof 演算子で
型名文字列がとれる
Python type()
Ruby Object#class
PHPではis_int(),
is_string()などの関数
(gettypeは使いにくい)
可能性を絞り込もう
<?php
/**
可能性は無限大
* @param mixed $a
可能性は無限大
* @param mixed $b
* @return mixed
*/
function add($a, $b)
{
if (!is_int($a)) {
throw new TypeError('Error');
}
if (!is_int($b)) {
throw new TypeError('Error');
}
実装するときに 以外の値が渡ってくる可能性を考えなくて良い
// int
return $a + $b;
}
実行時に変な値に対 して処理が続行する 可能性は避けられる
例外で処理が 停止するので
PHPとかいう
静的型付き
プログラミング言語
静的型付きPHP
<?php declare(strict_types=1);
このメソッドを実装するときに 以外の値が
// int
渡ってくる可能性は考えなくてよい
//
function add(int $a, int $b): int
{
return $a + $b;
}
静的 =
実行しなくても
型が決まってる状態
静的型付き
Statically typed
既に型が決定してる
動的型付け
Dynamic typing
実行時に型を付ける
よくある誤解
静的型=コンパイラ
動的型=インタプリタ
ただしプログラム実行時
のデータの表現方法が
そういう関係になりがち
C言語は
静的型付き
多くの動的言語 はC言語で実装
必ずしも排他の
関係ではない
お使いの言語ランタイム(ruby, python, phpなど)のC言語実装 がどうなっているか、変数がC言 語の型でどう表現されてるか読ん
でみるとおもしろいと思います
PHPは実行時に 型をチェックする
ただし関数と
プロパティに静的に
型を付けられる
ただし静的に型を付けて も実行時にクラッシュす
る可能性があります
型で守られてると はどういう状態か
‒Akinori Abe 『型安全性入門』(Apr 6, 2017)
‒Akinori Abe 『型安全性入門』(Apr 6, 2017)
関数を呼び出す側が間 違って呼び出すことを PHPだけでは防げない
動的言語で完全かつ
健全にするのは
不可能
偽陽性(動かないのに動き そうなフリをしている)こ とを最小にしていくこと
を目指す
コンパイラの代りに
静的型チェッカーを使 おうということになる
PHPでも複数の 型チェッカーが
揃っている
PhpStorm
Phan, Psalm
PHPStan
PHPのソースコードを 解析しても判別できな い型は注釈(annotate) してあげる必要がある
人間が
コメントで
型を書く
人間が型を間違って つけると破綻するの で実際簡単ではない
連想配列(Hash, dict)
を構造体のつもりで
多用されると静的解析
を簡単に破滅できる
と思うでしょ? PHPDocでなら 型をつけられます
PHPに型を付けたり
CIに載せる話は
FANBOXに記事やス ライドを掲載してます
型について学ぶに はどうすればいい
ハードルが高い
(そもそも値段が…)
一章のPDFは無料なので 読んでほしいが難しいの で理解できなくてもいい
型のみならずプログラミ ング言語についてのさま
ざまな概念を学べる
まとめ
仕事で使ってる言語を好 きになるために目を逸ら
さず向き合っていこう