LoginSignup
6

More than 3 years have passed since last update.

Nimの便利な標準ライブラリ sugar

Last updated at Posted at 2020-12-22

はじめに

こんにちは、meganeoです。
sugarというNimの面白い標準モジュールを見つけたので紹介します。

環境

Nim 1.4.2

sugarとは

sugarは、Nimの標準モジュールの1つです。
macroを使い、複雑なものを簡潔に書けるようにしています。

import

import sugar

=>

=>は、JavaScriptでいうところのアロー関数です。
無名関数を簡潔に書くことができます。

proc TwoFunc(f: proc(int, int): int): int =
  f(2, 2)

TwoFunc((x, y) => x + y)

->

->は、↑のような高階関数を定義するとき、引数を簡潔に書くことができます。

proc TwoFunc(f: (int, int) -> int): int =
  f(2, 2)

dump

dumpは、引数に入れた式とその結果を出力します。

let
  x = 10
  y = 5
  a = "a"
  b = "b"

dump(x + y) # output: x + y = 15

dump(a & b) # output: a & b = ab

capture

caputureは、ループ内で任意の条件に当てはまる場合に、グローバルスコープに値を返すのに便利です。

# グローバルスコープで関数型の変数を先に定義しておく
var MyClosure: proc
for i in 3..5:
  for j in 4..8:
    if i * j == 28:
      capture i, j: #キャプチャーしたい値を引数にする
        MyClosure = () => dump(i * j)

MyClosure() # output: i * j = 28

当たり前ですが、当てはまる条件が複数の場合は最後にループした方が優先されます。

var MyClosure: proc
for i in 3..5:
  for j in 4..8:
    if I * j in [28, 32]:
      capture i, j:
        MyClosure =  () => dump(i * j)

MyClosure() # output: i * j = 32

dup

dupは、引数として渡した変数を内部で変更してしまう関数(いわゆる破壊的メソッド)を、元のデータに影響なく使うことができます。

import algorithm

var a = @[5, 4, 3, 2, 1]
echo sorted(a) # output: @[1, 2, 3, 4, 5]
echo sorted(a) == a.dup(sort) # output: true

collect

collectは、Pythonの内包表記のように、配列を元に配列や辞書を生成できるマクロです。
collectのブロック内の最後の式が評価され、その配列が指定した関数(ここではnewSeq)に渡されるようです。
つまり、自作のコンテナ型のコンストラクタも使うことができるということです。

let nineNum = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
let oddNum = collect(newSeq):
  for i in nineNum:
    if i mod 2 == 1: i

echo oddNum # output: @[1, 3, 5, 7, 9]


let evenNum = collect(newSeq(4)): # 長さ指定もできる
  for i in nineNum:
    if i mod 2 == 0: i

echo evenNum # output: @[2, 4, 6, 8]

また、table{key:value}setmySet.inclのようにtablesetを生成するには、ブロック内の最後の式を次のように書きます。

import sets, tables

let nineTable = collect(initTable(9)):
  for i, d in nineNum.pairs: {i: d} # {key: value}のように書く

echo nineTable # output: {}

let nineSet = collect(initHashSet):
  for d in nineNum.items: {d} # 入れたい値を {} で囲う

まとめ

アドベントカレンダーに参加すること自体初めてなので至らない点もあるかと思いますが、これをきっかけに、少しでもNimに興味を持っていただけたら嬉しいです。最後までお読みいただきありがとうございました!

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
6