以下の内容はhttps://let.blog.jp/tag/Nimより取得しました。


Nim の {}
Python でいう dict の {}
Nim でも同じかなと思って使ってみても思い通りに使えません

let value = {"foo":"bar"}

echo value["foo"]
echo value.foo

この echo はどちらもエラーです
エラーはアクセスのところなので {} の記法は構文エラーではないようです

チュートリアルなどドキュメントを検索しても基本的なところでは使われていないようで 唯一 set で使うというのがありました
ですが set は

let value = {"foo", "bar", "baz"}

という形式で少し違うものです

Dictionary で調べたほうが早いと思って探すと Nim では Table らしいです
作り方はこういうの

let table = to_table({"key": "value", "other": "things"})

to_table 関数を通すみたいです
じゃあ to_table に入れる前の {} だけは一体何なの?

検索してもそれらしいのがヒットしないので直接型を見てみました

import typetraits

let value = {"foo": 1, "bar": 2}
echo type(value)
# array[0..1, (string, int)]

タプルの配列になってるみたいです

let value2 = [("foo", 1), ("bar", 2)]

と同じということでしょうか

let value = {"foo": 1, "bar": 2}
let value2 = [("foo", 1), ("bar", 2)]
echo value == value2
# true

一致しました
この辺は Python とは違うみたいです
{} だけで Table を作成してくれたらいいのに

わかってから探すと意外と簡単にマニュアル中で見つかりました
https://nim-lang.org/docs/manual.html#statements-and-expressions-table-constructor

Table はよく使うデータ構造なので基本やチュートリアルのドキュメントで紹介しておいてほしいですね
ファイルから重複行を除外する(つづき)
前記事の続きです
重複行を削除して同じ行は 1 回だけにしたいですが Linux コマンドだと sort コマンドが必要です
ソートするのは無駄だなと思ってソートしないものを作ってみたらソートするより遅かったです
sort コマンドでのソートはマルチスレッド化されていることや自作の方は Python のコードという理由もありますが実行時間ではソートしたほうが速くなっていました

無駄な処理があっても速いのならソートすればいいとなるのですが 本来の並びが維持されない問題があります
ググっても並びをもとに戻す良さそうな方法が見つからないということもあり コマンドで頑張るよりは Python で作ったものを使えばいいかなと思ってます
ただ ソートしてるのより速度で負けてるのが気になるところです
Python みたいなスクリプト言語ではなくネイティブな言語ならもっと速くなりそうということで別言語でも作ってみることにしました

そうは言っても C/C++ 言語は使いたくないです
今のコードが Python なので 構文が似てる Nim にすることにしました

まずは元の Python のコード

import sys

if len(sys.argv) < 2:
exit()

filename = sys.argv[1]

with open(filename) as file:
set = set()
while line := file.readline():
line = line.rstrip("\n")
if line not in set:
set.add(line)
print(line)

Nim 版

import std/sets
import std/cmdline

let params = commandLineParams()
if params.len == 0:
quit()

let filename = params[0]

block:
let file = open(filename)
defer: file.close

var set = HashSet[string]()
var line: string
while file.readLine(line):
if line notin set:
set.incl(line)
echo line

似てはいるものの 細かいところは結構違っていて Python からなら移植が楽かというと そうとも言い切れないくらいでした
慣れていて これはこう書き換えるというのが頭に入ってるならともかく 初心者がやってみるには結構時間がかかるものだと思います
一応以前にも少し使ったことのある言語なのですが ほぼ覚えてなくて調べながら書いてました
それに Nim はちょうど今月の頭に v2.0 のリリースがされて色々変更があったようです
std/os にあった関数が std/cmdline などに移動していました
https://nim-lang.org/blog/2023/08/01/nim-v20-released.html

あと一番困るのがインデントはスペースのみという制限です
1 種類だけに制限するならインデントのためにある文字のタブにすべきだと思いますね
タブと違ってスペースは可変じゃないのでアクセシビリティなどでも劣ってると言われることが増えているのにこの考えなのは残念です
コンパイル前の処理として全 .nim ファイルのタブをスペースに置換した一時ファイルを作ってそれらを使ってコンパイルするよう一手間必要になります

それは置いておき実行時間の比較です

[root@552d14e2dbe8 n]# time ./a data.txt
aaa
bbb
ccc

real 0m34.028s
user 0m33.867s
sys 0m0.160s

[root@552d14e2dbe8 n]# time ./a data.txt
aaa
bbb
ccc

real 0m33.575s
user 0m33.438s
sys 0m0.136s

遅っ

Python でも

real    0m12.368s
user 0m12.249s
sys 0m0.110s

くらいだったのですけど
ネイティブ系の言語で遅いときはだいたい最適化オプションがないからだと思うので探してみます

nim c --d:release --opt:speed a.nim

のようにしてビルドすれば リリース用ビルドで速度に最適化できるそうです
これでビルドし直して試してみます

[root@552d14e2dbe8 n]# time ./a data.txt
aaa
bbb
ccc

real 0m5.737s
user 0m5.697s
sys 0m0.040s

[root@552d14e2dbe8 n]# time ./a data.txt
aaa
bbb
ccc

real 0m5.809s
user 0m5.749s
sys 0m0.060s

Python よりも速くなりました
sort + uniq よりも速いですね

ただ条件としてほとんどが重複行という前提があります
重複率を下げるため出力条件を変更してみました

for i in range(50 * 1000 * 1000):
print(i % 1000000)

これで実行してみると Nim だと 19 ~ 20 秒です
ソートを行う方は 21 秒だったので 差は縮まったけど一応は勝ってると思ってました
ただやっぱりソートをする方は実行するごとに速くなって 21 → 10 → 7.1 → 6.8 秒まで速くなりました
これ以上は速くならないようです

読み込んでるファイルは同じなのでファイルのキャッシュなら Nim 側の時点でキャッシュされてるはずですし そっちでも高速化しそうですがそんなことはなかったです
どういう仕組みなんでしょうね



以上の内容はhttps://let.blog.jp/tag/Nimより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14