SlideShare a Scribd company logo
JavaScript*で学ぶ関数型プログラミング*5章
関数を組み立てる関数
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 1
本スライドの大まかな流れ
1. 関数合成の基礎
2. カリー化
3. 部分適用
4. まとめ
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 2
本章の目的
関数の部品を集めて、より豊かな機能を持った関数を「合成す
る」様々な方法を探る
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 3
5.1$関数合成の基礎
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 4
関数合成とは
• 関数と関数を組み合わせて新しい関数を生成すること
• 以下の例では"f"と"g"を組み合わせた関数"g∘f"を表す
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 5
invoker(関数を振り返る
• 4#章(p107)で紹介された
• 関数を生成して返す
• オブジェクトをターゲットにしてメソッド呼び出しを行う
• オブジェクトが該当メソッドを持っていない場合は#
undefined#を返す
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 6
function invoker (NAME, METHOD) {
return function(target /* args ... */) {
if (!existy(target)) fail("Must provide a target");
var targetMethod = target[NAME];
var args = _.rest(arguments);
return doWhen((existy(targetMethod) && METHOD === targetMethod), function() {
return targetMethod.apply(target, args);
});
};
};
var rev = invoker('reverse', Array.prototype.reverse);
_.map([[1,2,3]], rev);
//=> [[3,2,1]]
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 7
ポリモーフィックな関数
• ポリモーフィックな関数とは
• 与えられた引数によって異なる動作を行う
• 1つ以上の関数を引数に取り、それらの関数を#undefined#
以外の値が返されるまで順番に呼び出す
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 8
construct(関数の振り返り
// 2 章(p55)にて紹介された cat, construct の振り返り
function cat() {
var head = _.first(arguments);
if (existy(head))
return head.concat.apply(head, _.rest(arguments));
else
return [];
}
// 要素と配列を引数に取り、配列の前に要素を挿入する関数
function construct(head, tail) {
return cat([head], _.toArray(tail));
}
construct(42, [1,2,3]);
//=> [42, 1, 2, 3]
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 9
function dispatch(/* funs */) {
var funs = _.toArray(arguments);
var size = funs.length;
return function(target /*, args */) {
var ret = undefined;
var args = _.rest(arguments);
for (var funIndex = 0; funIndex < size; funIndex++) {
var fun = funs[funIndex];
ret = fun.apply(fun, construct(target, args));
if (existy(ret)) return ret;
}
return ret;
};
}
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 10
dispatch)関数が行っていること
1. 関数が格納された配列を走査
2. 指定したオブジェクトでそれぞれの関数を呼び出す
3. 最初に指定された実際(existy()%が%true)の値を返す
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 11
配列!or!文字列を文字列に変換する関数をつくる
• 普通に書いたら下記のようになりがち
• 文字列"or"配列を引数に取る関数を定義
• 引数に与えられたデータの型や妥当性を判定
• if'else"ブロックでそれぞれのデータ型の"toString"メソッド
呼び出し
→"invoker"関数と"dispatch"関数を用いると単純化できる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 12
invoker!関数と!dispatch!関数を同時に利用
var str = dispatch(invoker('toString', Array.prototype.toString),
invoker('toString', String.prototype.toString));
str("a");
//=> "a"
str(_.range(10));
//=> "0,1,2,3,4,5,6,7,8,9"
→"ポリモーフィックな関数であることがわかる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 13
dispatch!関数における決まりごとの確認
• 下記条件が満たされるまで関数を順番に実行する
• 与えられた配列に格納された関数がなくなる
• 実行した関数が正常な値を返す
※!invoker!関数の仕様に依存するわけではない
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 14
文字列を逆順ソートする関数
function stringReverse(s) {
if (!_.isString(s)) return undefined;
return s.split('').reverse().join('');
}
stringReverse('abc');
//=> "cba"
stringReverse(1);
//=> undefined
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 15
逆順ソートを行うポリモーフィックな関数
stringReverse!と!Array#reverse!を組み合わせる
var polyrev = dispatch(invoker('reverse', Array.prototype.reverse),
stringReverse);
polyrev([1,2,3]);
//=> [3, 2, 1]
polyrev('abc');
//=> "cba"
→"異なるデータ型を扱うことができた
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 16
終了関数との合成
• 下記の例では"always"が終了関数
var polyrev = dispatch(invoker('reverse', Array.prototype.reverse),
stringReverse);
// dispatch 関数によって生成された関数も dispatch 関数の引数になることができる
var sillyReverse = dispatch(polyrev, always(42));
sillyReverse([1,2,3]);
//=> [3, 2, 1]
sillyReverse("abc");
//=> "cba"
sillyReverse(1000000);
//=> 42
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 17
switch!文!による手動ディスパッチを!
dispatch!関数を用いて簡潔にする
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 18
function performCommandHardcoded(command) {
var result;
switch (command.type)
{
case 'notify':
result = notify(command.message);
break;
case 'join':
result = changeView(command.target);
break;
default:
alert(command.type);
}
return result;
}
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 19
performCommandHardcoded!関数の利用例
引数に渡された!command!オブジェクトのフィールドを参照し、
コマンド文字列の内容によって異なる関数を実行する
performCommandHardcoded({type:'notify', message: 'hi!'});
// notify 関数を実行
performCommandHardcoded({type:'join', message: 'waiting-room'});
// changeView 関数を実行
performCommandHardcoded({type:'wat'});
// alert 関数を実行
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 20
dispatch!関数の利用
function isa(type, action) {
return function(obj) {
if (type === obj.type)
return action(obj);
};
}
var performCommand = dispatch(
isa('notify', function(obj) { return notify(obj.message); }),
isa('join', function(obj) { return changeView(obj.target); }),
function(obj) { alert(obj.type); }
);
performCommand!関数に渡す関数の注意点を考えてみよう
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 21
拡張性の比較
• performCommandHardcoded"関数の場合
• 拡張する場合、switch"文の内部を変更する必要がある
• performCommand"関数の場合
• 別の"dispatch"関数でラッピングするだけで済む
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 22
performCommand!関数の拡張例!その!1
新たなコマンド!kill!を追加する例
→!performCommand!関数をラップすることで拡張する
// performCommand の拡張例
var performAdminCommand = dispatch(
isa('kill', function(obj) { return shutdown(obj.hostname); }),
performCommand
);
performCommand({type: 'kill', hostname: 'localhost'});
// シャットダウン
performCommand({type: 'fail'});
// alert を実行
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 23
performCommand!関数の拡張例!その!2
join!コマンドを制限する例
→!既存コマンドをオーバーライドする。
var performTrialUserCommand = dispatch(
isa('join', function(obj) { alert("Cannot join until approved") }),
performCommand);
performTrialUserCommand({type: 'join', target: 'foo'});
// 拒否メッセージが入った alert を実行
performTrialUserCommand({type: 'notify', message: 'Hi new user'});
// notify 関数を実行
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 24
関数合成のまとめ
• 関数合成とは、関数を組み合わせて新しい関数を生成すること
• これまで説明した以下の内容が関数合成の本質
• 既知の方法で既存のパーツを使うことによって新たな動作を
組み立てる
• 上記で組み立てた新たな動作も後にパーツとして利用できる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 25
5.2$変異は低レイヤーでの操作
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 26
変数の変異は気にする必要がない
• 関数型プログラミングにおいて関数は抽象の最小単位
• 関数が変数の境界をつくるのでローカル変数の状態変更は関数
の外部に漏れることはない
• 変数の変異は低レイヤーにおける操作として意識の外に置く
べき
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 27
命令型プログラミングとの比較
// 命令型プログラミング
var result = 0;
for(var n = 1; n <= 10; n++) {
result = result + n;
}
// 関数型プログラミング
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var plus = function(a, b) {
return (a + b);
};
var result = _.reduce(numbers, plus);
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 28
使うべき道具を理解しよう
• 本書は関数型プログラミングの美徳を熱く説くものではない
• ライブラリの特性や実行速度などの都合により、命令型プログ
ラミングで実装すべき場面もある
• 問題とその解決策を理解する力とそこで使える引き出しを持っ
ていることが、最善のソリューションにつながる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 29
5.3$カリー化
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 30
カリー化とは
• 複数の引数を取る関数を、1#つの引数のみを取る関数のチェー
ンに変換する処理
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 31
数学的に捉えてみる
!は!2!引数関数であり、左から順に引数として! ,! !を受け取る
これを左からカリー化すると...
このとき、関数! !は!関数! !はカリー化された関数という。
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 32
関数合成の基礎を振り返る
!のとき! !ならば! !が成り立つ!
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 33
カリー化(右から)を図示
※!本書では右の引数からカリー化を行う
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 34
カリー化の具体例
function leftCurryDiv(n) {
return function(d) {
return n/d;
};
}
function rightCurryDiv(d) {
return function(n) {
return n/d;
};
}
var divide10By = leftCurryDiv(10);
divide10By(2)
//=> 5
var divideBy10 = rightCurryDiv(10);
divideBy10(2)
//=> 0.2
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 35
5.3.2%自動的にパラメータをカリー化
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 36
固定された関数を返す高階関数!curry
• divide10By"と"divideBy10"は手動だった
• 今回は引数を"1"つだけ取るように固定された関数を返す関数で
カリー化を行う
function curry(fun) {
return function(arg) {
return fun(arg);
};
}
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 37
parseInt
• parseInt:#文字列を引数にとり、それを数値に変換する
• 第#1#引数:#文字列
• 第#2#引数:#底
parseInt('11');
//=> 11
parseInt('11', 2);
//=> 3
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 38
parseInt!+!Array#map!で発生する問題
• それぞれの配列要素に対して引数に与えられた関数を実行
• 実行時、要素・インデックス・元の配列が与えられる
• 引数を"1"つだけ取るように矯正すれば問題ない
> ['11','11','11','11'].map(parseInt);
//=> [ 11, NaN, 3, 4 ]
> ['11','11','11','11'].map(curry(parseInt));
//=> [ 11, 11, 11, 11 ]
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 39
2"つのパラメータをカリー化
function curry2(fun) {
return function(secondArg) {
return function(firstArg) {
return fun(firstArg, secondArg);
};
};
}
var parseBinaryString = curry2(parseInt)(2);
parseBinaryString("111");
//=> 7
parseBinaryString("10");
//=> 2
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 40
コラム:"なぜ右からカリー化?
• 右のほうにある引数は専門化のための
オプションであることが多い
• parseInt"もこれに当てはまる
• これを固定化(または無視)すること
で関数の動作をコントロールしやすく
なる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 41
5.3.2.1&カリー化を利用して新しい関数を生成する
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 42
var plays = [{artist: "Burial", track: "Archangel"},
{artist: "Ben Frost", track: "Stomp"},
{artist: "Ben Frost", track: "Stomp"},
{artist: "Burial", track: "Archangel"},
{artist: "Emeralds", track: "Snores"},
{artist: "Burial", track: "Archangel"}];
_.countBy(plays, function(song) {
return [song.artist, song.track].join(" - ");
});
//=> {"Ben Frost - Stomp": 2,
// "Burial - Archangel": 3,
// "Emeralds - Snores": 1}
function songToString(song) {
return [song.artist, song.track].join(" - ");
}
var songCount = curry2(_.countBy)(songToString);
songCount(plays);
//=> {"Ben Frost - Stomp": 2,
// "Burial - Archangel": 3,
// "Emeralds - Snores": 1}
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 43
5.3.2.2%3%段階%カリー化で%HTML%カラーコードビルダーを実装
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 44
_.uniq
• 配列から重複要素を取り除いた新しい配列を返す
• _.uniq(array, [isSorted], [iterator])
• isSorted"はすでに配列がソート済みの場合に用いる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 45
3"段階のカリー化
function curry3(fun) {
return function(last) {
return function(middle) {
return function(first) {
return fun(first, middle, last);
};
};
};
};
var songsPlayed = curry3(_.uniq)(false)(songToString);
songsPlayed(plays);
//=> [{artist: "Burial", track: "Archangel"},
// {artist: "Ben Frost", track: "Stomp"},
// {artist: "Emeralds", track: "Snores"}]
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 46
HTML%カラーコードを生成する関数
function toHex(n) {
var hex = n.toString(16);
return (hex.length < 2) ? [0, hex].join(''): hex;
}
function rgbToHexString(r, g, b) {
return ['#', toHex(r), toHex(g), toHex(b)].join('');
}
rgbToHexString(255, 255, 255);
//=> "#ffffff"
var blueGreenish = curry3(rgbToHexString)(255)(200);
blueGreenish(0);
//=> "#00c8ff"
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 47
5.3.3$「流暢な」APIのためのカリー化
• Haskell(では、関数はデフォルトでカリー化されている
• 一方、JavaScript(ではそうではない。そのため、API(やドキュメ
ントを用意する必要がある
• カリー化を用いるかどうかの一般的なルールは「API(が高階関
数を活用するか」
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 48
5.3.4%JavaScript%におけるカリー化のデメリット
• 任意の段階までカリー化する関数は実用的ではない
• Haskell(や(Shen(では多段カリー化を有効活用できる(API(がある
• JavaScript(では一般的にカリー化は不利に働き、混乱を招く
• 可変数引数が許可されているため
• カリー化よりも任意の深さまでの部分適用がより一般的に使わ
れる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 49
5.4$部分適用
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 50
部分適用とは
• 関数を"任意"の数だけ引数を指定して部分的に実行する
• 部分適用された関数は残りの引数を与えると即時実行される
• f(a,b,c)"→"g(a,b)
• a,b"を付与すると即時実行
• カリー化は"h(a)"のように引数を1つにする
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 51
5.4.1%1つ・2つの既知の引数を部分適用
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 52
1つの既知の引数を部分適用
function div(n, d) { return n / d }
function partial1(fun, arg1) {
return function(/* args */) {
var args = construct(arg1, arguments);
return fun.apply(fun, args);
};
}
var over10Part1 = partial1(div, 10);
over10Part1(5);
//=> 2
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 53
2つの既知の引数を部分適用
function partial2(fun, arg1, arg2) {
return function(/* args */) {
var args = cat([arg1, arg2], arguments);
return fun.apply(fun, args);
};
}
var div10By2 = partial2(div, 10, 2);
div10By2()
//=> 5
→"1つか2つの引数の部分適用はよくある。
任意の数の引数を予め適用できればさらに便利になる。
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 54
5.4.2%任意の数の引数を部分適用
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 55
function partial(fun /*, 任意の数の引数*/) {
var pargs = _.rest(arguments);
return function(/* arguments */) {
var args = cat(pargs, _.toArray(arguments));
return fun.apply(fun, args);
};
}
var over10Partial = partial(div, 10);
over10Partial(2);
//=> 5
var div10By2By4By5000Partial = partial(div, 10, 2, 4, 5000);
div10By2By4By5000Partial();
//=> 5
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 56
5.4.3%部分適用の実用例:%事前条件
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 57
validator!関数を思い出してみよう
• 検証用のプレディケート関数を引数に取る
• エラーが発生した場合のエラーメッセージを関数のオブジェク
トフィールドに格納して返す関数
function validator(message, fun) {
var f = function(/* args */) {
return fun.apply(fun, arguments);
};
f['message'] = message;
return f;
}
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 58
validator!関数の利用例
var zero = validator("0 ではいけません", function(n) { return 0 === n; });
var number = validator(" 引数は数値である必要があります", _.isNumber);
function sqr(n) {
if (!number(n)) throw new Error(number.message);
if (zero(n)) throw new Error(zero.message);
return n * n;
}
sqr(10);
//=> 100
sqr(0);
// Error: 0 ではいけません
sqr('');
// Error: 引数は数値である必要があります
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 59
事前条件と事後条件
• 事前条件
• 関数の呼び出し元の保証
• 例示したような入力データ検証(zero,#number)
• 事後条件
• 事前条件が満たされたと想定した場合の、関数呼び出しの結
果に対する保証
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 60
事前条件と計算の骨子を区別する
• zero"と"number"という2つの事前条件は計算自体の骨子に関係
しない
• 実行部の動作保証を行うだけなので分離すべき
→事前条件と計算の骨子を分離し、そのあとで新たな関数を用い
てそれらを部分適用を行うことで結びつける
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 61
// 具体的な事前条件を引数に取る
function condition1(/* validators */) {
var validators = _.toArray(arguments);
return function(fun, arg) {
var errors = mapcat(function(isValid) {
return isValid(arg) ? [] : [isValid.message];
}, validators);
if (!_.isEmpty(errors))
throw new Error(errors.join(", "));
return fun(arg);
};
}
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 62
condi&on1(の利用例
var sqrPre = condition1(
validator("0 ではいけません", complement(zero)),
validator("引数は数値である必要があります", _.isNumber));
sqrPre(_.identity, 10);
//=> 10
sqrPre(_.identity, '');
// Error: 引数は数値である必要があります
sqrPre(_.identity, 0);
// Error: 0 ではいけません
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 63
安全でない!sqr!関数の例
function uncheckedSqr(n) { return n * n };
uncheckedSqr('');
//=> 0
• JavaScript+は演算時に空の文字列を+0+に自動変換する
• 空の文字列の2乗が+0+であることを許容すべきではない
→"これを解決するために"validator,"partial1,"condition1,"
sqrPre"を組み合わせる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 64
おさらい!1
// エラーが発生した場合のエラーメッセージを関数のオブジェクトフィールドに格納して返す
function validator(message, fun) {
var f = function(/* args */) {
return fun.apply(fun, arguments);
};
f['message'] = message;
return f;
}
// 1つの既知の引数を部分適用
function partial1(fun, arg1) {
return function(/* args */) {
var args = construct(arg1, arguments);
return fun.apply(fun, args);
};
}
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 65
おさらい!2
// 事前条件と計算の骨子を分離する
function condition1(/* validators */) {
var validators = _.toArray(arguments);
return function(fun, arg) {
var errors = mapcat(function(isValid) {
return isValid(arg) ? [] : [isValid.message];
}, validators);
if (!_.isEmpty(errors))
throw new Error(errors.join(", "));
return fun(arg);
};
}
// 事前条件と計算の骨子を結びつける
var sqrPre = condition1(
validator("0 ではいけません", complement(zero)),
validator("引数は数値である必要があります", _.isNumber));
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 66
引数の妥当性チェックを計算から分離する
var checkedSqr = partial1(sqrPre, uncheckedSqr);
checkedSqr(10);
//=> 100
checkedSqr('');
// Error: 引数は数値である必要があります
checkedSqr(0);
// Error: 0 ではいけません
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 67
更に追加の検証項目を加える
var sillySquare = partial1(
condition1(validator("偶数を入力してください", isEven)), checkedSqr);
sillySquare(10);
//=> 100
sillySquare(11);
// Error: 偶数を入力してください
sillySquare('');
// Error: 引数は数値である必要があります
sillySquare(0);
// Error: 0 ではいけません
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 68
関数の生成時のカリー化および部分適用の制約
• 「1#つ以上の数の引数を専門化することによって合成する」と
いう共通の制約
• 引数と戻り値の関係を関数合成に持ち込みたい場合がある
→"関数を並べて端から端までつなぎ合わせる"_.compose"関数を
紹介する
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 69
5.5#並べた関数を端から端まで#compose#関数
でつなぎ合わせる
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 70
関数のつなぎあわせ
function isntString(str) {
return !_.isString(str);
}
isntString(1);
//=> true
// compose 関数によるつなぎあわせ(右から左に実行される)
var isntString = _.compose(function(x) { return !x }, _.isString);
isntString([]);
//=> true
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 71
5.5.1$合成を使った事前条件と事後条件
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 72
前節のおさらいと本節の目標
• 前節のおさらい
• 引数が前提に準拠するかを確認してから二乗する関数"
checkedSqr"を組み立てた
• 本節の目標
• 事後条件(関数呼び出しの結果に対する保証)を"
checkedSqr"に追加する
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 73
事後条件の定義
var sqrPost = condition1(
validator("結果は数値である必要があります", _.isNumber),
validator("結果はゼロではない必要があります", complement(zero)),
validator("結果は正の数である必要があります", greaterThan(0)));
sqrPost(_.identity, 0);
// Error: 結果はゼロではない必要があります, 結果は正の数である必要があります
sqrPost(_.identity, -1);
// Error: 結果は正の数である必要があります
sqrPost(_.identity, '');
// 結果は数値である必要があります, 結果は正の数である必要があります
sqrPost(_.identity, 100);
//=> 100
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 74
事後条件を既存の関数に追加する
_.compose!を接着剤として利用する
var megaCheckedSqr = _.compose(partial(sqrPost, _.identity), checkedSqr);
// 事前条件の検証時エラー
megaCheckedSqr(10);
//=> 100
megaCheckedSqr(0);
// Error: 0 ではいけません
// 事後条件の検証時エラー
megaCheckedSqr(NaN);
// Error: 結果は正の数である必要があります
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 75
事後条件でのエラーは常に自らの失敗
• 事後条件の検証時エラーは以下のようなときに発生する
• 事前条件に漏れがある
• 事後条件が厳しすぎる
• 内部ロジックに不具合がある
→"自らの失敗により発生することがほとんどである
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 76
5.6$まとめ
• 一般的もしくは特化した目的のいずれでも、既存の関数から新
しい関数を合成することができるという考え方を実践した
• カリー化と部分適用の説明とそれらの具体的な利用方法を紹介
した
• conditionや_.compose"などの関数を用いて、事前条件と事
後条件を既存の関数に追加する具体例を示した
TAKAMURA'Narimichi'/'第'4'回'Topotal'輪読会@2015/03/18 77

More Related Content

What's hot

リテラルと型の話 #__swift__
リテラルと型の話 #__swift__リテラルと型の話 #__swift__
リテラルと型の話 #__swift__
Tomohiro Kumagai
 
Flex's DI Container
Flex's DI ContainerFlex's DI Container
Flex's DI Container
Masaaki Yonebayashi
 
Serf2Excel - Serf を実運用に活かす話 + Consul もあるよ
Serf2Excel - Serf を実運用に活かす話 + Consul もあるよSerf2Excel - Serf を実運用に活かす話 + Consul もあるよ
Serf2Excel - Serf を実運用に活かす話 + Consul もあるよ
Masahito Zembutsu
 
Xamarin で ReactiveUI を使ってみた
Xamarin で ReactiveUI を使ってみたXamarin で ReactiveUI を使ってみた
Xamarin で ReactiveUI を使ってみた
Hironov OKUYAMA
 
JSクラス定義
JSクラス定義JSクラス定義
JSクラス定義
Wataru Nakaseko
 
Swift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswiftSwift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswift
Tomohiro Kumagai
 
Swift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposiumSwift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposium
Tomohiro Kumagai
 
Pronama 0707 wf4
Pronama 0707 wf4Pronama 0707 wf4
Pronama 0707 wf4
Tomoyuki Obi
 
WebAPIのバリデーションを、型の力でいい感じにする
WebAPIのバリデーションを、型の力でいい感じにするWebAPIのバリデーションを、型の力でいい感じにする
WebAPIのバリデーションを、型の力でいい感じにする
Takuya Kikuchi
 
リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__
Tomohiro Kumagai
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform
信之 岩永
 
プロトコル指向に想う世界観 #__swift__
プロトコル指向に想う世界観 #__swift__プロトコル指向に想う世界観 #__swift__
プロトコル指向に想う世界観 #__swift__
Tomohiro Kumagai
 
RUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践SmalltalkRUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践Smalltalk
Sho Yoshida
 
作られては消えていく泡のように儚いクラスタの運用話
作られては消えていく泡のように儚いクラスタの運用話作られては消えていく泡のように儚いクラスタの運用話
作られては消えていく泡のように儚いクラスタの運用話
Tsuyoshi Torii
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swift
Yuki Asai
 
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
TanUkkii
 

What's hot (17)

リテラルと型の話 #__swift__
リテラルと型の話 #__swift__リテラルと型の話 #__swift__
リテラルと型の話 #__swift__
 
Flex's DI Container
Flex's DI ContainerFlex's DI Container
Flex's DI Container
 
Serf2Excel - Serf を実運用に活かす話 + Consul もあるよ
Serf2Excel - Serf を実運用に活かす話 + Consul もあるよSerf2Excel - Serf を実運用に活かす話 + Consul もあるよ
Serf2Excel - Serf を実運用に活かす話 + Consul もあるよ
 
Xamarin で ReactiveUI を使ってみた
Xamarin で ReactiveUI を使ってみたXamarin で ReactiveUI を使ってみた
Xamarin で ReactiveUI を使ってみた
 
JSクラス定義
JSクラス定義JSクラス定義
JSクラス定義
 
Swift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswiftSwift 2.0 で変わったところ「前編」 #cswift
Swift 2.0 で変わったところ「前編」 #cswift
 
Swift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposiumSwift 2.0 大域関数の行方から #swift2symposium
Swift 2.0 大域関数の行方から #swift2symposium
 
Pronama 0707 wf4
Pronama 0707 wf4Pronama 0707 wf4
Pronama 0707 wf4
 
WebAPIのバリデーションを、型の力でいい感じにする
WebAPIのバリデーションを、型の力でいい感じにするWebAPIのバリデーションを、型の力でいい感じにする
WebAPIのバリデーションを、型の力でいい感じにする
 
Fabrication
FabricationFabrication
Fabrication
 
リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__リテラルと型の続きの話 #__swift__
リテラルと型の続きの話 #__swift__
 
.NET Compiler Platform
.NET Compiler Platform.NET Compiler Platform
.NET Compiler Platform
 
プロトコル指向に想う世界観 #__swift__
プロトコル指向に想う世界観 #__swift__プロトコル指向に想う世界観 #__swift__
プロトコル指向に想う世界観 #__swift__
 
RUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践SmalltalkRUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践Smalltalk
 
作られては消えていく泡のように儚いクラスタの運用話
作られては消えていく泡のように儚いクラスタの運用話作られては消えていく泡のように儚いクラスタの運用話
作られては消えていく泡のように儚いクラスタの運用話
 
Deep dive into oss written in swift
Deep dive into oss written in swiftDeep dive into oss written in swift
Deep dive into oss written in swift
 
ECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミングECMAScript6による関数型プログラミング
ECMAScript6による関数型プログラミング
 

Viewers also liked

偽相関と偏相関係数
偽相関と偏相関係数偽相関と偏相関係数
偽相関と偏相関係数
Teruki Shinohara
 
統計学基礎
統計学基礎統計学基礎
統計学基礎
Yuka Ezura
 
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
Kazunori Tatsuki
 
パターン認識 05 ロジスティック回帰
パターン認識 05 ロジスティック回帰パターン認識 05 ロジスティック回帰
パターン認識 05 ロジスティック回帰sleipnir002
 
深層学習とTensorFlow入門
深層学習とTensorFlow入門深層学習とTensorFlow入門
深層学習とTensorFlow入門
tak9029
 
ロジスティック回帰の考え方・使い方 - TokyoR #33
ロジスティック回帰の考え方・使い方 - TokyoR #33ロジスティック回帰の考え方・使い方 - TokyoR #33
ロジスティック回帰の考え方・使い方 - TokyoR #33horihorio
 

Viewers also liked (6)

偽相関と偏相関係数
偽相関と偏相関係数偽相関と偏相関係数
偽相関と偏相関係数
 
統計学基礎
統計学基礎統計学基礎
統計学基礎
 
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
[A 3]SSJSでも使える!Javascriptでオブジェクト指向プログラミング入門
 
パターン認識 05 ロジスティック回帰
パターン認識 05 ロジスティック回帰パターン認識 05 ロジスティック回帰
パターン認識 05 ロジスティック回帰
 
深層学習とTensorFlow入門
深層学習とTensorFlow入門深層学習とTensorFlow入門
深層学習とTensorFlow入門
 
ロジスティック回帰の考え方・使い方 - TokyoR #33
ロジスティック回帰の考え方・使い方 - TokyoR #33ロジスティック回帰の考え方・使い方 - TokyoR #33
ロジスティック回帰の考え方・使い方 - TokyoR #33
 

Similar to 【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 5 章

StackStorm MeetupJP #11
StackStorm MeetupJP #11StackStorm MeetupJP #11
StackStorm MeetupJP #11
Ohyama Hiroyasu
 
StackStorm MeetupJP #11
StackStorm MeetupJP #11StackStorm MeetupJP #11
StackStorm MeetupJP #11
Ohyama Hiroyasu
 
ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】株式会社ランチェスター
 
Kanazawa.js.Next
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Next
dynamis
 
ES6 はじめました
ES6 はじめましたES6 はじめました
ES6 はじめました
Net Kanayan
 
StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践
Shu Sugimoto
 
はかどるChefの小ネタ集
はかどるChefの小ネタ集はかどるChefの小ネタ集
はかどるChefの小ネタ集
Yukihiko SAWANOBORI
 
Clrh 20140906 lt
Clrh 20140906 ltClrh 20140906 lt
Clrh 20140906 lt
Tomoyuki Obi
 

Similar to 【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 5 章 (9)

StackStorm MeetupJP #11
StackStorm MeetupJP #11StackStorm MeetupJP #11
StackStorm MeetupJP #11
 
StackStorm MeetupJP #11
StackStorm MeetupJP #11StackStorm MeetupJP #11
StackStorm MeetupJP #11
 
ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】ちょっと詳しくJavaScript 特別編【悪霊の神々】
ちょっと詳しくJavaScript 特別編【悪霊の神々】
 
Kanazawa.js.Next
Kanazawa.js.NextKanazawa.js.Next
Kanazawa.js.Next
 
Hokuriku Scala 1
Hokuriku Scala 1Hokuriku Scala 1
Hokuriku Scala 1
 
ES6 はじめました
ES6 はじめましたES6 はじめました
ES6 はじめました
 
StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践StackStormを活用した運用自動化の実践
StackStormを活用した運用自動化の実践
 
はかどるChefの小ネタ集
はかどるChefの小ネタ集はかどるChefの小ネタ集
はかどるChefの小ネタ集
 
Clrh 20140906 lt
Clrh 20140906 ltClrh 20140906 lt
Clrh 20140906 lt
 

More from Narimichi Takamura

Nginx バージョンアップ動向(2015/07〜2015/12)
Nginx バージョンアップ動向(2015/07〜2015/12)Nginx バージョンアップ動向(2015/07〜2015/12)
Nginx バージョンアップ動向(2015/07〜2015/12)
Narimichi Takamura
 
Dovecot & Postfix バージョンアップ動向 201506-201511
Dovecot & Postfix バージョンアップ動向 201506-201511Dovecot & Postfix バージョンアップ動向 201506-201511
Dovecot & Postfix バージョンアップ動向 201506-201511
Narimichi Takamura
 
Nginx バージョンアップ動向(2015/01〜2015/06)
Nginx バージョンアップ動向(2015/01〜2015/06)Nginx バージョンアップ動向(2015/01〜2015/06)
Nginx バージョンアップ動向(2015/01〜2015/06)
Narimichi Takamura
 
Dovecot & Postfix バージョンアップ動向 201401-201505
Dovecot & Postfix バージョンアップ動向 201401-201505Dovecot & Postfix バージョンアップ動向 201401-201505
Dovecot & Postfix バージョンアップ動向 201401-201505
Narimichi Takamura
 
ぼくとおこめとJSON
ぼくとおこめとJSONぼくとおこめとJSON
ぼくとおこめとJSON
Narimichi Takamura
 
Nginx バージョンアップ動向(2014/01〜2014/12)
Nginx バージョンアップ動向(2014/01〜2014/12)Nginx バージョンアップ動向(2014/01〜2014/12)
Nginx バージョンアップ動向(2014/01〜2014/12)
Narimichi Takamura
 
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
Narimichi Takamura
 
【続編】その ionice、ほんとに効いてますか?
【続編】その ionice、ほんとに効いてますか?【続編】その ionice、ほんとに効いてますか?
【続編】その ionice、ほんとに効いてますか?
Narimichi Takamura
 
その ionice、ほんとに効いてますか?
その ionice、ほんとに効いてますか?その ionice、ほんとに効いてますか?
その ionice、ほんとに効いてますか?
Narimichi Takamura
 
ぼくとおこめ
ぼくとおこめぼくとおこめ
ぼくとおこめ
Narimichi Takamura
 
( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」
( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」
( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」Narimichi Takamura
 

More from Narimichi Takamura (11)

Nginx バージョンアップ動向(2015/07〜2015/12)
Nginx バージョンアップ動向(2015/07〜2015/12)Nginx バージョンアップ動向(2015/07〜2015/12)
Nginx バージョンアップ動向(2015/07〜2015/12)
 
Dovecot & Postfix バージョンアップ動向 201506-201511
Dovecot & Postfix バージョンアップ動向 201506-201511Dovecot & Postfix バージョンアップ動向 201506-201511
Dovecot & Postfix バージョンアップ動向 201506-201511
 
Nginx バージョンアップ動向(2015/01〜2015/06)
Nginx バージョンアップ動向(2015/01〜2015/06)Nginx バージョンアップ動向(2015/01〜2015/06)
Nginx バージョンアップ動向(2015/01〜2015/06)
 
Dovecot & Postfix バージョンアップ動向 201401-201505
Dovecot & Postfix バージョンアップ動向 201401-201505Dovecot & Postfix バージョンアップ動向 201401-201505
Dovecot & Postfix バージョンアップ動向 201401-201505
 
ぼくとおこめとJSON
ぼくとおこめとJSONぼくとおこめとJSON
ぼくとおこめとJSON
 
Nginx バージョンアップ動向(2014/01〜2014/12)
Nginx バージョンアップ動向(2014/01〜2014/12)Nginx バージョンアップ動向(2014/01〜2014/12)
Nginx バージョンアップ動向(2014/01〜2014/12)
 
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 1 章
 
【続編】その ionice、ほんとに効いてますか?
【続編】その ionice、ほんとに効いてますか?【続編】その ionice、ほんとに効いてますか?
【続編】その ionice、ほんとに効いてますか?
 
その ionice、ほんとに効いてますか?
その ionice、ほんとに効いてますか?その ionice、ほんとに効いてますか?
その ionice、ほんとに効いてますか?
 
ぼくとおこめ
ぼくとおこめぼくとおこめ
ぼくとおこめ
 
( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」
( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」
( (0) / (0)) ☆祝☆ (nari_ex) LT at Cloud Server Festa 2013 Autumn「サバフェス!」
 

Recently uploaded

This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.
chiefujita1
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
CRI Japan, Inc.
 
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
Toru Tamaki
 
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
Yuuitirou528 default
 
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
t m
 
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
Matsushita Laboratory
 
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさJSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
0207sukipio
 
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
Matsushita Laboratory
 

Recently uploaded (8)

This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.This is the company presentation material of RIZAP Technologies, Inc.
This is the company presentation material of RIZAP Technologies, Inc.
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
 
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
 
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
 
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
遺伝的アルゴリズムと知識蒸留による大規模言語モデル(LLM)の学習とハイパーパラメータ最適化
 
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
 
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさJSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
JSAI_類似画像マッチングによる器への印象付与手法の妥当性検証_ver.3_高橋りさ
 
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
ReonHata_便利の副作用に気づかせるための発想支援手法の評価---行為の増減の提示による気づきへの影響---
 

【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 5 章