Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
蛇を蟹っぽくお型付け
wolf_cpp
December 18, 2019
Technology
1
310
蛇を蟹っぽくお型付け
wolf_cpp
December 18, 2019
Tweet
Share
Other Decks in Technology
See All in Technology
SwiftUI Layout
auramagi
1
120
フィンテック養成勉強会#23
finengine
0
210
Empath Company Deck
empathpr
0
180
Swift Regex Builder
kumamotone
1
110
FastConnect 冗長性のベスト・プラクティス
ocise
0
140
How to start with DDD when you have a Monolith
javujavichi
0
370
Retca Cloud
bau
0
580
ソフトウェアテスト自動化、一歩前へ
yoshikiito
7
1.1k
Camp Digital 2022: tailored advice
kyliehavelock
0
150
ノーコードで Stripeを使いこなす3つの方法 / jp-stripes-online-vol-4
stripehideokamoto
0
320
DOM Invader - prototype pollution対応の衝撃 - / DOM Invader - prototype pollution
okuken
0
170
サーバレスECにおける Step Functions の使い方 〜ステートマシン全部見せます!〜
miu_crescent
0
200
Featured
See All Featured
How to name files
jennybc
40
61k
Side Projects
sachag
450
37k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
212
20k
Designing for humans not robots
tammielis
241
23k
Gamification - CAS2011
davidbonilla
75
3.9k
Making the Leap to Tech Lead
cromwellryan
113
7.4k
Fontdeck: Realign not Redesign
paulrobertlloyd
73
4.1k
ParisWeb 2013: Learning to Love: Crash Course in Emotional UX Design
dotmariusz
100
5.9k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
181
15k
How GitHub Uses GitHub to Build GitHub
holman
465
280k
Art, The Web, and Tiny UX
lynnandtonic
280
17k
Design by the Numbers
sachag
271
17k
Transcript
蛇を蟹っぽくお型付け wolf-cpp / CADDi, Inc.
import me me.company = ‘キャディ株式会社’ me.language = [‘python’, ‘rust’, ‘cpp’]
me.hobby = [‘violin’, ‘coffee’] me.age = 23 me.nickname = [ ‘きむD’, ‘をるふちゃん’ ] # NOTE: 重要 me.twitter = ‘@wolf_cpp’ # -*- coding: utf-8 -*-.
import おしごと 製造業における社会課題をテクノロジーで解決する 見積もり算出のシステム化 → 3D図面自動注文 品質・価格・納期の最適化 → 確定発注 一括発注で調達担当者さまの負担減
おしごと.wolf_cpp 見積もりの計算システムのコアを担当 -型安全で -計算の過程が式木(expression_tree)として出力 -SI+Jpy単位を扱える・自動変換されること -セグフォしないこと
かなしみ.rs Rustしか選択肢なくね? いや。いいんだけどね。
Rustよくわからんてひと • データの所有権という概念がある → データを変数間で共有することはできない • コードをコンパイルし、OSで直接実行可能なバイナリを吐く(LLVM基盤を利用) • C++より実行が速いかもしれん •
トレイトによって型が提供しなければいけない機能を強制できる 所有権とトレイトがめっちゃむずかしい。つらい。
しかし.py コスト計算システムのサーバができてきた → テストツールが必要 正となるデータはビジネスサイドからExcelで提供されるよ!(白目) これはPythonの出番 (☝ ՞ਊ ՞)☝
書いてみた if coating_type == ‘メラミン樹脂塗装’: coating_type = ‘melamine_resin’ elif coating_type
== ‘アクリル樹脂塗装’: coating_type = ‘acrylic_resin’ elif coating_type == ‘ポリウレタン樹脂塗装’: coating_type = ‘polyurethane_resin’ elif coating_type == ‘粉体塗装’: coating_type = ‘powder_resin’ else: raise CoatingError(“無いよそんな塗装”)
問題点 しょうがないのはわかってるけどさ switch文がないのはやっぱりつらい 10個くらいelifを連鎖させているうちにwolf-cppは考えました。 なんでPythonにはmatch式がないんだろう、と。
Rustのmatch式 match x { 1 => println!("one"), 2 => println!("two"),
3 => println!("three"), 4 => println!("four"), 5 => println!("five"), _ => println!("something else"), }
Python版 案① def match(var, matches, *, default): return matches[var] if
var in matches else default a = 12 res = match(a, { 1 : 'a', 12 : 'b', 123 : 'c', }, default = 'd',)
Python版 案② def match_apply(var, matches, *, default): return matches[var](var) if
var in matches else default() a = 123 match_apply(a, { 1 : lambda x: print('a'), 12 : lambda x: print('b'), 123 : lambda x: print('c'), }, default = lambda x: print('d'),)
書いてみた if not outer_diameter: outer_diameter = ‘0’ if not inner_diameter:
inner_diameter = ‘0’ request_pb.thickness = str( float(outer_diameter) – float(inner_diameter) ) def empty_to_zero(in): if not in: in = ‘0’ request_pb.thickness = str( float( empty_to_zero(outer_diameter) ) – float( empty_to_zero(inner_diameter) ) ) ------------------------------------------------------
問題点 型安全じゃないのはいったん目をつぶろう 変換掛けたくなるたびに両側にカッコをつけるのがつらい Ctrl + LeftArrow を連打 (あるいはHome Key)してるうちにwolf-cppは考えました。 ドット演算子かなんかでつなげて書けないのかと。
• 変数をラップするクラス • Pythonは参照で変数をしばき倒す仕様なので copy.deepcopy を利用 https://gist.github.com/wolf-cpp/09ed5df41294c49d94706813bfecef05 手が滑って謎ライブラリを生やした class Var:
def __init__(self, item): self.value = copy.deepcopy(item.value) if isinstance(item, Var) else copy.deepcopy(item)
https://gist.github.com/wolf-cpp/09ed5df41294c49d94706813bfecef05 castをメソッドで生やした def cast(self, t): return Var( t( copy.deepcopy(self.value) )
) # キャストに失敗したら第二引数の値を返す def try_cast(self, t, default_value): try : res = t( copy.deepcopy(self.value) ) except (ValueError): res = default_value return Var( res )
https://gist.github.com/wolf-cpp/09ed5df41294c49d94706813bfecef05 castをメソッドで生やした arr = [Var(‘’), Var(‘1’), Var(‘12’) for i in
arr: i.cast(int) -------- arr = [Var(‘’), Var(‘1’), Var(‘12’) for i in arr: i.try_cast(int, 0) ValueError: invalid literal for int() with base 10: '' OK!
https://gist.github.com/wolf-cpp/09ed5df41294c49d94706813bfecef05 map, apply def apply(self, fn): self.value = fn(self.value) return
self def match(self, input_dict, *, default): return Var( match(self.value, input_dict, default=default) ) # matchに失敗したら元の値を返す def try_match(self, input_dict): return Var( match(self.value, input_dict, default=self.value) )
https://gist.github.com/wolf-cpp/09ed5df41294c49d94706813bfecef05 map, apply a = Var(2) a.map({ 1: ‘a’, 2:
‘b’, 3: ‘c’, }, default= ‘d’) b = Var(100) b.apply( lambda x: x**2 ) c = Var(3) c.try_map({ 1: ‘e’, 2: ‘f’, 3: ‘g’, }) b 3 10000
https://gist.github.com/wolf-cpp/09ed5df41294c49d94706813bfecef05 Nimっぽいって言われた。 def print(self): print(self.value) return self • Selfを返すことで、そのままつなげて書けるよ! c
= Var(‘bar’) c.try_map({ ‘foo’: 1, ‘bar’: ‘2’, ‘baz’: 3, }).print() 2
そして地獄のoperator定義
Q. Rustっぽいだと? 所詮ダックタイピングだろ
Q. Rustっぽいだと? 所詮ダックタイピングでしょ A. せやな……実装してやんよ
None
https://gist.github.com/wolf-cpp/09ed5df41294c49d94706813bfecef05 __set_attr__ でちょっと黒魔術 • setattr(object, name, value) • オブジェクト、文字列、任意の値を渡す。 •
setattr(x, ‘foobar’, 123) は x.foobar = 123 と等価 • つまり、この関数をオーバーロードしてあげれば 「代入しようと思った??ざんねーん!!」 みたいなこともできる。
__set__attr__の中で = で代入することはできない(set_attrが再帰的に呼ばれちゃう) object.__setattr__(self, ‘変数名’, 値) で代入する また、クラスのメンバ変数にアクセスしたければ以下のようにする self.__dict__[‘変数名’] これは以下の文と等価
self.変数名
完成したクラス a = Var(100) a.value = 1 a.print() b =
TypeSafe(‘a’) b.value = 2 1 AttributeError: TypeSafe class does not allow assignment wrong type: `TypeSafe.value (<class 'str'>) = 2 (<class 'int'>)`
おまけ • 実はさっきのクラス TypeSafe の第2引数 mut を False にすると 再代入そのものが禁止になる仕様
b = Const(‘a’) b.value = ‘b’ AttributeError: const-TypeSafe does not allow re- assignment to `value`
上司に見せたら
上司に見せたら それ以上聞きたくないって言われた。。。 (´・ω・`)
print(‘Thank you!’)