最初に前提として書いておくと、javascriptでifやswitchは文となっています。この記事では、そんな二つの文法を返り値を返せるようにiff関数やswitchf関数として実装するというものです。
https://qiita.com/Yametaro/items/17f5a0434afa9b88c3b1
の感想で書いていたものになります。このページに掲載するプログラムは元記事の物を参考にしています。
#if関数改めiff関数
これに関しては、元記事の中でも元記事の感想欄でも指摘されてましたが、通常は三項演算子を使ってください。
元記事の感想欄で失敗したので、省略はできないとします。
感想欄でも書いたものになりますが、thenとelseの順番が逆でもいいバージョンを作ってみました。
const iff = cond=>{
const met = cond2=>func=>{
const revmet = revfunc => {
return cond2? func():revfunc();
}
return (cond==cond2)?{else:revmet}:{then:revmet}
};
return {then:met(cond),else:met(!cond)};
}
//以下サンプル
a=true;
document.write(iff(a).then(()=>"that is right<br>").else(()=>"that is wrong<br>"));
document.write(iff(a).else(()=>"that is wrong<br>").then(()=>"that is right<br>"));
いい実装かはわかりませんが、仕組みを説明します。最後のreturn {then:met(cond),else:met(!cond)};
というところを見てください。thenを先にした時とelseを先にした時で、引き渡している条件が逆転しています。これが肝となっています。cond(指定した条件式)とcond2を整理したいと思います。
thenが先かelseが先か | cond | cond2 |
---|---|---|
then | true | true |
else | true | false |
then | false | false |
else | false | true |
まず、最後のcond2に注目してください。cond2がtrueになるときはthenが先で条件式がtrueの時と、elseが先で条件式がfalseの時です。つまり先に指定された方の関数の返り値を返すときです。次にcond2がfalseになるときはelseが先で条件式がtrueの時と、thenが先で条件式がtrueの時です。つまり後に指定した方の関数返り値を返すときです。つまり、条件式だったり、thenとelseどっちが先かによらず先に指定した関数か、後に指定した関数かどっちの関数の返り値を返せばいいのか一緒になっています。なので、revmet関数は単にcond2によって分岐しているだけになっています。また、thenが後に来てもelseが後に来ても同じrevmetでいいというわけです。 | ||
次に、condとcond2を比較すると、両方trueの時と、両方falseの時にthenを先に指定しています。なのでcond==cond2 という式で、thenを含むオブジェクトを返すかelseを含むオブジェクトを返すかを分岐しています。 |
||
よって上記の簡単な実装で適切な返り値となっています。なかなか説明が難しかったのでうまく説明できた自信ないですけどわかりましたか? | ||
ちなみにelseifいりますか?といってもelse-thenの順番で書く人はelseifはどこに書くんでしょうか? | ||
#switch関数改めswitchF関数 | ||
ttstsfさんのプログラムを参考にしました。case関数の第二引数(カリー化されてる時ってこの言い方でいいんでしょうか?)を空にすると、次のcase関数の第二引数のが実行されます。もちろん、次のcase関数の第二引数もからならさらにその次の。最後のcase関数だけ引数は空にできません。対応させることもできましたが、意味がないので。 |
const switchF = num =>{
const caseF = num1 => num2 => casefunc =>{
const defaultF = num1 => defunc =>{
return (num1==undefined)? defunc():num1();
}
if(num1[0]==undefined){
return (num==num2)||(num1[1]==1)?
(casefunc==undefined)?
{case:caseF([casefunc,1]),default:defaultF(casefunc)}
:{case:caseF([casefunc,0]),default:defaultF(casefunc)}
:{case:caseF([undefined,0]),default:defaultF(undefined)}
}else{
return {case:caseF(num1),default:defaultF(num1[0])}
}
}
return{case:caseF([undefined,0])}
}
ちょっと説明がわかりにくかったかもしれないのであんまりいい例ではありませんが、サンプルを書いておきます
const re = switchF(1)
.case(0)()
.case(6)(()=>"土日です")
.case(1)()
.case(2)()
.case(3)()
.case(4)()
.case(5)(() => "平日です")
.default(() => "正しい曜日番号ではありません");
document.write(re);
読めばわかりますが、曜日番号をもとに平日か土日か返します。
なんかこれ以外にわかりやすい使用例があれば教えてください。少なくともこの例だったら簡単なif文で調べられるのでいい例ではありません。
多分元記事の物には該当機能はなかったように記憶してます。
#他には
他にはなんか式にしたら便利そうな文ってありましたっけ?あったら関数の実装に挑戦するので教えてください。元記事のコメントではfor関数を作った例がありました。