Open6

D言語を触ってみる

こまもか🦊こまもか🦊

前から薄ら気になってたのでやってみる

知ってる知識

  • Cの代替を目指している
  • UFCS(.で関数を呼び出すやつ)が使える
  • デフォルトでGCが入っているが抜くこともできる
  • ツールチェーンが揃っている
  • マスコットが異常に有名

環境

  • Linux(Manjaro/Hyprland)
  • Vim(v9.1)
こまもか🦊こまもか🦊

dubとかdmdとかldcとかgdcとか色々ある(名前がイマイチ覚えずらい...)

まとめると、

  • dmd
    公式コンパイラ
  • ldc
    LLVMベースのコンパイラ
  • gdc
    gccベースのコンパイラ

dubはコンパイラではなくビルドツール(cargoみたいなやつ)

なのでとりあえずdmddubをインストールすればOK

https://zenn.dev/i16777215/articles/972724b0f6811e

こまもか🦊こまもか🦊

公式からシェルスクリプトのインストーラが配布されているのだけど、実行してもgpgでエラーが出てインストールできない。

なのでmiseasdf-dmdを使ってインストールする。

mise plugins install https://github.com/sylph01/asdf-dmd.git
mise use -g dmd

dubはGitHub ReleaseにバイナリがあったのでそれをDLした。
もしReleaseに対応しているOS/Archがなくてもdmdがあればビルドすることができる。
リポジトリをgit cloneしてdmd -run ./build.dすれば./bin/にバイナリが生成されている。手元で実行したらかなり重かったので注意

D言語はd-serveというLSPも提供している。
エディタの拡張機能でインストールされるし、インストールに関してはあまり意識はしなさそう。
一応リポジトリをcloneしてdub buildすればバイナリが手に入る。

こまもか🦊こまもか🦊

プロジェクトの作成はdub initでできる。

いくつか質問されるので適当に答えていく。

自分はこんな感じで答えた。

❯ dub init
Select a package recipe format:
1) sdl    2) json
#? [2]: 2 ←Jsonの方が読みやすそう
Name [dlang-fizzbuzz]: ←ディレクトリは既に作ってあるのでスキップ
Description [A minimal D application.]: ←後から編集できるだろうし適当にスキップ。
Author name [Comamoca]: ←これで良いのでスキップ
Select or enter an SPDX license-identifier (https://spdx.org/licenses/):
 1) BSL-1.0 (Boost)               8) BSD-
 2) MIT                           9) MPL- (Mozilla)
 3) Unlicense (public domain)    10) EUPL-
 4) Apache-                      11) CC- (Creative Commons)
 5) AGPL-                        12) Zlib
 6) GPL-                         13) ISC
 7) LGPL-                        14) proprietary
? [14]: 2 ←もっぱらMITライセンスを使っているため2を選択
Copyright string [Copyright © 2024, Comamoca]:
Add dependency (leave empty to skip) []:
     Success created empty project in /dlang-fizzbuzz
             Package successfully created in .

これでカレントにファイルが生成されているはず。

❯ tree
.
├── dub.json
└── source
    └── app.d

2 directories, 2 files

source/app.dがエントリポイントになる。
中身を見てみるとすでにプログラムが書き込まれている。

cat source/app.d
import std.stdio;

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

とりあえずこれを実行してみる

❯ dub run
    # デバッグ実行である旨のメッセージが表示される
Edit source/app.d to start your project.

dubは特に引数が与えられない場合、カレントのプロジェクトをビルトして実行する。(makeっぽい挙動)
なのでrunを付けなくても実行はされる。

❯ dub
    # デバッグ実行である旨のメッセージが表示される
Edit source/app.d to start your project.
こまもか🦊こまもか🦊

まずはおなじみのFizzbuzzを書いてみる。
matchとかmapが使えるのでRustっぽく記述できて気持ち良い。

import std.conv;
import std.range;
import std.stdio;
import std.algorithm;

void main()
{
	iota(30)
	.each!(n => writeln(fizzbzz(n)));
}

string fizzbzz(int n) {
	switch (n % 15) {
		case 0:
			return "FizzBuzz";
		case 3, 6, 9, 12:
			return "Fizz";
		case 5, 10:
			return "Buzz";
		default:
			return to!string(n);
	}
}

rangeまわりはこれを参考にした
https://qiita.com/umarider/items/dd47534bdc5ee06cb295

こまもか🦊こまもか🦊

なんとなく慣れてきた気がするので気象庁のAPiを叩いてみる。
一応Dにはcurlのバインディングが存在するけど、文字コードがらみが面倒だったのでサードパーティのdlang-requestsを使ってみる。
JSONのパースは標準のパーサーを使っている。

UFCSが使えるので型変換周りもスッキリ書けて気持ちが良い。

import requests;
import std.stdio;
import std.algorithm;
import std.array;
import std.conv;
import std.json;

void main()
{
    string url = "https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json";
    auto resp = getContent(url);

    JSONValue json = parseJSON(resp.toString);
    json[0]["timeSeries"][0]["areas"][0]["weathers"]
	    .array
	    .map!(a => a.str)
	    .array
	    .join("\n")
	    .writeln;
}