floatのお話
どうもShZgZです。
本日は雪の影響(おかげ)で少し早く帰れました。諸々お気をつけ下さい。
今回はタイトル通り「floatのお話」です。
まず、下のコードをご覧下さい。
>>> 27.0 / 10.0 - 17.0 / 10.0 > 1 True
※Python3の計算結果です。
これを見て、「?、当たり前じゃん」となっちゃう方は恐らくこの読んでも面白い事はあまり無いと思いますが、できれば読んで頂いてコメント貰えるととても嬉しい。
Paiza解いてる時に詰まった部分なんですが、なんか浮動小数点の計算しててなんか挙動おかしいなと思って確かめてる時にこれを見つけました。
普通に計算したら、
27.0 / 10.0 - 17.0 / 10.0 = 2.7 - 1.7 = 1.0
1.0 > 1 = False
1.0 < 1 = False
こうなってくれるんじゃ無いかと思ってたわけです。
でもならない。
因みに、
>>> 27.0 / 10.0 - 17.0 / 10.0 1.0000000000000002
こうなりました。
簡単にすると、
>>> 2.6 - 1.6 1.0 >>> 2.7 - 1.7 1.0000000000000002
※因みに、Rustでも同様であることは確認しました。他の言語は試してません。興味ある方は是非試してみて下さい。
この原因ですが、そもそも浮動小数点をどう扱っているかというところです。
浮動小数点数の計算はIEEE 754で定められています。←これどういうことかというとプログラミング言語における標準仕様(IEEE 754)に書かれてることだから、それに沿ってる色んな言語で上記のような状況がありえるよってことです。
浮動小数点の基本形式に関しては情報処理技術者の試験とかでもあった気がするので説明は割愛します(気になったらWikiとか他のサイトとかを参考にしてみて下さい。今回の話ではわかってなくても大丈夫です。)が、
浮動小数点数である"2.7"はデータとしては"2.7±誤差"となってもっている可能性があるということです。
ここでは先の例があるので2.7としましたが、モチロン他の値でもありえます。
要するに、浮動小数点数がデータとしてどのように保持されているかを理解していれば別ですが、よくわかんないという場合には
浮動小数点数(1.1, 2.9882, 10.301 ...etc)は、表示されたままではなく誤差があるものとして考えておこう。
・まとめ
プログラミングにおいて浮動小数点数を扱う際には、
1.1も中では1.1000000000001とかかもしれないし、2.9882も中では2.9881999999998とかかもしれないから、もしかしたらその浮動小数点数には誤差があるかもしれないと思っておきましょうということ。
機械学習について思ったことを書いとく
どうもShZgZです。
継続的にブログを書くことが出来る人たちは本当に凄いと思います。
が、それでも私はなんとなく書きたいなと思ってときだけ書きます。
今回はタイトルの通り、機械学習についてちょっと思ったことをメモっておきます。
昨今、やれ人工知能だとか機械学習だとかディープラーニングだとか騒がれてますが、全くもって便利なもんだと思います。
ディープラーニングの仕組みとかも面白くて、久しぶりに数学に触れた感じがしました。証明しようとしたら大変だろうけど、なんとなく概要を理解して計算を実装することは結構簡単なので是非やってみて下さい。
ちゃんと読んだのこれしかないんですが、概要掴むのには丁度良かった。
で、さっきちょろっと考えたことです。
※ただ、一つ注意して下さい。ちょっとネガティブっぽいこととかポジティブっぽいこととか言いますが、機械学習の構造は理解してるけど、別段機械学習を仕事とか趣味で使ってる訳でも無い人間が言っていることです。
機械学習で人工知能の性能はガンガン上がってると感じる一方で結局責任の所在はどうなるんだろう?と。
名目上とか、法律上はまぁそれらの人工知能を運営してる会社なり団体なりの責任になるんだろうとは思うんですが、そういうのではなくて自分が本当に人工知能だけを完全に信頼できるようになるのかということを考えました。
今も翻訳とか記事を書くこととか、作曲だとかを計算機に任せるってことは既に実現しているし、結構な精度だと思います。この辺の行為に関しては、特にリスクが高い訳でもないし、とりあえずやってみて良かったらまた使うってことでいいとは思います。
ただ、自動運転とか手術とかはどうなのか?
考え易いのは自分の手術かな。(ただ、私には物心ついてからの手術経験無いので想像ですが。)
命が掛かっていたり、失敗したら障害が残ってしまうような手術で人工知能に全てを任せることができるようになるのかどうか。
今後、人工知能の性能が上がっていって(症例が増えればテストデータも増えるし、学習精度も上がっていくことでしょう。)お医者さんよりも手術の成功確率が上がる時代は来るでしょう。ただ、そのときにじゃあ人工知能さんに手術をお願いしますっていう風に簡単に言うのは中々踏ん切りがつきません。
人工知能の精度は上がっていったとしても精度は100%にはならない訳で、それに対して状況は千差万別。他の人たちでは大丈夫だったとしても、自分の場合はおかしな挙動をしてしまうってことはありうるのではないかと。
人間だってミスはします。そりゃ無いに越したことは無いけど、するもんはします。人工知能もその性質上ミスでは無いのですが、明らかにおかしい挙動をすることがあります。そのような明らかな異常行動さえなければ手術でも任せられるんだと思います。
そういう意味で、今は人工知能と人間が協力しあっていく方向になっていっている。道具として使うのではなく、その人工知能の人格?人間性?ちょっと違う気もするけど(そもそも人間じゃないしね)、その人工知能の性格みたいなものを理解し、協力しあっていくということになっていくのだろうと思っています。
それはいい方向性だと思います。ただ、それでもヒューマンエラーは起こりうる訳で、人が介在せず、計算機が全てを行う方がミスは減らせるだろうとエンジニアながらに考えてしまうわけです。
ただ人と機械が協力しあって生きていくって小さい頃に見ていたアニメのようでとても良いと、高ぶる気持ちはあります。それがいつまでも続くことなのか、どこかでやはり機械だけになっていってしまうのか。どうなんでしょうか。
思ったままに書きましたが、結論から言いますとアニメ大好きです。
StepByStep和訳:1.Printing on Terminal
どうもShZgZです。
台風本当に凄いですね。皆さんも気を付けて下さい。
引き続きRust Programming Step-by-Step · GitBookの和訳らしきものを進めていきます。
今回はコンパイラのインストールとハロワとかの画面表示系です。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Terminal上にプリント
始め方
もっとも短いRustプログラムは
fn main(){}
これはよく下のように書かれます。
fn main() {
}
見てわかるようにこれは何も行われません。ただ"main"という名前のついた空の関数を定義しただけです。関数によって何かを行う指示の集合に名前を与える。
"fn"というのは"function"の略で、"main"とは関数の名前を表します。丸括弧("()"←これのこと)には関数の引数を含むことが、波括弧("{}"←これのこと)にはステートメントを含むことができます。上の例では、引数もステートメントもありません。
Rustで書かれたプログラムが実行されるときは"main"関数が実行されます。"main"関数が無い場合は完全なプログラムではありません。そのときはライブラリとなります。
このプログラムを実行するためには以下の操作を完了して下さい。
・Rustコンパイラとユーティリティのインストールを行う。
コンパイラはhttps://www.rust-lang.org/ja-JP/よりダウンロードすることができます。Linux, Windows, Mac OS Xのx86 (32-bit) or x86-64 (64-bit)で利用可能です。それぞれのプラットフォームで"stable", "beta", "nightly"という3つのバージョンが存在します。インストールするものは"stable"バージョンをお薦めします。"stable"バージョンは最も古いですが、最もテストされ、これから変更される可能性も低いものとなっています。これらのバージョンは全てコンソールのコマンドラインより利用されます。インストール後は、インストールされたバージョンを確認するために以下のコマンドを実行して下さい。
rustc -V
(因みに私の環境では"rustc 1.20.0"が表示されます。)
・Rust練習用のファイルを保存するためのフォルダを作成(もしくは指定)し、上部の最も短いRustプログラムの内容を持ったmain.rsファイルをお好みのテキストエディタで作成して下さい。
・コマンドライン上でRust練習用フォルダに移動し、以下のコマンドを実行して下さい。
rustc main.rs
実行するとすぐにプロンプト(コマンドラインでinputバーの前にある文字のことで、Windowsなら">"、それ以外なら多分"$")が表示されます。この時、"main"という名前のついたファイルが作成されています。(Windowsでは"main.exe"になっています。)実際に、"rustc"コマンドは正しく指定されたファイルのコンパイルを行いました。つまり、ソースコードを読み、対応するマシンコードを生成し、そのマシンコードを同じフォルダに保存したわけです。
・コマンドライン上で、Windowsならば以下を実行して下さい。
main
その他のOSでは以下を実行して下さい。
./main
これで作成されたプログラムを実行することが出来ました。しかし、今回は何も行わないプログラムなので、またすぐにプロンプトが表示されてしまうはずです。
Hello, World!
それではコマンドライン上にテキストを表示する方法を見ていきましょう。前節のプログラムを以下のように変更してみましょう。
fn main() {
print!("Hello, world!");
}
前のようにコンパイルし、実行すると、以下のように表示されます。
Hello, world!
新しく追加された行が"トークン"として知られる8つの構文アイテムを持つことに注目して下さい。それらを調べていきましょう。
print
: これはRustのスタンダードライブラリに定義されたマクロ名です。!
: これはその前にある名前がマクロであることを示しています。このシンボルが無いと、"print"は関数を表します。しかし、Rustのスタンダードライブラリにそのような関数は無いので、コンパイルエラーとなります。マクロは関数に似た物です。(それはRustの名前に関連付いたステートメントの集合を表す。この名前を利用することで、それらのステートメントを実行することができる。)(
: マクロの引数リストの開始"
: 文字列リテラルの開始Hello, world!
: 文字列リテラルの内容"
: I文字列リテラルの終了)
: マクロの引数リストの終了;
: ステートメントの終了
文字列リテラルの意味を調べてみましょう。
"文字列"とは「スペースや句読点を含む長さの決まった文字列」
つまり、"文字列リテラル"とは「ソースコードに直接指定される長さの決まった文字列」(上の例だと"Hello, world!"←これが文字列リテラル)
"println"マクロは単に受け取った引数をコマンドライン上に表示します。
Rustは大文字と小文字を区別します。(大文字と小文字を区別することを英語で"case sensitive"って言うらしい)
文字列リテラルやコメント部分(Rustでコメントアウトは"// ここ行末までコメント"か"/* 囲まれてる部分コメントで、コメントを改行したかったら行頭にアスタリスク */")以外の1文字の大文字小文字を入れ替えたりすると、コンパイルエラーになったり、挙動が変わってしまう。代わりに、文字列リテラル内で同様のことを行うとコンパイルは成功するが、挙動は変わってしまうかもしれない。
例えば、
fn Main() {
}
このプログラムをコンパイルしようとすると、プログラム中に"main"関数が定義されていないとしてコンパイルエラーとなる。("main"と"Main"を区別するし、前に説明したようにプログラムには"main"関数が必ず必要だから。)
今後、指定した場合を除き、例示するコードは"main"関数内に書かれていることを想定するため、"main"関数の定義ステートメントは省略します。
文字列の連結を表示
下のような方法で、1つの文字列リテラルを使用する代わりに、1つのステートメントで複数の文字列リテラルを表示できる。
print!("{}, {}!", "Hello", "world");
このステートメントを"main"関数の内部に書くと、再び以下の文字列が表示される。
Hello, world!
この場合、"println"マクロは","(カンマ)で区切られた3つの引数を受け取っている。引数は全て文字列リテラルで、最初の文字列は二つの波括弧のペア("{}")を含んでいる。それらはプレースホルダーで、他2つの文字列を挿入する場所を示している。
だから、このマクロは最初の引数の後に全ての引数を調べる。そして、最初の引数の中の波括弧のペアそれぞれを他の引数と置き換える。
printf("%s, %s!", "Hello", "world");
But there is an important difference. If you try to compile
しかし、ここには重大な違いがある。もし、以下のコードをコンパイルしようとすると
print!("{}, !", "Hello", "world");
you get a compilation error, as the arguments of the macro after the first one are more numerous than the placeholders inside the first argument; that is, there is some argument that doesn't have any corresponding placeholder.
最初の引数を除いた残りの引数の数が、最初の引数内部にあるプレースホルダーの数より多い(上の例だと"{}, !"の中にはプレースホルダー1つなのに、"Hello"と"world"って2つあって1つ多いよねってこと)ためコンパイルエラーとなる。つまり、対応するプレースホルダーの存在しない引数がある。
そして、もし、以下のコードをコンパイルしようとすると
print!("{}, {}!", "Hello");
上の逆で、引数より多いプレースホルダーがあるとしてコンパイルエラーとなる。つまり、対応する引数の存在しないプレースホルダーがある。
一方でC言語の方ではコンパイルエラーは起こらないが、代わりに実行時にクラッシュするかおかしな挙動を引き起こす。
複数行を表示
今まではただ1行を表示するプログラムを書いてきたが、ここでは以下のようにして1つのステートメントで複数行を表示する。
print!("First line\nSecond line\nThird line");
これは以下のように表示される。
First line
Second line
Third line
The sequence of characters \n
, where n
stands for "new line", is transformed by the compiler into the character sequence that represents the line terminator for the currently used operating system.
この文字列"\n"はコンパイラによって、以下のように変換される。
"\n" → "そのOS上で使用される行末を表す文字列"
これが与えられたら、全てのプリントステートメントに関して、ステートメントの最後で一度改行することはとても普通のことであり、Rustのスタンダードライブラリにはそのようなマクロが用意されている。
println!("text of the line");
Calling this println
macro (whose name is to be read "print line"), is equivalent to calling print
with the same arguments, and then outputting a line terminator. That is, that statement is equivalent to:
"println"(これは"print line"と読まれる)マクロを呼ぶことは、いくつかの引数と共に"print"を呼び、行末を表す文字列を表示することと同義である。つまり、このステートメントは以下と同様
print!("text of the line\n");
整数を表示
もし、整数を表示したかったら
print!("My number: 140");
もしくは
print!("My number: {}", "140");
もしくは、第2引数のクォートを除いて
print!("My number: {}", 140);
これらのステートメントは以下のように表示される。
My number: 140
最後のステートメントにおいて、第2引数は文字列リテラルではなく、整数リテラルである。
整数は文字列以外のデータ型で、"print"マクロで第1引数に含まれる対応するプレースホルダーを置き換えることができる。
事実、コンパイラはソースコードに含まれる文字列"140"を10進表記の数として解釈し、それはバイナリフォーマットにおいて数との等価性を生成し、実行プログラムに保存する。
実行時には、そのプログラムはバイナリフォーマットのその数を受け取り、文字列"140"に変換し、プレースホルダーを文字列と置き換え、表示用文字列を生成し、その文字列をコマンドラインへ送る。
この手続きは例えば、以下のようなプログラムだとどうなるかを説明している。
print!("My number: {}", 000140);
the compiler generates exactly the same executable program generated before. Actually, when the source string 000140
is converted to the binary format, the leading zeros are ignored.
コンパイラは前と同様の実行プログラムを生成する。実際に、ソース文字列"000140"はバイナリフォーマットに変換され、先頭の"0"は無視される。
引数の型が異なったとしても、このステートメントは
print!("{}: {}", "My number", 140);
前と同様の行を表示するだろう。ここでは1つ目のプレースホルダーは文字列リテラルに対応し、2つ目は整数リテラルに対応する。
上で使ったrustcコマンドは大きい欠点を持っている。その欠点とは、コード中に見つかったエラーを全て見つかった順番で表示してしますことである。もし、あなたのコードが多くの構文エラーを含み、それらを最初から最後まで修正しなければならないような時があったとします。しかし、コンパイラがそれらのエラーを出力し終えると、プロンプトのすぐ上の部分には最後に見つかったエラーが表示されており、最初のエラーへ戻るためにはスクロールしていかなければならない。
一時的な解決法として、以下のコマンドを、Unix-like terminalもしくはLinux上で実行する。
clear; rustc $* --color=always 2>&1 | more
You can put it in a script file, named, say, rs
, so that to compile a file named main.rs
you can type:
あなたはこれを"rs"と名付けられたスクリプトファイルに書くことにより、"main.rs"と名付けられたファイルを以下のように実行できる。
rs main.rs
This script first clears the screen, then runs the rustc
compiler with all the arguments you give to it. If the compilation is successful, or if it generates less than a screenful of error messages, it behaves like a normal run of rustc
.
このスクリプトはスクリーンをクリアし、全ての引数とともにrustcコンパイラを実行する。もし、コンパイルが成功したり、エラーメッセージがスクリーンに全て表示される程度の量だった場合は通常のrustcように振舞う。
一方、エラーメッセージがスクリーンを覆ってしまった場合は表示が止まり、"--More--"というメッセージがターミナルスクリーンの下部に表示される。この時、いくつかのキーを押すことができる。
- Enterキーは1行進む。
- スペースキーは1スクリーン分進む。
- Qキー("quit"を表す)は、途中でエラーメッセージの表示を止め、コマンドラインに戻る。
StepByStep和訳:0.Introduction
どうもShZgZです。
Rustの記事を書こう書こうと思ってたんですが、書けてませんでした。
勉強する方で頑張っちゃってどうもOutputが疎かになってしまうので、復習も兼ねてRust Programming Step-by-Step · GitBookの和訳らしきことをやっていこうかと思います。
Rustに関するドキュメントはどれもある程度のプログラミング知識を前提としているものが多いですが、このドキュメントはその名の通りStep By Stepで徐々に進んでいく印象があります。なので、ペースゆっくり目がいいという人向けかと思います。
ちょいちょい勝手に自分で文章とかコードとか追加しちゃうこともあるかもしれませんが、悪しからず。
では。導入から。
-----------------------------------------------------------------------------------------------
導入
この本はRust初心者にRustの書き方を簡単なものから一歩ずつ解説していきます。
読み進めていく上で、基本的なプログラミング知識を必要とします。(出来れば、CかC++)
このテキストを理解するためにはプログラミング言語でよくあるintegerやfloatが何であるか知っていて、識別子と文字列リテラルを区別できれば十分です。
ここではコマンドライン環境を想定しています。(LinuxやUnixのshell, MacのTerminal, Windowsのコマンドプロンプトです。)
Kotlin:基本構文
どうもShZgZです。
Kotlinをちょっとちゃんとやってみようかと思い、
とりあえずOfficialのReferenceを読んでいきます。
とりあえず原文で読んでいってよく分からないところは日本語版を参考にしていこうかと思います。
基本的にはJavaを知っていて、JavaとKotlinでどう変わったかを確認していく感じなりますが悪しからず。
パッケージ定義
パッケージの定義はJava同様一番上です。セミコロンが無いことを除いては変わり無しですね。
package my.demo
import java.util.*
関数定義
関数はかなり変わったというか別物です。
形としてはこんな感じ、
fun 関数名(引数名: 引数の型, ・・・): 返り値の型{
(処理内容)
return 返り値
}
返り値の型とreturnを省略して
fun 関数名(引数名: 引数の型, ・・・) = 返り値
こんな風にも書けます。関数型の言語でよくある感じの書き方になってきてるように感じます。実際にはこんな感じです。
fun sum(a: Int, b: Int): Int {
return a + b
}fun sum(a: Int, b: Int) = a + b
因みにVoidはKotlinではUnitという型になりました。
ローカル変数定義
ローカル変数はvalで定数、varで変数を表すようになりました。
val a: Int = 1
val b = 2
val c: Int
c = 3var x: Int = 3
x += 1
コメント
コメントはJavaから変化無し
// 1行の場合はスラッシュ2つ
/*
複数行の場合は"/* */"でくくる
*/
文字テンプレートの使用
文字テンプレートとは
var a = 3
var str = "a is $a" // a is 3
str = "a + 3 is ${a + 3} // a + 3 is 5
こんな感じで、"$"(ドルマーク)をつけると
文字列の中で、"$"の後の式を評価した値で置換してくれるってやつ
JavaでもString.formatとかでできたけど断然こっちの方が使い易そう。
条件式(というかif式)の使用
if文が式になりました。どういうことかと言うと
if (a > b){
println(a)
} else {
println(b)
}
今まで通り上記みたいな書き方はできますが、
println(if (a > b) a else b)
こんな感じに、ifは(a > b)を評価した結果がtrueならaを、falseならbを返す式になりました。
Javaでいうif文と3項演算子が1つになった感覚ですかね。
実際、上の2つのソースをコンパイルしたらif文と3項演算子になってました。
Null値とNullチェックの使用
KotlinではNullを代入する型と代入しない型で型が変わります。
var a : Int // nullは入らない(正確にはnullが入るとエラーになります。)
var b : Int? // nullが入る
まぁ"?"をつけるだけです。
実際は、"?"の付いている方はJavaの型と同様で、"?"が付いている方は変数に値が代入される前にnullチェックが行われ、nullの場合はエラーとなるようになります。
この状況で
println(a * b)
などとするとbがnullの可能性があるためエラーとなりますが、
if (b != null){
のようにnullチェックを行うとその中では自動でnullでは無い型へキャストしてくれます。この辺は優秀ですね。Javaじゃいちいち書かなきゃいけなかったチェックは不要になりますね。
型チェックと自動キャストの使用
Kotlinさんは賢いことに型チェックを行った変数やプロパティは自動でキャストしてくれます。
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// この括弧内ではobjはStringにキャストされます。
return obj.length
}// 型チェックの括弧の外なのでここではobjの型はAnyです。
return null
}
上で、Any型はJavaのObject型、ifの中で使われている"is"は"instanceof"です。上の類似で下のような場合も自動的に型がキャストされます。
fun getStringLength(obj: Any): Int? {
if (obj !is String) return null//この括弧内ではobjはStringにキャストされます。
return obj.length
}fun getStringLength(obj: Any): Int? {
// "&&"の右側ではobjはString型にキャストされます。
if (obj is String && obj.length > 0) {
return obj.length
}return null
}
forループ
forも書き方が変わりました。
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println(item)
}
これは型が省略された感じですね。
Javaなら、
for (String item : items)
とかなんでちょっと短くなったかなって感じです。
val items = listOf("apple", "banana", "kiwi")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
こっちのインデックスで回してく方はかなり短くなってくれてると思います。
Javaなら、
for (int i = 0; i < items.size(); i++)
ですからね。
whileループ
whileは変わり無しですね。
val items = listOf("apple", "banana", "kiwi")
var index = 0
while (index < items.size) {
println("item at $index is ${items[index]}")
index++
}
when式
これはJavaでいうところのcaseに近いですが、caseよりも汎用的に使えそうです。
fun describe(obj: Any): String =
when (obj) {
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
objの値や型で場合分けしてくれるわけです。複数の条件にしたい場合はカンマでつなげます。(1, 2 -> "One or Two"みたいに)
range
".."を使うことにより範囲を表現することができるようになりました。
if (x in 1..5) // xが1から5の間にいる場合
for (y in 1..5) // yは1から5まで1つずつ増えていく
1..5でリストが作られるとかかと思ったんですが、1から5まででforを回してるだけでした。
for (x in 1..10 step 2) {
print(x)
}
for (x in 9 downTo 0 step 3) {
print(x)
}
こんな書き方もできるらしい。
collections
forループとwhen式のところでもちょっと触れましたが、collectionsに対して
for (item in items) {
println(item)
}
とか
when {
"orange" in items -> println("juicy")
"apple" in items -> println("apple is fine too")
}
とかができて。(whenは引数無しでも大丈夫、中が3項演算子だから条件式にさえなってればいいんですね。)
fruits
.filter { it.startsWith("a") }
.sortedBy { it }
.map { it.toUpperCase() }
.forEach { println(it) }
ラムダ式は括弧が波括弧に変わりましたが、大体一緒ですね。
まとめ
Javaで冗長だと思ってた部分がかなり省略されてる印象です。
省略された感じはしますが、書き方とかどうも学習コストは多少上がった?感じを受けました。元々Javaだからかもしれませんが。
地味に書き方変わってるので、Java8の書き方ができる人ならまぁそんなに苦労することもなさそうに思いますが、ちょっと前のJavaまでしかわからないっていうような人だとちょっと大変かもしれませんね。
ただKotlinの方がコードを書くの自体は楽しそうな気がします。
Kotlinを使ってみる
どうもShZgZです。
非常に暑く、我が家付近では雨が続いております。
皆さんはいかがお過ごしでしょうか?
私は普段Javaエンジニアとして働いていますが、今回はちょっと遅くなりましたが、Kotlinを触ってみようかと思ってます。
発表されたのは2011年7月20日とのことですが、その頃は全然知りませんでした。
(そもそもその頃はエンジニアですらありませんでした。)
とはいえ、一昨年くらいからちょいちょい話は聞いていて、今回GoogleさんがkotlinをAndroidの公式言語に追加するということがありました。
そのため、ちょっくら触ってみようというわけです。
仕事ではAndroidには全く関わりがありませんが、どうにもJavaとの互換性が高く、Javaよりもコード量が少なくて済むとかなんとか。期待に胸が膨らみます。
それではまずはやはりコンパイラを入れるところからやっていきます。
因みにOSはMac OS Xです。
インストールですが、MacでHomebrewが入ってれば以下のコマンドで一発です。Homebrew — macOS 用パッケージマネージャー
(因みにですが、ココでブラウザでも実行できます。)
brew install kotlin
簡単に文法とか確認するだけならREPLが一番 ♪
ただJava(Version 1.8)にはありません。1.9で追加されるとのことですがまだありません。
しかしKotlinにはREPLがあるということなので以下のコマンドよりREPLを実行
$ kotlinc-jvm
Welcome to Kotlin version 1.0.1 (JRE 1.8.0_60-b27)
Type :help for help, :quit for quit
>>>
それではいつものやつやってみます。
Javaならこんなんですね。
System.out.println("こんにちわ。Javaの世界 !!");
Kotlinではこんな感じらしいです。
println("こんにちわ。Kotlinの世界!!")
お分かりでしょうか?
そうです!!
とうとう標準出力メソッド(println)がデフォルトで使えるようになりました。
もう一つ比較で、
Javaならこんな感じ(注:ソースはイメージです。)
>>> static void test(String str){
... System.out.println("Hello, " + str + "!!");
... }
>>> test("TEST");
Hello, TEST!!
Kotlinだとこんなのになります。
>>> fun test(str : String){
... println("Hello, $str!!")
... }
>>> test("TEST")
Hello, TEST!!
ここまでのぱっと見の相違点として
・ まずメソッド定義がfunになった。楽しそう!!
・返り値の型がいらんくなった。あえて書くならvoidじゃなくてUnitにするらしい、↓みたいに。
fun test(str : String): Unit {
・printlnの中で引数を引用する際に"$引数名"でよくなった。JavaでもString.formatとか使えばいけたけど、これがデフォルトのprintなのは結構助かりそう
・そして、セミコロンがいらん。セミコロンがいらん。
とりあえず今回はこれくらいで。
今回は簡単な出力しか試さなかったけど、他の方々が書いてるコードを見るとJavaで書くよりも結構短くなってる印象です。
Javaとの完全互換(Javaで作ったクラスをKotlinで呼べて、Kotlinで作ったクラスをJavaで呼べるとかとか)であることから平行した開発も出来る。Kotlinへの移行を考える際も最悪Javaに戻れるっていう安心感もある。
ただ、今日までエンジニアで出向いた現場でJavaのバージョンは大体1.7以下だった。(今の現場は1.8だけど、1.8で追加されたStreamとか使いまくるとあまり周りから良い顔はされない。まぁ悪い顔されるわけでも無い)
それから考えると、もうすぐJavaは1.9が出て(今のところ2017年9月まで延期っぽい)、Kotlinも盛り上がってきてるけど、SESで出向く先のちょっと大きめの会社の下請けでは採用されるのには結構時間が掛かりそう。
とりあえず個人的にはもうちょっと使ってってみようかと思います。
Rust1日目
どうもShZgZです。
普段の仕事ではまず使うことは無いんですが、
最近Rustが熱い
全く触ったことの無い言語で
(とは言っても私はJava以外は殆どまともに触ったこと無いんだけど)
とりあえずJava以外も触っていってみようということで触っていきます。
ちょっとWikiさんを参照したところ
- 作った人・・・Graydon Hoare(グレイドン・ホアレさんって読むらしい、最初はホーア論理の人なのかと思ってしまった、恥ずかしい)
- 特徴・・・安全性、メモリ管理、並列性
そもそも最初にRustに対して興味を持ったのはヴァルちゃんが使ってたからどっかの記事でRustは早い・安全・並行的な部分を押していたからです。
後は、そもそもRustはOCamlで書かれてたらしいんですが、数年前にML系の言語を使っていたためちょっとした懐かしさもあり、Rust使ってみようかなと。是枝くんも綺麗だって言ってたし。
とりあえずお勉強するにあたってテキスト的なものはあるかなと探したところバッチリ公式にThe Bookなるものがあると。
日本語版もあるのですが、ちょっと更新が遅いっぽいのと英語だけど結構読み易い感じがするので、英語版のほうを参考にしていきます。まぁこのドキュメント訳していくよって話では無いですが、軽い要約くらいな感じにはなっちゃうかもしれません。悪しからず。
全然言語の導入に行けませんでしたが、次回から入っていきます。でわ。