if 文とか switch 文を見やすく書きやすくしたい
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ 構文サポートじゃないから いつもこの関数定義してでも使いたいってほどのが作れない
switch って使い勝手微妙ですよね
かといって if 文で else if いっぱい書くのも見た目が綺麗じゃないです
最近見かけた書き方でこんなのありました
綺麗といえば綺麗ですが インデントが 1 つ増えるし 書く量が多いです
いい感じにできないかなー といろいろ試してみます
条件部分をわかりやすくするために 無駄に [] で囲むようにしました
返り値を受け取れるのでいわゆる if 式になります
ただこれは引数の構造があまりよくないです
奇数番目と偶数番目で意味を持たせてますし 見た目は好きですがちょっとどうかなと思ってしまいます
見やすさは減りましたね
せっかく構造化して省略できる引数を書けるようになったので関数を実行するスコープへ渡す値をそれぞれの配列の 3 つめの値で渡せるようにしました
全部並列だと省略できないのでこういうオプションつけれるのはいいところです
if 文の条件に使ったのを関数の引数にして使えるようになっています
true になったら関数が実行されるんだから絶対 true じゃんと思うかもですが 動的言語はそうじゃないんです
プロパティがあるか確認してあればそれを使いたい時に
短いスコープになることが多いので 一文字の変数で受け取って入力が楽になるというのもあります
一時変数作るのも無駄な変数がいっぱいスコープにあるの嫌なのでこっちのほうがすきです
とくに match ではつかえます
whenAll は条件にあったのを上から順番に全部実行するものです
それまでの結果を受け取れるので else if じゃなくて if 文を並べて書くものの代わりにできます
case に条件式を書ける switch みたいとも言えますね
やっぱり そこまで見やすくないっていうのが微妙です
条件分岐は ES6 で構文増えてないんですよね
関数型の言語に多いパターンマッチや if や switch の式化をしてくれてもよかったのに
かといって if 文で else if いっぱい書くのも見た目が綺麗じゃないです
最近見かけた書き方でこんなのありました
if (x === 0)
a(x)
else if (x === 1)
(function(){
var b = a(x)
a(b + b)
})()
else if (x > 1)
(function(){
var b = a(x)
a(b * b)
})()
else
a(x * x)
a(x)
else if (x === 1)
(function(){
var b = a(x)
a(b + b)
})()
else if (x > 1)
(function(){
var b = a(x)
a(b * b)
})()
else
a(x * x)
綺麗といえば綺麗ですが インデントが 1 つ増えるし 書く量が多いです
いい感じにできないかなー といろいろ試してみます
ifs
見た目を重視してみますifs(
[a], x => x*2,
[b < c], () => b+c,
[d.startsWith("_")], () => d.substr(1)
)
var value = ifs(
[x.a],
a => Math.pow(a, 2),
[x.b],
b => Math.pow(b, 3),
[x.c],
c => Math.sqrt(c)
)
function ifs(...args){
for(var i=0;i<args.length;i+=2){
if(args[i][0]){
return args[i+1](args[i])
}
}
}
[a], x => x*2,
[b < c], () => b+c,
[d.startsWith("_")], () => d.substr(1)
)
var value = ifs(
[x.a],
a => Math.pow(a, 2),
[x.b],
b => Math.pow(b, 3),
[x.c],
c => Math.sqrt(c)
)
function ifs(...args){
for(var i=0;i<args.length;i+=2){
if(args[i][0]){
return args[i+1](args[i])
}
}
}
条件部分をわかりやすくするために 無駄に [] で囲むようにしました
返り値を受け取れるのでいわゆる if 式になります
ただこれは引数の構造があまりよくないです
奇数番目と偶数番目で意味を持たせてますし 見た目は好きですがちょっとどうかなと思ってしまいます
when, whenAll
次のは 引数の構造を考えてますwhen(
[
val === "abc", (cond, opts) => val + opts.join(""), [1,2,3]
],
[
val[0] === "a", () => {
var str = val.substr(1)
return str.split("-")
}
]
)
when(
[
str.match(/\[(.)\]/),
(cond, opts) => cond.pop()
],
[
str.match(/\[(..)\]/),
(cond, opts) => cond.pop().substr(1)
],
[
str.match(/\[(...)\]/),
(cond, opts) => opts[0] + cond.pop() + opts[1],
[pre, post]
]
)
whenAll([x, x => x+2], [x.v, v => v.z], [a===b, false])
whenAll([
a,
(cond, opts, pres) => 100
],[
b,
(cond, opts, pres) => pres.pop() ? "a は true" : "a は false"
],[
c,
(cond, opts, pres) => pres.pop() ? "b は true" : "b は false"
])
function when(...witems){
var result = null
witems.some(e => {
var cond = e[0]
var value = e[1]
var opts = e[2] || []
var value_is_function = typeof value === "function"
if(cond){
result = value_is_function ? value(cond, opts) : value
return true
}else{
return false
}
})
return result
}
function whenAll(...witems){
var results = []
witems.forEach(e => {
var cond = e[0]
var value = e[1]
var opts = e[2] || []
var value_is_function = typeof value === "function"
results.push(cond ? (value_is_function ? value(cond, opts, results.slice()) : value) : undefined)
})
return results
}
[
val === "abc", (cond, opts) => val + opts.join(""), [1,2,3]
],
[
val[0] === "a", () => {
var str = val.substr(1)
return str.split("-")
}
]
)
when(
[
str.match(/\[(.)\]/),
(cond, opts) => cond.pop()
],
[
str.match(/\[(..)\]/),
(cond, opts) => cond.pop().substr(1)
],
[
str.match(/\[(...)\]/),
(cond, opts) => opts[0] + cond.pop() + opts[1],
[pre, post]
]
)
whenAll([x, x => x+2], [x.v, v => v.z], [a===b, false])
whenAll([
a,
(cond, opts, pres) => 100
],[
b,
(cond, opts, pres) => pres.pop() ? "a は true" : "a は false"
],[
c,
(cond, opts, pres) => pres.pop() ? "b は true" : "b は false"
])
function when(...witems){
var result = null
witems.some(e => {
var cond = e[0]
var value = e[1]
var opts = e[2] || []
var value_is_function = typeof value === "function"
if(cond){
result = value_is_function ? value(cond, opts) : value
return true
}else{
return false
}
})
return result
}
function whenAll(...witems){
var results = []
witems.forEach(e => {
var cond = e[0]
var value = e[1]
var opts = e[2] || []
var value_is_function = typeof value === "function"
results.push(cond ? (value_is_function ? value(cond, opts, results.slice()) : value) : undefined)
})
return results
}
見やすさは減りましたね
せっかく構造化して省略できる引数を書けるようになったので関数を実行するスコープへ渡す値をそれぞれの配列の 3 つめの値で渡せるようにしました
全部並列だと省略できないのでこういうオプションつけれるのはいいところです
when([true, (cond, opts) => opts.map(e => e * e).join(""), [1,2,3]])
// "149"
// "149"
if 文の条件に使ったのを関数の引数にして使えるようになっています
true になったら関数が実行されるんだから絶対 true じゃんと思うかもですが 動的言語はそうじゃないんです
プロパティがあるか確認してあればそれを使いたい時に
when([x.property, p => console.log(p)])
と書けます短いスコープになることが多いので 一文字の変数で受け取って入力が楽になるというのもあります
x.property && console.log(x.property)
と書いたほうが綺麗ですがx.abcdefghijklmnopqrstuvwxyz.zyxwvutsrqponmlkjihgfedcba && console.log(x.abcdefghijklmnopqrstuvwxyz.zyxwvutsrqponmlkjihgfedcba)
みたいに長くなると嫌になってきます一時変数作るのも無駄な変数がいっぱいスコープにあるの嫌なのでこっちのほうがすきです
とくに match ではつかえます
when([
"abcd[e]fg".match(/\[(.)\]/),
match => {
var value = match.pop()
// なにか
}
])
"abcd[e]fg".match(/\[(.)\]/),
match => {
var value = match.pop()
// なにか
}
])
whenAll は条件にあったのを上から順番に全部実行するものです
それまでの結果を受け取れるので else if じゃなくて if 文を並べて書くものの代わりにできます
case に条件式を書ける switch みたいとも言えますね
やっぱり そこまで見やすくないっていうのが微妙です
条件分岐は ES6 で構文増えてないんですよね
関数型の言語に多いパターンマッチや if や switch の式化をしてくれてもよかったのに