新しく言語を習得するときにロゼッタコード(rosettacode)を参考にする

タイトルの通りだが、新しく言語を習得するときは、チュートリアルもそうなんだが、結構rosettacodeで逆引きして、へぇーこーゆー風に書くんだーみたいなのをみてみたりする

ロゼッタコード

タスクを選ぶ

もちろん英語サイトなので、アレルギーがある人には見た瞬間「うっ」ってなるかもですけど、中身は簡単
下記のページで参考にしてみたいタスクをクリックし、言語ごとに実装例がかいてあるので、それを参考にする
http://www.rosettacode.org/wiki/Category:Programming_Tasks

fizzbuzz

例えばみんなだいすきfizzbuzzとかもある
http://www.rosettacode.org/wiki/FizzBuzz

Nimで書くとこんな感じ

for i in 1..100:
  if i mod 15 == 0:
    echo("FizzBuzz")
  elif i mod 3 == 0:
    echo("Fizz")
  elif i mod 5 == 0:
    echo("Buzz")
  else:
    echo(i)

Swiftで書くとこんな感じ

for i in 1...100 {
    switch (i % 3, i % 5) {
    case (0, 0):
        print("FizzBuzz")
    case (0, _):
        print("Fizz")
    case (_, 0):
        print("Buzz")
    default:
        print(i)
    }
}

Luaで書くとこんな感じ

word = {"Fizz", "Buzz", "FizzBuzz"}

for i = 1, 100 do
        print(word[(i % 3 == 0 and 1 or 0) + (i % 5 == 0 and 2 or 0)] or i)
end

Adaで書くとこんな感じ

with Ada.Text_IO; use Ada.Text_IO;

procedure Fizzbuzz is
begin
   for I in 1..100 loop
      if I mod 15 = 0 then
         Put_Line("FizzBuzz");
      elsif I mod 5 = 0 then
         Put_Line("Buzz");
      elsif I mod 3 = 0 then
         Put_Line("Fizz");
      else
         Put_Line(Integer'Image(I));
      end if;
   end loop;
end Fizzbuzz;

まぁこのように結構な言語数がある。実際にこのコードがベスト・プラクティスなわけではないが、参考にはなる。

sha-256

nimでsha-256でハッシュしたいときに、さっと見られるので、便利

import strutils

const SHA256Len = 32

proc SHA256(d: cstring, n: culong, md: cstring = nil): cstring {.cdecl, dynlib: "libssl.so", importc.}

proc SHA256(s: string): string =
  result = ""
  let s = SHA256(s.cstring, s.len.culong)
  for i in 0 .. < SHA256Len:
    result.add s[i].BiggestInt.toHex(2).toLower

echo SHA256("Rosetta code")

まか書き方が冗長だったりすることもあるかもだが、それは自分で直せばいいし、あくまで参考程度にみるには結構重宝するサイトだと思う

nim tutorial part2 (1) memo [objects]

つづき

nim チュートリアル part2 のメモ

objects

nimは最小限のOOP(オブジェクト指向)をサポートしている。

type
    Person = ref object of RootObj # 
        name*: string # *がつくと public
        age: int # * ないと private? 
    Student = ref object of Person
        id: int # with and id field

var
    student: Student
    person: Person
    sample: int

student = Student(name: "Anton" , age: 5,id: 2)
person = Person(name: "sample" , age: 10)

echo student[]
# echo student    -> これはエラーになる
echo person[]

classはないが、object型をrefすることで同じようなことはできる。
*のありなしで、public/privateをわけている。継承もできるが、多重継承はサポートしていない。ここらへんはPythonと異なる。
typeっていうのがあるので、お気づきかもだが、いくつか型を指定できる。enumとかobject とか ref objectとか…
それは次回。

ライブチャットサービスのlivezillaを入れてみた

ライブチャットサービスでいいのないかなーって探してたらオンプレでできそうないいものがあったので、メモ

サイトに来てもらって、そこからのコンバージョンを上げたいとかあるんだけど、ユーザが何思ってるかとか組み上げるものがあんまりなかったので、導入したいなーと思ってSaaSのものをみてたんだけど、月額安いんだけど、オペレータ増やすと途端に値段あがってくし、ログあんまり残らないし、性能でるかわからんしってことで、オンプレでできるのを探しており、Livezillaっていうのを見つけた。

LiveZilla概要

  • 構成はPHP + JS + MySQLという感じで超シンプル。
  • ソースコードはやや見づらいがメンテできないほどではない
  • オペレータは1名だけなら永久無料(30日間は無制限利用)
  • オペレータのクライアントアプリがある
    • デスクトップ(win,linux,mac)
    • モバイル(iOS, Android)
  • 翻訳機能(エディタ)がある

  • ボット用のAPIがある
  • オペレータ画面でユーザが表示してる画面がみえる(入力までは見えない)
  • チケット管理ができる
  • ブラックリスト管理
  • 優先順位管理
  • slack連携できる
    などなど、もう機能としては十分である。

画面はこんな感じ

ライセンス

あと、ライセンスが買い切りで無制限プランが999ユーロらしく、結構やすい。
zopimとかのだと3オペレータ10ヶ月分で10万弱なので、ならボット無制限でつくれるので、いいかなと。

ビジネスとしては

アップデートライセンスは別にある。これは予測だけど、クライアントアプリ(デスクトップ、スマホとも)は多分、最新のLiveZillaのAPIにしか対応してないとかなんとかで、そのアップデートライセンスを買わせるモデルなんじゃないかなと。ただ、アップデートライセンスもそれほど高くなく、499ユーロくらいなので、別に全然いい。

さて、これでコンバージョンあがるといいなー。

nim lang チュートリアル(4) (distinct,modules)

つづき

distinct

これは他の言語でもあるのかな。理解するまで時間がかかったものだが、どうやらある型をベースに
異なる型を生成するもよう。

下記の例だとエラーになる

type  Dollar = distinct int

var  d: Dollar

echo d + 1   // Error: type mismatch: got (Dollar, int literal(12))

int型をベースにDollar型を生成している。
だが、演算子までは使えない

modules

nimはmodule機構がある

import

おなじみimport

import strutils

モジュール内の関数を読み込まないこともできる

import strutils expect isDigit

var a: string = "1"
echo isDigit(a)  // Error: undeclared identifier: 'isDigit'

コンパイルエラーになる

from statement

moduleの中からなにを使えるようにするか選択できる

from mymodule import x ,y ,z 
x()  # OK
from mymodule import nil
x()  # error
mymodule.x()  # OK

aliasも指定できる

from mymodule as m import nil
m.x()  # OK

include statement

モジュールのファイル分割時に使用するみたい

include fileA  , fileB , fileC

node dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.60.dylib のエラーでたら…メモ

npmコマンド打ったらエラーがでてきたので、メモ

$ npm 
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.60.dylib
  Referenced from: /usr/local/bin/node
  Reason: image not found
Abort trap: 6

nodeでも同じようなエラーがでていた

$ node
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.60.dylib
  Referenced from: /usr/local/bin/node
  Reason: image not found
Abort trap: 6

あわてず、再インストール

$ brew reinstall npm

Nginxでお手軽なHLSストリーミング

スマホで動画再生コンテンツをお手軽にリリースしたいなーって時に、mp4とかwebmとかだと正直再生までに時間かかるので、ストリーミングをちょっと触る。
Nginxは標準でストリーミング対応できてるっぽいので、これを使う。

お試しの環境はMacで。

下準備(動画変換ライブラリ)

動画変換にはffmpegを使う。
まずは、mp4とかwebmとかmovをHLSで再生できるm3u8に変換したいので、ffmpegを再ビルド・インストールする

$ brew reinstall ffmpeg  --with-fdk-aac --with-libvo-aacenc  --with-libvorbis --with-libvpx --with-openjpeg  --with-theora --with-opencore-amr

動画変換する

動画を下記コマンドで変換かける

$ ffmpeg -i video.mp4 -vcodec libx264  -b:v 768k -s 640x360 -acodec libfdk_aac  -b:a 96k -ar 44100 -flags +loop-global_header  -map 0 -vbsf h264_mp4toannexb -f segment  -segment_format mpegts -segment_time 10  -segment_list video.m3u8 video%03d.ts

video.mp4をm3u8形式に変換する。

マークアップに記述する

ブラウザでhlsを再生するのに、video.jsを使用する
hlsのcontribモジュールも使用する。

index.htmlはこんな感じ
iOSで自動再生するには、<video>タグ内に playsinlinemutedをいれれば自動再生できます

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <link href="//vjs.zencdn.net/6.7/video-js.min.css" rel="stylesheet">
  <title>HTTP Live Streaming Test</title>
  <style>
    .wrapper {
      height: 100%;
      width: 100%;
      position: relative;
    }

    video {
      widows: 480px;
    }
  </style>
</head>

<body>
  <script src="//vjs.zencdn.net/6.7/video.min.js"></script>
  <script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script>
  <script src="./videojs-contrib-media-sources.js"></script>
  <div class="container">
    <header>
      <h1>HTTP Live Streaming Test</h1>
    </header>
    <video class="video-js vjs-default-skin" id="video" width="360" autoplay controls muted playsinline preload="metadata">
      <source src="video/video.m3u8" type="application/x-mpegURL">
    </video>
    <script>
      var player = videojs('video');
      player.play();
    </script>
</body>
</html>

ディレクトリ構成はこんな感じです

/usr/local/var/www/
├── index.html
├── video
│   ├── video.m3u8
│   ├── video000.ts
│   ├── video001.ts
│   ├── .....(many ts file.)
│   ├── video027.ts
│   └── video028.ts
├── videojs-contrib-hls.min.js
└── videojs-contrib-media-sources.js

Nginxを起動して、下記URLにアクセスすると再生されます(ブラウザのdevtoolsのnetworkをみると、ストリーミングで配信されてるのがわかります)

http://localhost/index.html

ほとんど何もせずにできました。多分30分もかからないくらい。先人の方たちに感謝します。
本番でやるにはもう少しちゃんとやらないとですけど、お試しとか少しデータとりたいときにはいいかもですね。

nim lang チュートリアル3 (parameters, discard, name arguments)

つづき

parameters

var変数をproceduresに渡すと参照渡しになるっぽい

proc divmod(a, b: int; res, remainder: var int) =
  res = a div b        # integer division
  remainder = a mod b  # integer modulo operation

var
  x, y: int
divmod(8, 5, x, y) # modifies x and y
echo x  # 1
echo y  # 3

discard

voidっていうのはないので、戻り値を無視する場合は、discardをつけて呼び出す


proc yes(question: string) bool = return true # yes("question") # Error: expression 'yes("question")' is of type 'bool' and has to be discarded discard yes("question")

discardable をつけても戻り値を無視できる

proc p(x, y: int): int {.discardable.} =
  return x + y

p(3, 4)

ただ無視するだけなので、echo とかつけたら表示はできる

proc p(x, y: int): int {.discardable.} =
  return x + y

echo p(3, 4)  # 7

nim チュートリアル (result variable, proc)

つづき

procedures

Javaのメソッド, PHPのfunction、Rubyのdefみたいなものかな

戻り値はreturn を書いたらそれをつかうけど、returnなかったらresultという変数の中身が返却される

proc calc(x: varargs[int]): int = 
    for i in x:
        if i < 0:
            return
    result = result + i

echo calc()          # 0
echo calc(1,2,3)   # 6
echo calc(4,4,5)  # 13
proc calc(x: varargs[int]): int = 
    for i in x:
        if i < 0:
            return
   return 100

echo calc()          # 100
echo calc(1,2,3)   # 100
echo calc(4,4,5)  # 100
proc calc(x: varargs[int]): int = 
    result = 4
    for i in x:
        if i < 0:
            return


echo calc()          # 4
echo calc(1,2,3)   # 4
echo calc(4,4,5)  # 4

resultっていうのが、返却されるってのは暗黙だなーと。

nim lang チュートリアル ( while , for , scope , block , break,whenstatement)

nim lang チュートリアルの つづき

while statement

while文は普通にある
書き方も目新しくはない

echo "What's your name?"
var name = readLine(stdin)

while name == "":
    echo "Please tell me your name: "
    name = readLine(stdin)

for statement

for文もある

## countup
for i in countup(1,10):
    echo i

## countdown
for i in countdown(10,1):
    echo i

## incでincrement
var i = 1
while i <= 10:
    echo i
    inc(i)

## レンジ指定 昇順
for i in 1..10:
    echo i  # 1 2 3 4 5 6 7 8 9 10

## レンジ指定 降順
for i in 0..<10:
    echo i  # 1 2 3 4 5 6 7 8 9

var str = "some string"
for i in 0..<str.len:
    echo i 

Scope and block statement

block内で宣言したものは、blockの外では使えない
JavaとかJSとかと同じ

block myblock:
    var x
echo x   # Error: undeclared identifier: 'x'

blockステートメントがある。機能としては何もしないが、名前付きのblockスコープが作れる。
whileとかの中で、breakにblockスコープを指定するとそのblockの外に出られる

block myblock1:
    echo "in myblock1"
    while true:
        echo "in while"
        break
    echo "still in myblock1"   ## printing

block myblock2:
    echo "in myblock2"
    while true:
        echo "in while"
        break myblock2
    echo "still in myblock2"    ## not printing

break statement

他の言語のbreakと同じ

continue statement

他の言語のcontinueと同じ

when statement

ifとほとんど同じ機能だが、変数での評価ができない(定数のみ評価)

例えば、下記だとクロスコンパイル時に他のOSの記述はコンパイル後のコードには入らない。
OSごとの最適化なんだろう。きっと。

when system.hostOS == "windows":
  echo "running on Windows!"
elif system.hostOS == "linux":
  echo "running on Linux!"
elif system.hostOS == "macosx":
  echo "running on Mac OS X!"
elif x == "macosx":            # Error: cannot evaluate at compile time: x
  echo "running on Mac OS X!"
else:
  echo "unknown operating system"

nim lang チュートリアル(readLine,if,case,let,const)

こちらの写経 -> https://nim-lang.org/docs/tut1.html

echo "What's your $name ?"
var name = readline(stdin)
echo "Hi, " , name , " !"

標準入力

readline(stdin) で標準入力を受け付けるもよう
JavaのSystem.inみたいなものかな

コンパイルは下記コマンドで

$ nim c Hello.nim
$ ./Hello

変数宣言はTypescriptっぽい感じ

var 変数名: 型

// 代入の場合
var 変数名: 型  =  値

// まとめて指定もできる
var x , y : int

// 改行で指定もできる
var
  x , y: int
    a,b,c: string

// まとめて代入もできる
var
  x , y: int = 1
    a,b,c: string = "abcdefg"

const と let

constが使える。Javaでいうstatic final な感じかな

const x = "abc"
x = "def"  // <- エラーになる

letも使える。Javaでいfinalな感じかな。

let x = "abc"
x = "def"

上の2つの例をみるとconstとletの違いが無いように思えるが、constはコンパイル時に値が決定している。
letは使用時に1度だけ値を入れることが可能になる

let x = readLine(stdin)     // OK

const x = readLine(stdin)  // NG

このような感じである

if statement

if文では、Pythonと同じようにインデントで制御されるので、インデントがないとちゃんと動かない

let name = readLine(stdin)
if name == "":
  echo "empty value"
elif name == "name":
  echo "name is name"
else:
  echo "Hi , ", name , "!"

こんな感じ

下記はPythonだが、まったく同じ

if a == 1:
    print(1)
elif a == 2:
    print(2)
else:
    print("else")

case statement

case文はレンジ指定とかで使うっぽい

from strutils import parseInt

let n = parseInt(readLine(stdin))
case n
of 0..2, 4..7: echo "The number is in the set: ", n
of 3, 8: echo "The number is 3 or 8 ", n
else: discard

三点リーダの両端を含めた間の値が選択される

一旦ここまで