C#
Dart
JavaScript
Kotlin
Python
TypeScript
public
プログラミングパラダイム
ラムダ式
関数型プログラミング
関数型プログラミング (Functional Programming)
関数型プログラミングはオブジェクト指向プログラミングにありがちな状態を持たない(同じ入力をすればいつも同じ結果が返ってくる)。
じゃあ状態管理はどうするのか
ずばり、オブジェクト指向プログラミングなど他のパラダイムを使う。
何でもかんでもオブジェクト指向プログラミングにこだわるべきでないのと同様に、何でもかんでも関数型プログラミングにこだわるべきでない。
現代的なプログラミング言語は関数型プログラミングとオブジェクト指向プログラミングの両方をサポートしているので、いいとこ取りをすればよいのだ。
高階関数
高階関数を使うと for ループを使った手続きから開放され、自然言語的なコーディングが可能になる。
every
Array.prototype.every() - JavaScript | MDN
every() メソッドは、列内のすべての要素が指定された関数で実装されたテストに合格するかどうかをテストします。これは論理値を返します。
JavaScript const values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
const result = values . every (( v ) => v >= 0 );
console . log ( result ); // true
Python values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
result = all ( v >= 0 for v in values )
print ( result ) # True
C# int [] values = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
var result = values . All ( v => v >= 0 );
// var result = Array.TrueForAll(values, v => v >= 0); // こういう書き方もできる
Console . WriteLine ( result ); // True
Kotlin fun main () {
val values = arrayOf ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
val result = values . all { it >= 0 }
println ( result ) // true
}
Dart void main () {
List < int > values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
final result = values . every (( v ) => v >= 0 );
print ( result ); // true
}
filter
Array.prototype.filter() - JavaScript | MDN
filter() メソッドは、この配列の中から、提供された関数で実装されたテストに合格した要素のみを抽出したシャローコピーを作成します。
JavaScript const values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
const odds = values . filter (( v ) => v % 2 === 0 );
console . log ( odds ); // [0, 2, 4, 6, 8]
Python values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
odds = list ( filter ( lambda v : v % 2 == 0 , values ))
print ( odds ) # [0, 2, 4, 6, 8]
C# int [] values = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
var odds = values . Where ( v => v % 2 == 0 ). ToArray ();
// var odds = Array.FindAll(values, v => v % 2 == 0); // こういう書き方もできる
Console . WriteLine ( string . Join ( "," , odds )); // 0,2,4,6,8
Kotlin fun main () {
val values = arrayOf ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
val odds = values . filter { it % 2 == 0 }
println ( odds . joinToString ( "," )) // 0,2,4,6,8
}
Dart void main () {
List < int > values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
final result = values
. where (( v ) => v % 2 == 0 )
. toList (); // toList()しないとIterableという型で返ってくる
print ( result ); // [0, 2, 4, 6, 8]
}
find
Array.prototype.find() - JavaScript | MDN
find() メソッドは、提供されたテスト関数を満たす配列内の最初の要素を返します。テスト関数を満たす値がない場合は、 undefined を返します。
JavaScript const values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
const zero = values . find (( v ) => v === 0 );
console . log ( zero ); // 0
Python values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
zero = next ( filter ( lambda v : v == 0 , values ))
print ( zero ) # 0
C# int [] values = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
var zero = values . FirstOrDefault ( v => v == 0 );
// var zero = Array.Find(values, v => v == 0); // こういう書き方もできる
Console . WriteLine ( zero ); // 0
Kotlin fun main () {
val values = arrayOf ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
val zero = values . find { it == 0 }
println ( zero ) // 0
}
Dart void main () {
List < int > values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
final result = values . firstWhere (( v ) => v == 0 );
print ( result ); // 0
}
map
Array.prototype.map() - JavaScript | MDN
map() メソッドは、与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成します 。
JavaScript const values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
const times = values . map (( v ) => v * 2 );
console . log ( times ); // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Python values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
times = list ( map ( lambda v : v * 2 , values ))
print ( times ) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
C# int [] values = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
var times = values . Select ( v => v * 2 ). ToArray ();
Console . WriteLine ( string . Join ( "," , times )); // 0,2,4,6,8,10,12,14,16,18
Kotlin fun main () {
val values = arrayOf ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
val times = values . map { it * 2 }
println ( times . joinToString ( "," )) // 0,2,4,6,8,10,12,14,16,18
}
Dart void main () {
List < int > values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
final result = values . map (( v ) => v * 2 ). toList ();
print ( result ); // [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
}
reduce
Array.prototype.reduce() - JavaScript | MDN
reduce() メソッドは、配列のそれぞれの要素に対して、ユーザーが提供した「縮小」コールバック関数を呼び出します。その際、直前の要素における計算結果の返値を渡します。配列のすべての要素に対して縮小関数を実行した結果が単一の値が最終結果になります。
JavaScript 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 const values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
// 合計値
const sum = values . reduce (
( accumulator , currentValue ) => accumulator + currentValue
);
console . log ( sum ); // 45
// 最小値
const min = values . reduce (( accumulator , currentValue ) =>
accumulator > currentValue ? currentValue : accumulator
);
console . log ( min ); // 0
// 最大値
const max = values . reduce (( accumulator , currentValue ) =>
accumulator < currentValue ? currentValue : accumulator
);
console . log ( max ); // 9
Python 1
2
3
4
5
6
7
8
9
10
11
12
13
14 from functools import reduce
values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
# 合計値
sum = reduce ( lambda x , y : x + y , values )
print ( sum ) # 45
# 最小値
min = reduce ( lambda x , y : x if x < y else y , values )
print ( min ) # 0
# 最大値
max = reduce ( lambda x , y : x if x > y else y , values )
print ( max ) # 9
C# 1
2
3
4
5
6
7
8
9
10
11
12
13 int [] values = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
// 合計値
var sum = values . Aggregate (( x , y ) => x + y );
Console . WriteLine ( sum ); // 45
// 最小値
var min = values . Aggregate (( x , y ) => x < y ? x : y );
Console . WriteLine ( min ); // 0
// 最大値
var max = values . Aggregate (( x , y ) => x > y ? x : y );
Console . WriteLine ( max ); // 9
Kotlin 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 fun main () {
val values = arrayOf ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
// 合計値
val sum = values . fold ( 0 ) { total , accumulator -> total + accumulator }
println ( sum ) // 45
// 最小値
val min = values . fold ( Int . MAX_VALUE ) { total , accumulator -> if ( accumulator < total ) accumulator else total }
println ( min ) // 0
// 最大値
val max = values . fold ( Int . MIN_VALUE ) { total , accumulator -> if ( accumulator > total ) accumulator else total }
println ( max ) // 9
}
Dart 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 void main () {
List < int > values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
// 合計値
final sum =
values . reduce (( accumulator , currentValue ) => accumulator + currentValue );
print ( sum ); // 45
// 最小値
final min = values . reduce (( accumulator , currentValue ) =>
accumulator < currentValue ? accumulator : currentValue );
print ( min ); // 0
// 最大値
final max = values . reduce (( accumulator , currentValue ) =>
accumulator > currentValue ? accumulator : currentValue );
print ( max ); // 9
}
some
Array.prototype.some() - JavaScript | MDN
some() メソッドは、指定された関数で実装されているテストに、配列の中の少なくとも 1 つの要素が 合格するかどうかを判定します。配列の中で指定された関数が true を返す要素を見つけた場合は true を返し、そうでない場合は false を返します。それ以外の場合は false を返します。配列は変更しません。
JavaScript const values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
const hasFour = values . some (( v ) => v === 4 );
console . log ( hasFour ); // true
Python values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
has_four = any ( v == 4 for v in values )
print ( has_four ) # True
C# int [] values = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
var hasFour = values . Any ( v => v == 4 );
Console . WriteLine ( hasFour ); // True
Kotlin fun main () {
val values = arrayOf ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
val hasFour = values . any { it == 4 }
println ( hasFour ) // true
}
Dart void main () {
List < int > values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
final hasFour = values . any (( v ) => v == 4 );
print ( hasFour ); // true
}
find() と some() の使い分けは以下が参考になりそう。
Javascript の配列操作: some と find と filter が便利 | 二代目俺のメモ
toSorted
ここに記載するのはすべて非破壊的にソートする方法である。
JavaScript const values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
// 昇順
const asc = values . toSorted (( x , y ) => x - y );
console . log ( asc );
// 降順
const desc = asc . toReversed ( asc );
console . log ( desc );
Python values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
# 昇順
asc = sorted ( values , key = lambda x : x )
print ( asc ) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 降順
desc = sorted ( asc , reverse = True )
print ( desc ) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
C# int [] values = { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 };
// 昇順
var asc = values . OrderBy ( x => x );
Console . WriteLine ( string . Join ( "," , asc )); // 0,1,2,3,4,5,6,7,8,9
// 降順
var desc = asc . OrderByDescending ( x => x );
Console . WriteLine ( string . Join ( "," , desc )); // 9,8,7,6,5,4,3,2,1,0
Kotlin fun main () {
val values = arrayOf ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
// 昇順
val asc = values . sortedBy { it }
println ( asc . joinToString ( "," ))
// 降順
val desc = asc . sortedByDescending { it }
println ( desc . joinToString ( "," ))
}
Dart 1
2
3
4
5
6
7
8
9
10
11
12
13 void main () {
List < int > values = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ];
// 昇順
// sort()は破壊的なソートかつ戻り値を返さないメソッドなので
// スプレッド演算子でコピーして、カスケード演算子でインスタンスを取得する
final asc = [... values ].. sort (( x , y ) => x - y );
print ( asc );
// 降順
final desc = [... values ].. sort (( x , y ) => y - x );
print ( desc );
}
forEach
Array.prototype.forEach() - JavaScript | MDN
forEach() メソッドは、与えられた関数を、配列の各要素に対して一度ずつ実行します。
JavaScript var items = [ "a" , "b" , "c" ];
items . forEach (( item , index ) => {
console . log ( ` ${ index } , ${ item } ` );
});
Python # PythonにArray.forEach()に相当する関数はない
items = [ "a" , "b" , "c" ]
for index , item in enumerate ( items ):
print ( f " { item } , { index } " )
C# string [] items = [ "a" , "b" , "c" ];
items . Select (( item , index ) => new { item , index }). ToList (). ForEach ( value =>
{
Console . WriteLine ( $"{value.index}, {value.item}" );
});
補足
Kotlin のメソッドは以下から確認した。
kotlin.collections - Kotlin Programming Language