いろいろ備忘録

雑記です。

(implicit s: Show[A])

def log[A](a: A)(implicit s: Show[A]) = println(s.show(a))

この(implicit s: Show[A])はカリー化とimplicitを両方使った結果。

もしlog[Int](3)とすると、
引数sが渡されていない、かつimplicitなので、
Intが引数で、かつimplictなShowメソッドを探す。

implicit val intShow = new Show[Int] {
def show(i:Int) = i
}

こんなのが見つかったら、それを先程のsに当てはめる。

Scalaの型クラス(typeclass)の分かりやすい説明(Cats公式翻訳) - Qiita

javaのstatic { }とか{ }

スタティックイニシャライザ

クラスがロードされる際に呼ばれる。

static変数の初期化が関数を使って出来る!

static {

}

 

インスタンスイニシャライザ

コンストラクタと似ているが、

コンストラクタがA(), A(String name)などとオーバーロードされているとする。
その全てに共通の処理があるとき、普通はそれをメソッドにして、コンストラクタからそれを呼び出すが、
インスタンスイニシャライザならば、
先程メソッドに書いた内容をインスタンスイニシャライザに書くだけで良い。
コンストラクタから呼び出す必要が無くなるので呼び忘れも無くなる。

{

}

promamo.com

N Scala応用 型パラと変位

Javaでは全てのクラスがObject型のサブクラスだが、
ScalaではAnyが最上位のクラスで、次にIntなどの値型はAnyValクラス、参照型はAnyRefクラスのサブクラスになる。
図にすると、

http://joelabrahamsson.com/PageFiles/148/1310_1644.jpg

引用元:

Learning Scala part eight – Scala’s type hierarchy and object equality

 といった流れ。

 

型パラメータの前につくプラス+とかマイナスーは、変位指定という。
プラスは共変といい、javaでいうextends。
マイナスは反変といい、javaでいうsuper。

 

共変は引数に指定できず、反変は返り値に指定できない。

理由は下記リンク。

 

hogepiyo.hatenablog.jp

 

 

 

N Scala応用 関数 覚書

ScalaにはFunction0 ~ 22のトレイトがある。数字は引数の数で、0なら返り値のみ。
関数の作り方をきちんと追うと、まずこれらのトレイトを継承した無名クラスを作り、その中でapplyメソッドを宣言する、という流れ。この辺が関数型言語の特徴なのか?

applyメソッドは特別で、a.apply(x)がa(x)と等しい
ふつう、関数はfunc(x)のように呼び出すが、これを関数がインスタンスとなるScalaで書くとfunc.apply(x)となってしまう。
先程のようにapplyを省略することで普通の書き方になる。

 

Scalaは式ベースの言語であり、中括弧{ } (ブロックという)も実は式。
その返り値はブロック内の最後の式の評価結果なので、{ x + y }とx + yは同じ結果になる。

 

new Function2[String, Int, Int]の大括弧は型パラメータという。たぶん大体ジェネリクス

 

関数とメソッドの違いは、第一級の値であるかどうか。
つまり関数はオブジェクトになる。メソッドはならない
なので、引数としてメソッドを与えたり、メソッドが何かのプロパティを持つことは不可能。

 

高階関数とは、関数を引数にしたり、返り値にする関数のこと。

 

Scalaには末尾再帰最適化という機能がある。これは再帰によるスタックのオーバフローを防止してくれる機能。
末尾再帰による最適化 - Qiita が詳しい。

自分なりに説明してみる。
オーバフローの原因は、再帰する関数の返り値がreturn result + func(a) のようになっていること。
上記のように書くと、func(a)を評価したにresultと足し合わせる。
つまり、呼び出し元のアドレスと result変数をコールスタックに保持しておかなければならない。これでオーバフローする。

一方、return func(result, a) とすると、funcの返り値が呼び出し元の返り値そのものとなる。
この場合、返り値を計算するのに必要な変数は全てfuncに渡される。
つまり呼び出し元の情報を今後一つも必要としないので、もはや呼び出し元のアドレスも変数も必要ない。
よってコンパイラはこれをループに変換でき、オーバフローも回避できる。

 

WebStormでExpressのテンプレートのscriptタグにCannot resolve directoryと出る時

Expressでなくとも、フレームワークを使っているときあるあるだと思います。

javascript - Webstorm: "Cannot Resolve Directory" - Stack Overflow

Settings→Directories→publicを右クリックしてresource rootを左クリック

didinj/mean-angular4-chat-appについて

Building Chat Application using MEAN Stack (Angular 4) and Socket.io

上のリンクに順を追って書かれているけれど、色々抜けているのでForkしたほうがよい。

MEANスタックは、Mongo DB, Express, Angular, Node.js で構成される。

ExpressがDBアクセスとJSONAPI, Socket.ioのサーバなどのバックエンドを担当して、Angularは表示などフロントエンドをする。

ルーティングはexpressで行う。angularへのルーティングはng buildによって生成されたdist/index.htmlをrender()することになる。よって、起動コマンドはng serveではなくnode なんたらになる。好みでpackage.jsonのnpm startをnodeなんたらに変える。

Socket.ioのサーバはroutes/chat.jsで動いている。他のサンプルではbin/wwwに書いてあるものもあった。見通しが悪くなってしまうので専用のファイルを作ったほうが良いかもしれない。もしくは別プロセスで動かすのも吉かもしれない。

チャット入室時

入室後

  • http://localhost:4000のSocket.ioで発言を送受信
  • Angularがhttp://localhost:3000/chat (Express)に発言をDBにも反映するためにPOSTしている
    二度手間になるのでサーバのSocket.ioの受信イベントにまとめるべきでは?

socket.ioのメッセージがブロードキャストされていて、localStorageにあるroomと一致する時表示するという方法を取っている。セキュリティ的にもトラフィック的にもSocket.ioのroom機能を利用して不必要なところには送らないようにすべき。

JSではthisが関数の実行時のオブジェクトとなるので、.bind(this)によって宣言時のthisになるようにしている。io.onでbind()しているのはon内の関数のthisがSocket.ioとなってしまうためにangularがもつchatsにpushできないため。宣言時にはangularなのでbindしていれば問題なくpushできる。

JSON.stringify()とは、JSONJSON形式の文字列にするメソッド。逆の働きをするのがparse()。