LoginSignup
9
3

More than 5 years have passed since last update.

Dlang-TourでD言語を少し勉強したメモ

Last updated at Posted at 2017-12-04

これはなにか

  • 2017年は新しい言語をゼロから勉強してなかったことを思い出したので、D言語をDlang-Tourで少しだけ勉強してみたのでその記録です。
  • 自分用のメモを雑多にまとめたので読みづらいです。ごめんなさい。

Dlang-tourを一通り読んで手元で動かしてみた所感

  • 自分はc++よりもjavaの方が経験が長いのだが とてもjavaっぽいc という印象を受けた。特にclassの定義はjavaと殆ど同じ。
  • 最近の言語っぽく、oopも関数型スタイルもこなすマルチパラダイムな言語でありながらメモリ管理をマニュアルで出来たりと守備範囲がめっちゃ広い
  • 一方で、守備範囲広すぎて、どういう用途が向いているのかパッと分からないという気もした。dlangじゃないとこれができない!というのが、自分の勉強不足が理由でまだ分かってないせいかもしれないけど…
  • とはいえ、速度を求める場合やメモリ制限が厳しい場合に、バイナリをシュッと出力できるモダンでシンプルな言語がほしい時にはいいかもしれない。組み込みとか、あとは競プロにも良さそう。

なぜD言語なのか

  • いつも利用してる図書館でたまたま見つけたプログラミング言語Dを勉強の息抜きで読んでみたら、思ったよりとっつきやすかったので勉強してみようと思った

学習記録

officialサイトのトップページに書いてある宣伝文句を読んで雑に訳した

  • 概要
    • D言語は多目的プログラミング言語だよ
    • 静的型付け、システムレベルアクセス、Cっぽいシンタックス
    • 安全性とプログラマーの生産性によって、効率性とコントロールとモデリングを併せ持つよ
  • なんでDなの
    • 利便性
      • Dは動的言語のように冗長な型を書かずにでかいコードが書けるよ
      • 一方で、静的インターフェースが型やプロパティを推論するので、静的世界と動的世界の良いとこどりが出来るよ
      • 自動メモリ管理によって安全でシンプルで堅牢なコードにするよ
      • Dはscoped resource managementとscope statementをサポートし、書きやすくて読みやすい決定論的トランザクションコードが書けるよ 1
      • 線形および連想配列、slice、rangeがあるので、日々のプログラミングタスク(小さなものから大きなものまで)をシンプルかつ楽しいものにするよ
    • パワー
      • Dはクラシックなポリモーフィズム、値セマンティクス、関数スタイル、ジェネリクス、汎用プログラミング、契約プログラミング等を提供し、それらは全て調和を保ちつつ統合されているよ
      • Dは並行性に対する革新的なアプローチを提供するよ。そのための機能として、真のイミュータブルなデータ、メッセージパッシング、デフォルトでの非共有性、複数スレッド間の真の不変データ共有管理を特徴としているよ。
      • シンプルなスクリプトから大規模なプロジェクトにいたるまで、Dは、ユニットテスト、情報隠蔽、洗練されたモジュール性、高速コンパイル、正確なインタフェースなど、アプリケーションのニーズに応じて幅広く拡張できるよ
    • 効率性
      • Dのコードは自然と効率性の高いネイティブコードにコンパイルされるよ
      • Dは大抵の「明確」なコードが速く、そして安全になるようにデザインされているよ
      • 時には、速度と制御のために、型安全の境界から逃げる必要があるかもしれないけど、そのようなレアケースに備えて、Dはポインタ、型変換、C関数アクセス、手動メモリ管理、独自のアロケーター、インラインアセンブリコードを提供するよ

Dlang tourの最初の方を読んでみる

$ brew install dmd
  • package managerである dub を使ってprojectのtemplateが作れるらしいのでやってみる。
$ brew install dub
$ dub init hello
dub init hello
Package recipe format (sdl/json) [json]:
Name [hello]:
Description [A minimal D application.]:
Author name [KazuhiroSerizawa]:
License [proprietary]:
Copyright string [Copyright © 2017, KazuhiroSerizawa]:
Add dependency (leave empty to skip) []:
Successfully created an empty project in '/Users/seri/Documents/d-work/hello'.
Package successfully created in hello

$ cd hello
$ tree .
.
├── dub.json
└── source
    └── app.d

app.d の中身は

import std.stdio;

void main()
{
        writeln("Edit source/app.d to start your project.");
}

実行するにはprojectの直下で dub run で良いようだ。 ( dub だけでもcompileされて実行された)

$ dub run
Performing "debug" build using dmd for x86_64.
hello ~master: target for configuration "application" is up to date.
To force a rebuild of up-to-date targets, run again with --force.
Running ./hello
Edit source/app.d to start your project.

moduleについて

  • dmdコンパイラに付随する標準ライブラリはPhobosという名称がついている
  • Phobosのnamespaceは std 。c++と同じか。
  • import キーワードでモジュールを読み込んで使えるようにする
import std.stdio;
  • 読み込むシンボルを選択的に限定することもできる
import std.stdio : writeln, writefln;
  • import句はファイルのトップにも書けるが、関数の中にも書ける
void main(){
    import std.stdio : writln;
    writeln("Hello World!");
}

moduleのpathについて

  • dのnamespaceはファイル階層と一致しており、例えば import my.cat で検索されるのは my/cat.d である
  • 何も指定しない場合、暗黙的にimportを実行するscriptのcurrent directoryを起点としてmoduleを検索する
  • moduleを検索する起点となるdirectoryを指定するにはコンパイル時に -I オプションでdirectoryを指定する
  • また指定したmoduleがファイルではなくdirectoryの場合コンパイラはそのdirectory配下の package.d というファイルをロードしようとする
    • pythonの __init__.py みたいなもんだろうか

余談:Dlang tourの日本語版に package.d を使うpath指定についての解説が入ってなかったのでPR出した

基本型

  • dlangの基本型はbool , byte, ubyte, char short, ushort, wchar, int, uint, dchar, long, ulong, float, double, real
  • 文字列は char がUTF-8、 wcharがUTF-16、 dchar がUTF-32に対応でそれぞれ使われるらしい
  • 型が異なる変数間の型変換は精度に影響しなければ許可される
  • 強制的な型変換には cast を使う
  • autoキーワードによって型推論ができる。 auto myVar = 7; だと myVar の型を intと推測する
  • 全てのデータ型は、初期値となる値を .init プロパティとして保持している。 int.init だと 0float.init だと nan を返す。

Memory管理

  • dlangもポインタ演算ができる
  • syntaxはc, c++と大体同じだが、mallocの代わりに new 演算子が使える
  • GCがあるのでnewした変数は自分でfreeしなくてもいい
int a;
int* b = &a;
auto c = &a; // aのアドレス
int *a = new int; // cで言うところの `malloc(sizeof(int))` に該当する?
  • dlangは3つのセキュリティレベルがある。 @system, @trusted, @safe
  • デフォルトは @system
  • @safe はメモリ破壊を防ぐためのdのサブセットであり、 @safe なコードは @safe または @trusted な関数のみ呼び出せるよう制限し、ポインタ演算を禁止したりする
void main() @safe
{
    import std.stdio;
    writeln("Edit source/app.d to start your project.");
    int a = 5;
    int* p = &a;
    int* c = p + 5;
}

コレを実行すると以下のエラーメッセージが出る

Error: cannot take address of local a in @safe function main
Error: pointer arithmetic not allowed in @safe functions

可変性

  • javaやc++でいうところの finalに該当する immutable という型修飾子がある
  • カレントスコープでのみ有効となる const もある
immutable int err = 5;
err = 6;
Error: cannot modify immutable expression err

関数定義

  • よくある感じ
int add(int lhs, int rhs) {
    return lhs + rhs;
}
  • 関数の返り値も auto で推論できる
auto add(int lhs, int rhs) {
    return lhs + rhs;
}

配列

  • 普通の静的配列、動的配列がある
  • 動的配列はスライスとも呼ばれ、range指定でデータの一部の参照を取り出すことができる
int[8] arr1; // 静的配列
int[] arr2 = new int[8]; // 動的配列
int[] arr3 = [1, 2, 3, 4, 5];
auto arr4 = arr3[1 .. $]; // スライスはrange指定で要素の参照(≠値コピー)を取り出せる
writeln(arr4); //=> [2,3,4,5];

foreach

  • dにはLLにはおなじみのforeachがある
foreach (int e; arr) {
    writeln(e);
}

foreach (i, e; [4, 5, 6]) { // iにはindexが格納される
    writeln(i, ":", e);
}

連想配列

  • いわゆるHash
int[string] hash;
hash["hogetarou"] = 1;
hash["fugatarou"] = 2;
writeln(hash["hogetarou"]); // 1

クラス

  • scopeの意味はjavaやc++と同じ模様
class Any {
    protected string type;

    // constructor
    this(string type) {
        this.type = type;
    }

    // finalは継承を禁止する
    final string getType() {
        return type;
    }

    // private
    private string hoge() {
        return "hoge";
    }

    // 継承して実装しないと使えない
    // abstractな関数が一個でもあるとnewできないabstract class扱いになる模様
    abstract string convertToString(); 
}

次はこれ読む

プログラミング言語D
IMG_20171104_225459.jpg


  1. サンプルコードを読んだ感じだとクロージャを書けるよってことらしい 

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3