Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
関数型プログラミングの考え方を取り入れて予測しやすいコードを書く
Search
ken7253
October 02, 2023
Programming
240
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
関数型プログラミングの考え方を取り入れて予測しやすいコードを書く
社内LT会にて発表した資料です。
ken7253
October 02, 2023
More Decks by ken7253
See All by ken7253
Firefoxにコントリビューションして得られた学び
ken7253
2
190
バンドルサイズを半減させた話 @Browser and UI #3
ken7253
0
87
CSS polyfill とその未来
ken7253
0
300
Browser and UI #2 HTML/ARIA
ken7253
2
380
PEPCは何を変えようとしていたのか
ken7253
3
600
Browser and UI #1 CSS
ken7253
0
190
レビューのやり方を(ちょっと)整理した話
ken7253
1
630
オーバーロード関数の話 @Mita.ts #2
ken7253
0
180
フロントエンドカンファレンス北海道参加レポート
ken7253
0
100
Other Decks in Programming
See All in Programming
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
950
Building an Out-of-Order CPU
latte72
1
780
FreeBSDでZabbixを動かす.pdf
kenkino
0
280
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
620
Security issues being discussed on Web Platforms
petamoriken
0
940
選挙速報を多くのユーザーへ 届ける Live Activities 設計
hamayokokuririn
0
140
【DroidKaigi 2026】「アクセシビリティを利用するとき、 アクセシビリティもまたこちらを利用している」 〜マルウェアによる攻撃と防衛について〜
halunoyo
0
460
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
250
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
100
Are APIs Still Relevant in the AI Era?
soyuka
0
220
Jetpack Compose メカニズム
skydoves
0
420
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
240
Featured
See All Featured
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
4.8k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
320
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.9k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.6k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
390
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
850
HDC tutorial
michielstock
2
870
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Transcript
Introduction Functional Programming 関数型プログラミングの考え方を取り入れて予測しやすいコードを書く
ken7253 Frontend developer 技術記事を書いたりするのが趣味。 最近はNext.jsを使ったアプリケーションを書いています。 インターフェイス設計やアクセシビリティ・SSG関連の技術に興味があります。 https://github.com/ken7253 https://zenn.dev/ken7253 https://dairoku-studio.com
前日譚 「なっとく!関数型プログラミング」 という本を買って読んでいました。 参考になる内容が多かった 関数型の考え方を紹介 ガチガチの関数型は難しいけど 少し取り入れてコードの品質を上げる
関数型プログラミングの考え方を部分的に採用し フロントエンドでも馴染み深いライブラリといえば?
None
話すこと 純粋関数について シグニチャーを意識して関数を作る
純粋関数
関数の分類の一つで特に関数型プログラミングで重要な考え方 下記の条件を全て満たした関数のことを純粋関数と呼ぶ 引数のみを利用する 戻り値は常に一つだけ 既存の変数を変更しない 純粋関数とはなにか
「引数のみを利用する」とは下記のようなこと グローバル変数を参照したり、時刻に依存するコードなど。 純粋関数の条件 // 🙆♂ 純粋関数 const pureFunc = (x:number,
y:number): number => { return x * y; }; // 🙅♂ 純粋関数ではない let x = 0; let y = 0; const notPureFunc = (): number => { return x * y; };
戻り値は常に1つだけ。 状況によってエラーを発生させたり、そもそも値を返さない場合がある関数など。 純粋関数の条件 // 🙅♂ 純粋関数ではない const notPureFunc = (a:
number): number | void => { if (a === 0) { throw new Error('Error'); } else if (a >= 100) { return a } // 値を返さない場合もある }
既存の変数を変更しない Array#push() や Array#reverse() などのメソッド、 var / let に対する再代入 などを関数の内部で呼び出して、既存の値を変更している場合など
純粋関数の条件 let num = 0; // 🙆♂ 純粋関数 const pureFunc = (n:number): number => { return n + 1; }; pureFunc(num); // num => 0 let num = 0; // 🙅♂ 純粋関数ではない const notPureFunc = (n:number): number => { return n++; }; notPureFunc(num); // num => 1
テストしやすい 意図しない挙動を起こしづらい コードの挙動が予測しやすい 副作用を分離することは 「臭いものに蓋をする」 だけに見える。 実際は、処理同士の繋がりが 型によって可視化 されてわかりやすいコードになる。 純粋関数だと何が嬉しいか
シグニチャー
シグニチャーとはなにか シグニチャー(シグネチャ)とは下記の情報をまとめた呼称 関数名 引数の型 返り値の型
下記のような関数があるとする。 この状態で何をしている関数であるか理解できる人は少ない。 シグニチャーの情報が少ない場合 export const foo: (a: any, b: any):
any => { // 外部からは見えない何らかの処理 }
シグニチャーをより正確にしてみる これにテストを追加してみる。 こうすることで(テストが無くても)ある程度挙動が推測できる。 シグニチャーの情報が少ない場合 export const sum = (first: number,
second: number): number | TypeError => { // 外部からは見えない何らかの処理 } import { sum } from "./sum" describe('与えられた引数を足し算して返却するsum関数', () => { test('自然数同士の足し算が正しく実行されること', () => {/* 省略 */}) test('引数のどちらかにNaNが渡された場合TypeErrorを返却すること', () => {/* 省略 */}) test('引数のどちらかにInfinityが渡された場合TypeErrorを返却すること', () => {/* 省略 */}) })
例としてこの関数を実際に使ってみる。 このようにシグニチャーから関数の使い方が理解できる。 情報の多い関数は適切に使用できる import { sum } from "./sum"; import
{ sendError } from "./sendError"; const [x,y] = [10, 20]; const sumResult = sum(x,y); // number | TypeError // そのままだと型が合わないので型ガードを利用する。 if (sumResult instanceof TypeError) { // sendError = (error: Error) => void; sendError(sumResult); // sendError(); はエラー情報をサーバーに送る処理として考える } else { console.log(sumResult); }
具体的なコードで見てみる 複数の要素の中から一番高さを持つ要素を探してコンソールに出力する処理 一つの関数にいろいろやらせている例 このようなコードがあった場合、次のように変えてみる。 // 入出力の情報がないので説明のための関数名が長くなりがち const displayHighestElementByElementList = ()
=> { // 要素の取得 const elements = document.querySelectorAll('.some-class'); const elementList = Array.from(elements); // 比較とソート const sortedFromClientHeight = [...elementList].sort((prev, next) => { return next.clientHeight - prev.clientHeight; }); // コンソールへの出力 console.log(sortedFromClientHeight[0]); }; displayHighestElementByElementList();
具体的なコードで見てみる 複数の要素の中から一番高さを持つ要素を探してコンソールに出力する処理 要素の取得 -> 比較関数 -> 出力 という値の流れが掴みやすい。 入出力の型情報があることで挙動が推測しやすい関数になる。 //
与えられた要素の配列から一番高さを持つ要素を返す関数 const getHighestElement = (elementList: Element[]): Element => { const sorted = [...elementList].sort((prev, next) => { return next.clientHeight - prev.clientHeight }); return sorted[0]; }; // 要素の取得 const elementList = Array.from(document.querySelectorAll('.some-class')); // コンソールへの出力 console.log(getHighestElement(elementList));
具体的なコードで見てみる 複数の要素の中から一番高さを持つ要素を探してコンソールに出力する処理 もっと関数型っぽい書き方だとこう。 配列のメソッドをうまく使って無駄なく宣言的に記述する。 // 与えられた要素の配列から一番高さを持つ要素を返す関数 const getHighestElement = (elementList:
Element[]): Element => elementList.reduce((acc, current) => acc.clientHeight >= current.clientHeight ? acc : current ); // 要素の取得 const elementList = Array.from(document.querySelectorAll(".some-class")); // コンソールへの出力 console.log(getHighestElement(elementList));
まとめ 関数を設計するときにいくつか持つとよい視点がある。 純粋関数という視点を持つ 関数の設計を行う場合はシグニチャーに情報を持たせる