[b][size=150][b][size=150]このワークシートは[url=https://www.geogebra.org/m/twxxx3yq]Math by Code[/url]の一部です。[br][/size][/b][br]<mapをやろう>[br][/size][/b][br]前回の関数型プログラミングの導入では、[br]反復のfor[code][/code]条件を手続き型から宣言型に移[br]し替えることを学んだね。[br][br]「n for n in 数の範囲」で数nの「[color=#0000ff][b][size=150]リスト[/size][/b][/color]」ができた。geogebraではSequenceコマンドとして作れた。[br][br]「2*n+1 for n in 数の範囲」で数nの式を作ると、奇数の「[color=#0000ff][b][size=150]リスト[/size][/b][/color]」が作れる。[br][br]関数型プログラミングでは[br]もちろん、[br][color=#0000ff][b]sum[/b][/color](リスト)とすれば、リストの数値の合計が出せる。[br][color=#0000ff][b]find[/b][/color](リスト, "a")などでリストから要素の位置を求めたり、[br]concat(リスト、リスト)などでリスト連結をしたり、[br]push(リスト、a)などでリストに要素を追加したりすることはよくあることだね。[br][br]それだけではなない。[br][br][b][color=#0000ff]map[/color][/b](x->f(x),リスト)などとかいて、要素xからf(x)のリストをマッピングできる。[br][color=#0000ff][b]filter[/b][/color](x->expr(x),リスト)などとかいて、要素xのうちexpr(x)が成り立つ要素だけリストができる。[br][br]前回は乱数の行列を使って、200行5列の得点表を作ったね。[br]今回は乱数の2次元配列を作って、[br][br][color=#38761d][size=150][b]50行5列の得点表を作り、[br]平均点以上なら+、 未満ならーにマッピングしたい。[br][/b][/size][/color][br]juliaでリストのmapやってみよう。[br]2次元配列全体に対してはマッピングできない。[br]だから、[br]1行のデータリストdata[y]にまで入り込んで、[br]小数得点aveと比べるために得点を小数化したfloat(x)にし、[br]+-を返す関数updown(x)を作っておき、data[y]を+ーデータとしてmapしよう。[br][b][IN]julia[/b][br]#============================================[br][color=#0000ff][br]num = 50[br]kamoku = 5[br][b]data=[[rand(0:100) for x in 1:kamoku] for y in 1:num][br]ave= sum([sum(data[y]) for y in 1:num])/(num*kamoku)[br]updown(x) = float(x) >= ave ? '+' : '-'[br]res = [ map(x->updown(x) , data[y]) for y in 1:num][br][/b]println(res)[br][/color][br]#============================================[br][OUT]例[br][['-', '-', '+', '+', '-'], ['-', '-', '+', '+', '-'], ['-', '+', '+', '+', '-'], ['+', '+', '-', '+', '+'], ['-', '-', '+', '-', '-'], ['-', '-', '+', '-', '+'], ['+', '-', '-', '+', '+'], ['-', '-', '-', '+', '+'], ['-', '+', '-', '-', '-'], ['+', '+', '+', '+', '+'], ['+', '-', '+', '+', '+'], ['+', '-', '-', '+', '+'], ['+', '-', '-', '-', '-'], ['-', '-', '-', '-', '+'], ['+', '-', '+', '+', '+'], ['+', '-', '+', '+', '+'], ['+', '+', '+', '+', '+'], ['-', '-', '-', '-', '-'], ['-', '+', '-', '+', '-'], ['-', '-', '+', '+', '+'], ['+', '-', '+', '+', '+'], ['-', '+', '+', '-', '+'], ['-', '+', '-', '-', '-'], ['-', '+', '-', '+', '-'], ['-', '-', '+', '-', '-'], ['+', '+', '-', '+', '-'], ['+', '+', '+', '+', '+'], ['-', '-', '+', '-', '-'], ['-', '-', '-', '-', '+'], ['-', '+', '+', '-', '+'], ['+', '+', '-', '-', '-'], ['+', '+', '-', '+', '+'], ['+', '+', '-', '+', '+'], ['+', '-', '+', '-', '-'], ['-', '-', '-', '-', '+'], ['+', '+', '+', '-', '-'], ['-', '+', '+', '+', '-'], ['+', '+', '-', '-', '-'], ['-', '+', '+', '+', '-'], ['-', '-', '+', '-', '-'], ['+', '-', '-', '+', '-'], ['+', '-', '+', '-', '-'], ['-', '+', '+', '-', '-'], ['+', '-', '-', '+', '-'], ['-', '-', '+', '-', '+'], ['-', '+', '-', '+', '-'], ['+', '+', '-', '-', '+'], ['+', '+', '+', '-', '-'], ['+', '-', '+', '+', '-'], ['-', '-', '-', '+', '+']][br][br]残念だが、geogebraにはmapコマンドそのものはない。[br]しかし、if文は使えるので、updown(x)という3項演算子のような関数は使わずに、[br]直接sequenceコマンドにifを入れ込んでみよう。[br]データ要素と平均を比べる場面では、Elementコマンドを使うとインデックス指定で[br]データが取り出せるね。[br][b][IN]geogebra[/b][br]#============================================[br][color=#0000ff][br]num = 50[br]kamoku = 5[br][b]data=Sequence(Sequence(RandomBetween(0,100),n,1,kamoku),m,1,num)[br]ave=((Sum(Sequence(Sum(data(n)),n,1,num)))/(num kamoku))[br]rs=Sequence(Sequence(If(Element(data,m,n)≥ave,"+","-"),n,1,kamoku),m,1,num)[br][/b][/color][br]#============================================
出力は、 [br]コマンドラインにコンパイルと実行を両方やり、メッセージを最小にすると、juliaと同様の結果になります。[br][b]cargo run --quiet[/b][br][['-', '-', '-', '-', '+'], ['-', '-', '+', '+', '-'], ['+', '-', '+', '+', '-'], ['-', '+', '-', '-', '-'], ['-', '-', '-', '-', '+'], ['-', '+', '-', '-', '+'], ['-', '-', '+', '+', '+'], ['+', '-', '-', '+', '+'], ['+', '+', '+', '-', '-'], ['+', '-', '-', '+', '+'], ['+', '+', '-', '+', '+'], ['+', '+', '+', '+', '+'], ['-', '-', '+', '+', '-'], ['-', '-', '+', '-', '+'], ['+', '-', '-', '-', '+'], ['-', '-', '+', '-', '+'], ['-', '+', '-', '-', '-'], ['-', '-', '+', '-', '-'], ['+', '+', '+', '+', '+'], ['[br][br]rustの構文の特徴を確認しておきましょう。[br][br]・juliaでは、f(x) for x in リスト、f(x) for x in 範囲、というように[b]要素の操作のあとに対象[/b]をかきました。[br]rustでは、[br][color=#0000ff][b]範囲.map(|x| f(x))とか、[br]リスト.iter().map(|x| f(x)}というように、[br]対象のあとに操作[/b]をかきます。[br][/color]また、rubyのように[b]対象となる要素xには|x|のように、絶対値マークをつけます[/b]。[br]それに、対象要素xを不定マーク(_)にすることができます。すると、[br]範囲.map(|_| f(x))は、f(x)を範囲となる回数を繰り返すという意味になります。[br][br]また、注意しなければならないのは、[br]juliaではmapですぐにリストができたのに、[br]pythonではlist()でかこまないとリストができなかったと同じように、[br]操作した[b]結果をあつめてリストにしますよという指示、.collect()[/b]をつけないといけないということです。[br][br]map()とか、sum()とかで対象をかこむjuliaの書き方とちがい、[br]リスト[b].iter().[/b]map(要素と操作).collect()[br]リスト.[b]iter().[/b]sum(要素と操作)[br]のようにイテレーション(走査)の機能として末尾に命令をたしてく形式です。[br]書き方が逆ですね。[br][br]また、[b]rust[/b]は,[br][b][color=#0000ff]let 変数::型名=式;[br][/color][/b]という形で変数を型名を明確にして束縛します。[br]メモリを確実に確保するためです。[br]もちろん、[b]型推論[/b]という機能もあるので、忘れても平気なときもありますが、[br]変数を組み合わせて演算していくうちに、型を変換する羽目に陥るときがあります。[br]そのときは、[br][color=#0000ff][b]変数 as 変換先の型名[/b] [br][/color]という書き方をしてください。[br]変換しないと仕方ないときがあります。[br][b]整数A÷整数Bは整数の範囲の商[/b]になってしまうので、[br][b]A as f64 / B as f64[/b]のようにして商が小数になるようにしましょう。[br]大きいサイズを小さく変換すると[br]内容によっては変わってしまうこともあるので、[br]プログラムは動いても、内容がおかしくなることもありうるので注意しましょう。[br]また、一般的にrustの書籍は先端を進んでいるという感じの方がかいているので、[br]硬い用語をそのまま、あえて使っていることが多い気がします。[br]pythonよりはまだ一般化してないからです。[br]そういうものだという気持ちで情報と接することが大切ですね。[br][br]また、[b]プリント文にも注意[/b]しましょう。[br]!マークは関数ではなくマクロというものだという目印です。[br]それは約束事だからいいいのですが、{:?}が気になりますね。[br]tableは表だから、ベクターのベクターです。[br]だから、その[b]型名にあう出力[/b]が必要になりますが、とりあえずデータを押し出したいときは[br]{}ではあなく、[b]{:?}[/b]にすると形の崩れたままでよければ出力できる便利な指定です。[br][b][color=#0000ff]println!("{:?}",[/color][/b]table);[br][br]