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

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

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

音樂は SoundCloud に公開中です。

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

Programming は GitHub で開發中です。

Haskell is good for scripting language ヾ(〃l _ l)ノ゙

Clojure/Haskell の誓ひと云ふのを立ててゐる。個人的な programming を Clojure/Haskell 以外でしないと云ふ誓ひだ。大体の事は置き換へてゆける。Java を使ふところは Clojure に置き換へる。Lisp を使ひたかったし、SuperCollider (Overtone)と Processing (Quil)を同時に扱ふのが簡單であるので、Haskell-like (Eta)ではなく Clojure を使ってゐる。JavaScriptHaskell に置き換へられる。Web front-end 用 framework (Miso)すら在る。

一つ困ってゐて、shell script とその仲間を捨てられずにゐた。ClojureHaskell も shell script を置き換へるのは辛からうと思った。ClojureJVM を起動しなければならないし、又これは JVM に關はる事ではないからできれば Haskell でやりたい。しかし GHC の標準 library では全然足りないから幾つも library を入れ追從しなければならない。と思ってゐた。さういふ時には、Ruby を書いたり Perl を書いたり Crystal を書いたりしてゐた。誓ひは破られたのである。

この度に、少々無理にでも Haskell で軽く scripting できる手法を見附けておくべきだらうと思ひ決めた。GHC の標準 library は貧弱だと思ひ込んでゐたから、その貧弱な標準 library で苦心するか、Stack project を作る事無く Hackage の library を簡單に扱へる方法を組み立てやうと決め、もそもそと調べ出した。

しかし書けたのである。特に苦勞は無かった。runghc も GHC の標準 library も好い仕事をした。皆とりこし苦勞だった。

昔との違ひはDashを使ふ樣に成ってゐた事である。何をするにもその環境の標準 library を全文檢索する癖が附いてゐたから、そんな誤解もしなく成ってゐた。全文檢索は凄い。runghc も頗る速かった。この理由は知らない。

以下が shell script から移してきた短い Haskell script である。git-deployと名附け、git-deploy some_host_on_ssh_config /home/some_userの樣に使ふ。雜な内容から用途の雜さは推して知るべしである。

#!/usr/bin/env runghc

import System.Environment ( getArgs, getExecutablePath )
import System.FilePath ( takeBaseName )
import System.Posix.Directory ( getWorkingDirectory )
import System.Process ( readCreateProcess, shell )
import Text.Printf ( printf )

main :: IO ()
main = do
  args <- getArgs
  case args of
    host:remoteDir:_ -> deploy host remoteDir
    _ -> help

help :: IO ()
help = putStr $ unlines [ "Help: deploy HOST REMOTE_DIR" ]

deploy :: String -> String -> IO ()
deploy host remoteDir = do
  projectName <- fmap takeBaseName getWorkingDirectory
  sh $ printf "git archive -9 -o /tmp/%s.tar.gz --prefix %s/ HEAD" projectName projectName
  sh $ printf "scp /tmp/%s.tar.gz %s:%s/%s.tar.gz" projectName host remoteDir projectName
  sh $ unlines
    [ (printf "ssh %s -K 'bash -s' <<EOF" host)
    , (printf "cd %s" remoteDir)
    , (printf "tar xzf %s.tar.gz" projectName)
    , "EOF"
    ]

sh :: String -> IO ()
sh command = do
  putStrLn $ "+" ++ command
  out <- readCreateProcess (shell command) ""
  putStrLn out

-- vim:set ft=haskell:

今困ってゐるのは、Haskell の文件を開くと Emacs (Evil) が固まる事。kill するしか無くなってしまふ。代りに Vim を使ってゐるが…。

ヾ(〃l _ l)ノ゙

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)ノ゙