Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
functionalなアプローチで動的要素を排除する
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Ryoichi SEKIGUCHI
January 18, 2025
Programming
1
4.3k
functionalなアプローチで動的要素を排除する
Ryoichi SEKIGUCHI
January 18, 2025
Tweet
Share
More Decks by Ryoichi SEKIGUCHI
See All by Ryoichi SEKIGUCHI
非同期処理とは何なのか
ryopeko
0
120
Ruby makes everything
ryopeko
0
150
正しく失敗しながら進むプロダクト開発/railsdm2018
ryopeko
10
6.2k
CircleCI を使って自動(ほぼ)でセキュリティアップデート / circleci meetup
ryopeko
4
590
Kaizen Platform でやっている Kaizen Week というイベントについて / kaize week tokyurubykaigi 10
ryopeko
2
1.2k
mysql casual talks vol7
ryopeko
0
2.6k
rubyhiroba
ryopeko
6
1.4k
devsumi2014-dena-bootcamp2014
ryopeko
40
65k
jtrk02
ryopeko
0
5.8k
Other Decks in Programming
See All in Programming
Vuetify 3 → 4 何が変わった?差分と移行ポイント10分まとめ
koukimiura
0
180
CS教育のDX AIによる育成の効率化
niftycorp
PRO
0
160
20260320登壇資料
pharct
0
120
「接続」—パフォーマンスチューニングの最後の一手 〜点と点を結ぶ、その一瞬のために〜
kentaroutakeda
3
1.9k
Ruby and LLM Ecosystem 2nd
koic
1
1.3k
ベクトル検索のフィルタを用いた機械学習モデルとの統合 / python-meetup-fukuoka-06-vector-attr
monochromegane
2
510
Reactive ❤️ Loom: A Forbidden Love Story
franz1981
2
140
20260315 AWSなんもわからん🥲
chiilog
2
170
Angular-Apps smarter machen mit Gen AI: Lokal und offlinefähig - Hands-on Workshop!
christianliebel
PRO
0
130
野球解説AI Agentを開発してみた - 2026/02/27 LayerX社内LT会資料
shinyorke
PRO
0
360
Symfony + NelmioApiDocBundle を使った スキーマ駆動開発 / Schema Driven Development with NelmioApiDocBundle
okashoi
0
210
モックわからないマン卒業記 ~振る舞いを起点に見直した、フロントエンドテストにおけるモックの使いどころ~
tasukuwatanabe
3
420
Featured
See All Featured
Agile that works and the tools we love
rasmusluckow
331
21k
Utilizing Notion as your number one productivity tool
mfonobong
4
270
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
100
HDC tutorial
michielstock
1
580
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
0
240
Mind Mapping
helmedeiros
PRO
1
130
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
How to build a perfect <img>
jonoalderson
1
5.3k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
10k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.4k
RailsConf 2023
tenderlove
30
1.4k
Testing 201, or: Great Expectations
jmmastey
46
8.1k
Transcript
functionalなアプローチで 動的要素を排除する 2024/01/18 東京Ruby会議12 @ryopeko
• 関口亮一 • @ryopeko • Backend Engineer
目次 • 動的なアプローチ • Rubyにおける関数型向けの機能 • functionalなアプローチ • ユースケース •
双方の比較 • まとめ
動的なアプローチ
Rubyにおける強力な武器のひとつ
動的なアプローチのための機能 • public_send • define_method • etc…
メタプログラミング + 動的評価
強力だが強い責任が伴う機能
動的なアプローチのメリットデメリット
動的なアプローチのメリット • 記述量の低減 • 多少の差分を吸収できる • カッコいい • etc…
動的なアプローチのデメリット • 読み解くのに知識が必要 • 実行時になって動作が確定する • grepが効かないケースがある • カッコいい •
etc…
動的なあれこれ class Foo %w/a b/.each do |c| define_method ("method_#{c}".to_sym) do
# do something end end end
動的なあれこれ public_send(:method_name, "foo")
動的なあれこれ types = ["a", 1] types.each do |type| case type
when String public_send(:method_for_string) when Integer public_send(:method_for_integer) else raise ArgumentError end end
Rubyにおける関数型向けの機能
Rubyにおける関数型向けの機能 • Lambda, Proc • curry (カリー化) • Proc#<<,>>(関数合成) •
etc…
関数オブジェクトの生成 lambda {} Proc.new {} -> {}
カリー化 f = -> (arg1, arg2) { arg1 + arg2
}.curry(2).call(1) f.call(2) #=> 3
関数合成 f1 = -> (arg1, arg2) { arg1 + arg2
}.curry(2).call(1) f2 = -> (arg3) { arg3.odd? } f = f1 >> f2 f.call(2) #=> true
おまけ(method objectもcurry化できる) def method_a(arg1, arg2) # do something end f_method
= method(:method_a).curry(2) f_method.call("foo").call("bar")
ユースケース
関数型アプローチを使うかどうか考えるポイント • 安易に動的にしようとしてないか一度立 ち止まる • 実行時でないと評価できない? • 処理 or 定義
定義 or 処理
定義 or 処理 • パイプライン的処理 • 必要なデータが揃っていなくても 一部評価可能な場合(ちょっと説明がムズイ)
もう少し具体的な例
少し具体的な例 : 顧客データ import機能 A B C D 1 2
3 4 元データをサービスDBにimportしたいが 変換が必要なケース
A B C D 1 2 3 4 rows
A B C D 1 2 3 4 rows cols
A B C D 1 2 3 4 カラムごとの変換のルールは事前にわかる
A B C D 1 2 3 4 行ごとに各々のカラムを変換ルールに 基づき変換していく
定義としての変換ロジックの例
例1: デフォルト値をセットする処理 DEFAULT_VALUE = "foo" f = -> (default_value, value)
{ value.nil? ? default_value : value }.curry(2).call(DEFAULT_VALUE) f.call(nil) #=> "foo"
例2: 単純な変換をする処理 f = -> (value) { value.upcase } f.call("foo")
#=> "FOO"
例3: マッピングを行う処理 RULES = { type1: { conversion: { “FOO”
=> "HOGE", “BAR” => "FUGA" } } }
例3: マッピングを行う処理 rule = RULES[:type1][:conversion] f = -> (conversion_rule, value)
{ conversion_rule[value] }.curry(2).call(rule) f.call(“foo”) #=> "hoge"
例4: 1,2,3全ての処理を行う処理 DEFAULT_VALUE = "foo" f1 = -> (default_value, value)
{ value.empty? ? default_value : value }.curry(2).call(DEFAULT_VALUE)
例4: 1,2,3全ての処理を行う処理 f1 = -> (default_value, value) { value.nil? ?
default_value : value }.curry(2).call("foo") f2 = ->(value) { value.upcase } f3 = -> (conversion_rule, value) { conversion_rule[value] }.curry(2).call(rule)
例4: 1,2,3全ての処理を行う処理 f = f1 >> f2 >> f3 f.call(nil)
#=> “HOGE”
アプローチの比較
動的なアプローチのメリットデメリット
動的なアプローチのメリットデメリット • 記述が少なく繰り返しを排除できる • コードを読むだけでは見通しが立ちにくい • 実行されるまでどう処理されるかわからない • grepが効かないことが多い
functionalなアプローチの メリットデメリット
functionalなアプローチのメリットデメリット • 処理を定義としてアウトプット可能 • 定義にデータを流すことでテスト可能 • メタプロが発生しないのでgrep可能 • パターンが網羅されていないと記述量で不利にな る場合がある(ただし...)
まとめ
まとめ • メリットデメリットはどちらにもある • 処理 or 定義でアプローチや表現は変わる • Rubyといえば動的、なわけではない武器はたくさ んある