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
250
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
見出しとはなにか
ken7253
0
0
Firefoxにコントリビューションして得られた学び
ken7253
2
200
バンドルサイズを半減させた話 @Browser and UI #3
ken7253
0
93
CSS polyfill とその未来
ken7253
0
320
Browser and UI #2 HTML/ARIA
ken7253
2
380
PEPCは何を変えようとしていたのか
ken7253
3
640
Browser and UI #1 CSS
ken7253
0
200
レビューのやり方を(ちょっと)整理した話
ken7253
1
640
オーバーロード関数の話 @Mita.ts #2
ken7253
0
190
Other Decks in Programming
See All in Programming
Crash Auto Pipelines
veronikapj
1
400
Vapor Mode でアクセシビリティは 壊れないか検証した話
fuqda
1
330
はじめてのPLATEAU
nokonoko1203
1
630
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
4
3.6k
TS 7.0 で baseUrl が使えなくなった今、パスエイリアスをどうするか
bicstone
2
580
Python Lambdaにおけるテストしやすい設計とAI支援の活用 / Designing Testable Python Lambda Functions with AI
kitano_yuichi
1
310
PyConTW 2026 - AI Coding 不只是工具升級, 區域醫院醫療資訊系統協作開發與資訊團隊轉型實踐
cclai999
0
240
SODA - FACT BOOK(JP)
sodainc
1
40k
Engineering Biometric UX Across Android Versions | DroidKnights 2026
ryunen344
1
190
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
15
11k
Web3Dライブラリを作ってVue Custom Rendererの仕組みを理解しよう / lets learn vue custom renderer by making 3d library
drumath2237
1
130
Goコンパイラを作ってGoをもっと理解する / Build a Go compiler to better understand Go
ikura_hamu
0
130
Featured
See All Featured
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
Facilitating Awesome Meetings
lara
57
7.2k
Six Lessons from altMBA
skipperchong
29
4.6k
Agile that works and the tools we love
rasmusluckow
331
22k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.9k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
570
BBQ
matthewcrist
90
10k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
3k
How to Talk to Developers About Accessibility
jct
2
620
My Coaching Mixtape
mlcsv
0
380
Embracing the Ebb and Flow
colly
88
5.2k
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));
まとめ 関数を設計するときにいくつか持つとよい視点がある。 純粋関数という視点を持つ 関数の設計を行う場合はシグニチャーに情報を持たせる