投稿

Kotlinの"きほん"の"き"

KotlinはJetBrains社が開発した汎用プログラミング言語です. 基本的にはJVMで動く言語ですが,JavaScriptへのトランスパイルやネイティブコンパイルもサポートしています. Javaとの違い KotlinはJVM上で動くためJavaと比較します. まず,第一に違うことはnull安全性です.Kotlinはnull許容型があり,nullを入れれる型と入れれない型を明確に区別しています.最近の言語の流行りですね,すごく使いやすいです.null非許容の型にnullを入れるとコンパイルエラーになりますし,null許容型をnullチェック無しで使うとコンパイルエラーになります.安心です. 次のKotlinの違いは演算子のオーバーロードです.Javaでは演算子のオーバーロードは提供されていませんが,Kotlinでは提供されています.そして,面白いことにJavaのメソッドも条件を満たせばKotlinから演算子として使えます.例えば equals メソッドとかは == 演算子として使えます.ちなみにJavaの == はKotlinでは === です. Javaにもあるような機能なので微妙ですが,古いJavaをお使いの方であればKotlinの型推論は便利だと思います(ダイヤモンド演算子じゃないです).Kotlinは変数宣言の際 val と var を使い変数を宣言します.基本的には val を一番良く使います.そして,この2つは型を明示的に指定しない場合は自動的に型推論をしてくれます.便利です. まだまだ,いろいろ違いはありますが,長くなりそうなのでここで一旦切ります. 環境 Kotlinの環境は同じくJetBrains社が開発しているIntelliJ IDEAが最強に相性が良いです. AndroidはAndroid StudioがIntelliJ IDEAをベースにしているのでAndroid Studioでも同等の機能が使えます. 関数 Javaは全てのメソッドが何らかのクラスに属している必要がありました.しかし,Kotlinはその制約がありません.そしてmain関数もクラス内ではなく外に書きます. とりあえず,Hello, Worldから始めます. fun main ( ) { println ( "Hell

[C++] 並行・並列処理に関連する標準ライブラリまとめ

C++は並行・並列処理を行うにあたってスレッドの管理や排他制御などの機能が標準ライブラリとして提供されています。 本記事ではそれらのライブラリをまとめて紹介します。並行・並列処理による未定義動作で1日無駄につぶす人が減るように願っています。 並行・並列処理とは まず、並行処理と並列処理の違いについて軽く説明します。 並行処理は複数の処理が同時に実行可能であることで、実際に同時に実行されているかは関係ありません。例えばスレッドを2つ立ち上げるプログラムがあった場合は並行処理となります。というか最低でも並行処理といえます。 では、並列処理はどういうことかというと、実際に同時に動きます。最近のCPUであれば2コア以上実行コアが存在すると思いますが、並列処理はこのコアを同時に使い複数のスレッドやプロセスが同時に動作することを言います。 つまり、並列処理は確実に並行処理ですが、並行処理は並列処理といえません。 並列処理になるかどうかは環境(CPUやOS)などに依存するため、本記事では並行処理に関して考えます。 並行処理と未定義 並行処理でよくある未定義動作はデータ競合(data race)です。データ競合は次のような条件を満たすをおきます(単純のためいろいろ端折ってあります)。 複数のスレッドが同時にアクセス 最低でも一つが書き込み 最低でも一つはアトミック操作でない アトミック操作は不可分な操作で変数へのアクセスを分割しないで行います。CPUによっては専用の命令が存在します。 この条件はかなり満たしやすいです。ちょっとでも気を抜くと未定義の世界に足を踏み入れてしまうので、気を付けてください 競合状態(race condition) データ競合と似た概念に競合状態というものがあります。データ競合と競合状態はレイヤーの違う話ですが、同じような文脈で語られることが多いので混同しやすいようです。 競合状態は操作が不可分であるものが実際には分割されてしまうときに起きます。 例えば、金銭の授受を行うアプリケーションを考えます。下のコードが例ですが、このプログラムはifで支払い能力があることを確認して授受を行います。この支払能力の確認と渡す側(from) から値を引くことは分割するとまずいことになります。 なので、いくらfromやto, amountがデータ競合を起こさないようにしてあっ

KotlinでPythonのargparseみたいなのを作ってみた

コマンドライン引数パーサーはいろんな言語に実装されています。自分が初めてまともに触った引数パーサーがPythonに標準でついてくるargparseでした。 argparseは標準ライブラリの一つではありますが、かなり実用的な引数パーサーとして使用できます。helpやusageも表示してくれて超便利です。(Pythonは標準ライブラリonly縛りでもある程度戦えるからすごい!) 自分はこれまでこのargparseがよく使う言語にあると良いなーと考え、とりあえず C++に実装 しました。 今回はその第二弾(?)と言うことでKotlinに実装しました。 リポジトリは GitHub にあります。 ライセンスはApache License 2.0です。 使い方  使い方はできるだけオリジナルのargparseに合わせました。 import net.sileader.argparse.ArgumentParser import kotlin.system.exitProcess fun main(cmd: Array<string>) { val parser = ArgumentParser("program", epilogue = "test program") parser.addArgument("-v", "--version", action = "store_true", help = "show version") val sub = parser.addSubParser() val push = sub.addParser("push", "push") push.addArgument("-d", "--data", action = "store", help = "data") val pull = sub.addParser("pull", "pull") pull.addAr

C++11の機能 (scoped enum, 可変長テンプレート, usingによる型エイリアス)

C++11の機能を紹介するシリーズ第五弾です。 今回はscoped enum, 可変長テンプレート, usingによる型エイリアスについて紹介していきます。 scoped enum Cからあるenumは中で定義した名前がそのまま垂れ流しになってしまっていました。これにより、すでに使われている名前とかぶるなどの問題がありました。 また、enumは整数型への暗黙的な型変換ができましたが、scoped enumは明示的に型変換を行わない限り整数型に代入することはできません。 enum class RgbColor { Red, Green, Blue, }; // 使う RgbColor rc = RgbColor::Red; int irc = static_cast<int>(rc); 可変長テンプレート C++11より前のテンプレートはテンプレート引数を可変長にすることができませんでした。そのため、最小1から最大10の任意の個数のテンプレート引数を受け取るには10個の関数テンプレートなどを書く必要がありました。しかし、この方法では最大の個数が10に制限されてしまいますし、何よりもテンプレートで省略可能であるはずのことが全く省略できていません。 そこで、C++11では0個以上の任意の個数のテンプレート引数を受けることができる可変長テンプレートが追加されました。 例として、引数に取った値をスペース区切りで標準出力に出力するコードを以下に示します。 template<class Arg> void print(Arg arg) { std::cout<<arg<<std::endl; } template<class Arg, class... Args> void print(Arg arg, Args... args) { std::cout<<arg<<" "; print(args...); } この例で出てくるclass...が可変長テンプレートです。テンプレート引数の型(?)の部分はテンプレートで使えるものであれば何でも使えます。この例ではclassを使っていますが、intで

自作OSをやってみて良かったこと

自作OSアドベントカレンダー2019 11日目 (12/11)です。 アドベントカレンダーには初めて参加させていただきます、拙い文章ですが温かい目で見守っていただけると幸いです。 ここでは、自作OSに挑戦してみて良かったなと思ったことを書いていきたいと思います。 自分はx86でBIOS(レガシーBIOS)とUEFI(x64)から起動するタイプを途中まで(というか割と序盤で脱線していきました)作った程度です。 知識が増える 自作OSをやってみたことで、いるか要らないかはさておき知識が増えました。 例えば、OSが起動するまでに起きていることや呼出規約、UEFIとBIOS、アセンブリとインラインアセンブリとかとか... 普通に生きていれば、あんまり気にすることのなかったことでも、OSの自作に挑戦したことで、自分で調べたり、作ってみたりして色々知ることができました。 OSは現代的なシステムの基底となっているシステムなので、これを知っておくと大分能力の幅が大きくなると思います。実際に色々役に立っています。 OSの偉大さがわかる 自作OSでは、当たり前ですがOSの力を借りれません。一番基本(?)のデバッグ方法のprintfデバッグすらできません。 そういう環境を経験すると意外とOSのお世話になってるなと実感します。 OSのすごさを感じた点としては、Linuxのプロセススケジューラの実装があります。これを知ったとき「なにそれ、めっちゃ頭いいじゃん!!」とか思いました。自分が実装したら普通にキューに突っ込んで「優先度?なにそれ美味しいの?」みたいな実装になりかねないのでかなり感動しました。 プログラミング言語に関する能力が向上する 自分はCとC++でOSを書いてみたことがありますが、標準ライブラリがないので(newlibとか使えば良いのでしょうが)、必要な機能を作ることになります。 簡単なものならstrcmpやstrcpyなどから、printfのような作る前だと、「これどう作るんだ...」となる関数まで色々作れます。(競プロとは違うパズルみたいな楽しさがあって好きです) 普通にアプリを作っているときには使わなかったり気づかなかったりした機能にも気づけたりしてとてもおもしろいと思います。 自分はここで自作OSそ

C++11の機能 (関数のdefault・delete宣言, overrideとfinal指定子, 移譲コンストラクタ, 継承コンストラクタ)

C++11の機能を紹介するシリーズ第四弾です。 今回は関数のdefault・delete宣言、overrideとfinal指定子、移譲コンストラクタと継承コンストラクタを紹介していきます。 関数のdefault・delete宣言 コンストラクタや代入演算子などにはユーザーが指定しなくても、必要に応じてコンパイラがそれらを自動的に作ってくれます。 ですが、「デフォルトで作ってほしくないんだよ」とか「コピーはしてほしくない」とか「この関数は呼べないようにしたい」という需要に答えるとなると、privateな部分に宣言だけ書いておくなど、あんまり綺麗でないやり方をするしかありませんでした。 そういうときに使うことができるのがdelete宣言です。delete宣言された関数は暗黙的に実体化されること無く、delete宣言された関数を必要とするコードが存在した場合コンパイルエラーになります。 対して、default宣言は、コンパイラが自動的に生成してくれるコードを明示的に生成させる宣言です。コピーやムーブで特殊な処理を行わない場合などはいちいち書くのは面倒で間違いの元になります。こういったときに使えます。また、virtualやinlineなどの指定子をつけた上でdefault宣言することもできるので、「仮想関数にするけど処理自体はコンパイラのデフォルトの動作で構わない」みたいな場合にも使えます。 struct Klass { Klass() = default; // デフォルトのコンストラクタはコンパイラのデフォルトで生成 Klass(const Klass&) = delete; // コピーコンストラクタは削除 Klass(Klass&&) = default; virtual ~Klass() = default; // 仮想関数としてデストラクタをデフォルト生成 }; overrideとfinal指定子 overrideはあのオーバーライドです。この指定子をつけることでこの関数はオーバーライドしているということを明示することができます。override指定子を付けているにもかからわずオーバーライドできていない場合はコンパイルエラーになります。なので、間違ってオーバー

C++11の機能 (constexpr, 右辺値参照・ムーブセマンティクス)

C++11の機能を紹介するシリーズ第三弾です。 今回は、constexprと右辺値参照・ムーブセマンティクスを紹介します。 constexpr constexprはコンパイル時定数を表現するための機能です。 コンパイル時定数はコンパイル時には値が確定している値のことで、コンパイル時定数になっていると展開されたり先に計算が行われるなどがされ実行時の効率が向上する可能性があります。 constexprは変数、関数、コンストラクタにつけることができます。 constexpr変数 変数につける場合はconstの代わりに記述することができます。 constexpr int ZERO = 0; このように記述するとZEROがコンパイル時定数になります。 コンパイル時定数はテンプレート引数として渡せます。 template<int N> void func() { ... } // 使う constexpr int ZERO = 0; func<ZERO>(); constexpr関数 関数にconstexprをつけると定数式が必要な場合にコンパイル時に計算されます。 逆に言うと必要のない場合や引数がコンパイル時定数でない場合は実行時に普通の関数として使われます。 C++11のconstexpr関数はreturnはひとつだけifやwhileなどの制御分が使えないなど、かなり制限がきついので、C++11のレベルで使うのは余りおすすめできません。C++14以降になるとこの制限がだいぶ緩くなるのでかなり使いやすくなりました。 constexpr int square(int n) { return n * n; } 右辺値参照とムーブセマンティクス 右辺値参照 右辺値参照はその名の通り右辺値を参照する参照です。 右辺値は簡単に言うと名前のないオブジェクトや破棄しても問題ないオブジェクトのことです。 この機能が登場するまでは右辺値も左辺値も同じ参照を使って参照していました。ですが、破棄しても問題ないオブジェクトと、破棄していけないオブジェクトが区別できないと、無駄な処理をしてしまうなどの問題があります。 これを区別するために登場した機能が右辺値参照です。