c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

7 libraries I made by Elixir ヾ(〃l _ l)ノ゙

qiita.com

12/5

Elixir を使って製品を作ってゐると、release して此れ程の時が経ち此れ程の人が利用してゐるのに樣々のものが足りない。此の世では、必要なものは作る事に成ってゐるさうだ。なので一つづつ作ってきた。

みなさんも一つづつ作ってゆきませう。世界。

  • holiday_jp
  • inner_cotton
  • Mnemonics
  • PQueue2
  • stream_gzip
  • stream_hash
  • witha

holiday_jp

holiday_jp | Hex

Japanese holiday.

Ruby にはholiday_jpと云ふ便利な gem が在る。日本の休日を database にしたものだ。

休日と云ふのは規則的な樣だが、法律で決まるものであり、法律の改正によって變はるものだ。年に 20 日弱しか無い休日は數十年前から先迄樂に羅列できる。複雜な規則を法律の改正日で条件分岐しながら書き起こすより、羅列して引いてくるはうがずっと樂で bug を出しにくい。千年後はどうなるかわからないが当分は充分である。

此の Elixir のholiday_jpは、Ruby の holiday_jp と同じ data を使ってゐる。函數は三つ用意してある。between/2holiday?/1on/1だ。

iex> HolidayJp.between ~D[2016-03-01], ~D[2016-03-31]
[
  %HolidayJp.Holiday{date: ~D[2016-03-20], week: "", week_en: "Sunday", name: "春分の日", name_en: "Vernal Equinox Day"},
  %HolidayJp.Holiday{date: ~D[2016-03-21], week: "", week_en: "Monday", name: "振替休日", name_en: "Holiday in lieu"},
]

iex> HolidayJp.holiday? ~D[2017-01-02]
true

iex> HolidayJp.holiday? ~D[2016-01-02]
false

iex> HolidayJp.on ~D[2017-02-11]
[%HolidayJp.Holiday{date: ~D[2017-02-11], week: "", week_en: "Saturday", name: "建国記念の日", name_en: "National Foundation Day"}]

inner_cotton

inner_cotton | Hex

Collection of recommended Elixir check utilities.

幾つか application や library を作ってゐると幾度も同じ library を入れる事に成る。静的 check tool でいつも使ふものを集めた。私の作ったものには全て此のinner_cottonを入れてある。意味は「中綿」、Lint(糸屑)を集めたもの。

現状では以下のものが入る。

  • Credo : Lint, coding style enhancer.
  • Dialyxir : Type checker using Dialyzer. Erlang 附屬の型檢査 tool を實行する。
  • InchEx : Document (ExDoc) improver.

HEAD では更に次のものが入る。

  • stream_data : Property base testing like QuickCheck. 多數の random data を使って性質 test を書ける。性質が常に成り立つか檢査するかのやうな事に使ふ。
  • EyeDrops : Guardの樣に、file の變更を監視して command を實行する。

mix cotton.initで各 tool 用の設定 file を置き、mix cotton.lintで Credo と Dialyzer と Inch が走り、mix testでいつも通り test が走り、mix cotton.watchで file の變更に合はせて lint と test が走る(HEAD では)。今はExCoverallsを入れやうとしてゐる。

Mnemonics

mnemonics | Hex

Read only data store for Elixir: fast, concurrently, for large data & hot reloadable.

Mnesia に匹敵しさうな名前を考へたらMnemonicsに成った。皮肉は效いてゐないが……。

數十 MB 位いの readonly data を on memory に置いて讀み出す爲のものだ。RubyActiveHashが Elixir にも欲しくて作った。Read only な ETS table を管理する library として在る。同じ table 名の data を複數 version 管理できる。realtime に data を差し替へる爲だ。

version と data の cache 機能を附け終へた所だ。Mnemonicsを使った code が testable にならないのが一番の課題で、次は其れに取り組まうとしてゐる。ExMachinaの擴張を書く事に成ると思ふ。

PQueue2

pqueue2 | Hex

Priority queue that wraps pqueue2.

優先度附き queue。

優先度附き queue すら無かったのか何故作ったと思ふかもしれぬ。私もさう思った。然して調べてみると「優先度附き queue」と名乗る Elixir の library は幾つも在った。私は全て調べた。結果、優先度附き queue として動作する實裝は無かった。同じ優先度からは random に出てくるものも在ったし(此れはPSQで、但し map としても機能する好いものだ)、一番 unique な實裝は LIFO として動いた、即ち優先度附き「stack」であった。辛うじて動いた一つはとっくに開發が放棄されてゐた。

Elixir ではなく Erlang にはちゃんとした實裝が在った。pqueueだ。此れを Elixir から便利に呼び、Enumerable と Collectable を實裝したものがPQueue2である。今作ってゐる application の背骨に使ってゐる。

stream_gzip

stream_gzip | Hex

Gzip or gunzip a stream.

Elixir の Stream は遲くて嫌はれてゐるかもしれないが、pararell に處理する程ではない場面で少ない memory で大きな data を手軽に扱へる好いものだ。stream_gzipは data 全体を memory に載せずに gzip / gunzip できる Stream だ。

"x.js"
|> File.stream!
|> StreamGzip.gzip
|> Stream.into(File.stream! "x.js.gz")
|> Stream.run

gzip でき、

"x.js.gz"
|> File.stream!
|> StreamGzip.gunzip
|> Stream.into(File.stream! "x.js")
|> Stream.run

で gunzip できる。Web application で data を生成しつつ gzip で streaming下載downloadさせる所で使った。

stream_hash

stream_hash | Hex

Stream into md4, md5, ripemd160, sha, sha224, sha256, sha384, sha512 hash.

上記stream_gzipを test する爲に作ったが、どこかで使へる事も在るだらう。

witha

witha | Hex

With aspect: Monad chain, like Haskell's do or Clojure's cats.core/alet.

{:ok, value} | {:error, reason}を返す函數を連鎖したくて作った。Elixir 標準の with 式で似た事はできるが、より各構造に特化した連鎖を書ける。

witha Witha.Error,
      [x1 <- {:ok, 1},
       x2 <- {:ok, x1 + 1}],
  do: x1 + x2
# {:ok, 3}

nil | valueも連鎖できる。

witha Witha.Nilable,
      [x1 <- nil,
       x2 <- x1 + 1],
  do: x1 + x2
# nil

AST level (macro)で new (return) & flat_map (bind)する作りに成ってゐる。此れ丈だと with 式の亜種なので、もっと高度な抽象化を取り込みたい。

tokyo.ex #8

speakerdeck.com

ヾ(〃l _ l)ノ゙

Work lein-droid with Leiningen 2.8 ヾ(〃l _ l)ノ゙

Clojureをやる。Overtone (SuperCollider)とQuil (Processing)が目當てだったが、JVM は此いつで濟ませて了へさうだ。AndroidClojure で書ける。

書けてゐた。

或る日突然書けなく成った。Leiningenを更新したからだ。lein 2.8 に成った。

% lein -v
Leiningen 2.8.1 on Java 1.8.0_152 Java HotSpot(TM) 64-Bit Server VM

AndroidVM は OpenJDK ではない。JVM っぽい JVM に似たものだから、Clojure の普通の compiler で出力したものは動かない。android-sdk で compile する必要が在る。此れを遣って呉れるのがlein-droidと云ふ Leiningen plugin だ。lein droid doallとひとたび叩けば android-sdk で compile し apk を作り實機に入れ起動し、debug console もこなす優れものだが、此れが error を吐く樣に成った。

調べると此れは Leiningen が内で使ふ library を新しいものに差し替へたからで、lein-droid が其の内で使ってゐた library を直截に使ってゐた。其所で、新しく差し替はった library を呼ぶ樣にしたり、依存を明示する樣にして直してみた。

github.com

所が反應が無い。元々 2016-10-23 から音沙汰が無い。つらい。何故誰も ClojureAndroid アプリを作らないのか。文明。世界。宇宙。

Clojure 自體は活潑に開發され、Android framework は根本的には變はってゐないので、Android アプリは作れるんですよ。好いですよ、Clojure。最高の Lisp。Elixir が目指したもの。

わっちが直したものを下記の手順で安裝installすれば、lein-droid が蘇る。

github.com

git clone git@github.com:ne-sachirou/lein-droid.git
cd lein-droid
git checkout -b fix/for_latest_leiningen origin/fix/for_latest_leiningen
lein install

cd PROJECT_PATH
lein droid doall

(〃l _ l)☆

A patch to run whatyouhide/stream_data in Elixir 1.4.* ヾ(〃l _ l)ノ゙

github.com

whatyouhide/stream_data は素晴らしい library だが Elixir 1.5 以上でなければ動かない。他の事の序でついでに 1.4 に對應させてみた。

diff --git a/lib/ex_unit_properties.ex b/lib/ex_unit_properties.ex
index f9822b1..f95bcad 100644
--- a/lib/ex_unit_properties.ex
+++ b/lib/ex_unit_properties.ex
@@ -373,7 +373,7 @@ defmodule ExUnitProperties do
         # TODO: Use :rand.export_seed in Elixir master.
         # The value may be :undefined in a new process
         # though, which means we may need to generate one.
-        initial_seed: {0, 0, ExUnit.configuration()[:seed]},
+        initial_seed: {0, 0, ExUnit.configuration()[:seed] || 1},
         initial_size:
           options[:initial_size] || Application.fetch_env!(:stream_data, :initial_size),
         max_runs: options[:max_runs] || Application.fetch_env!(:stream_data, :max_runs),
diff --git a/lib/stream_data.ex b/lib/stream_data.ex
index 6584798..ef4e673 100644
--- a/lib/stream_data.ex
+++ b/lib/stream_data.ex
@@ -513,7 +513,7 @@ defmodule StreamData do
     children =
       int
       |> Stream.unfold(next_division)
-      |> Stream.drop_while(&((int - &1) not in range))
+      |> Stream.drop_while(&(not (int - &1) in range))
       |> Stream.map(&integer_lazy_tree(int - &1, range))

     lazy_tree(int, children)
diff --git a/mix.exs b/mix.exs
index a658b0c..1d19f65 100644
--- a/mix.exs
+++ b/mix.exs
@@ -8,7 +8,7 @@ defmodule StreamData.Mixfile do
     [
       app: :stream_data,
       version: @version,
-      elixir: "~> 1.5",
+      elixir: "~> 1.4",
       start_permanent: Mix.env() == :prod,
       deps: deps(),

diff --git a/test/ex_unit_properties_test.exs b/test/ex_unit_properties_test.exs
index 8bc162d..3fd66a6 100644
--- a/test/ex_unit_properties_test.exs
+++ b/test/ex_unit_properties_test.exs
@@ -83,7 +83,7 @@ defmodule ExUnitPropertiesTest do
     property "shrinking" do
       assert_raise ExUnit.AssertionError, fn ->
         check all list <- list_of(integer()) do
-          assert 5 not in list
+          refute 5 in list
         end
       end
     end

が、私が作ってる library の 1.4 對應は切らうと思ふ。

Drop Elixir 1.4.* support · ne-sachirou/inner_cotton@63ce4f5

ヾ(〃l _ l)ノ゙

Elixirの優先度附きキューライブラリPQueue2を作った

pqueue2 | Hexを作った。

github.com

Erlang で書かれたpqueueに含まれてる pqueue2 モジュールを、Elixir でラップしたもの。

q = PQueue2.new |> PQueue2.put(:a, 2) |> PQueue2.put(:b, 1) |> PQueue2.put(:c, 1)
{:b, q} = PQueue2.pop

Collectable と Enumerable も實裝したので次の書き方も出來る。

[:b, :c, :a, :d] == [{:a, 2}, {:b, 1}, {:c, 1}, {:d, 2}] |> Enum.into(PQueue2.new) |> Enum.to_list

Hex を檢索すると、優先度附きキューを實裝したと述べるライブラリは沢山在る。全てを試してみたが、正しく「優先度附きキュー」として動作するライブラリは、pqueue と、pqueue をラップしたものしか無い。あとは「優先度附き」ではあるが「キュー」として動作しない。pqueue を Elixir でラップしたものは數年更新が停まってゐる。pqueue は最近でも更新されてゐる。そこで pqueue を使ふ事にした。pqueue は Erlang で書かれてゐて、Elixir らしい使ひ方をするには不便だ。だから Elixr でラップした。

PropCheckで property based test を書いたりした。

遲延評價Streamでgzip/gunzipするElixirのライブラリを作った

Stream で hash を計算する

stream_hash | Hex

何故無かった。

github.com

"test/fixture/xyzxyz.txt"
|> File.stream!
|> StreamHash.hash(:sha512)
|> Enum.to_list
|> hd

# <<215, 133, 241, 243, 115, 159, 59, 127, 111, 242, 140, 106, 171, 211, 130, 48,
#   174, 198, 241, 236, 195, 112, 105, 150, 106, 133, 78, 249, 2, 178, 132, 254,
#   50, 181, 85, 46, 183, 97, 187, 7, 38, 17, 26, 188, 232, 143, 152, 210, 71, 54,
#   245, 48, 107, 70, 180, 43, 96, 26, 69, 90, 17, 156, 111, 65>>

Stream で gzip/gunzip する

stream_gzip | Hex

何故無かった。

github.com

Gunzip:

"x.gz"
|> File.stream!
|> StreamGzip.gunzip
|> Enum.join

Gzip:

"x"
|> File.stream!
|> StreamGzip.gzip
|> Stream.into(File.stream! "x.gz")
|> Stream.run