しばらく触っていなかったのですが、ふと思い立って、データ構造を追加してみました。
具体的には、
の二つを追加しました。実装はほとんど、Scala版のRedBlackTreeのポーティングですが、is
乱発しなければいけなくて、結構めんどかったです。
GitHub - kmizu/kollection: Immutable Collection Libraries and Additional Utilities for Kotlin
しばらく触っていなかったのですが、ふと思い立って、データ構造を追加してみました。
具体的には、
の二つを追加しました。実装はほとんど、Scala版のRedBlackTreeのポーティングですが、is
乱発しなければいけなくて、結構めんどかったです。
GitHub - kmizu/kollection: Immutable Collection Libraries and Additional Utilities for Kotlin
タイトルの通りなんですが、JetBrainsさんが公式で
とか書いているおかげで信じている人もいるかもしれません。ですが、それは正しくありません。
試しに、次のコードをコンパイルしてみましょう。
fun double(x: Int?): Int = x?.let{ it * it } ?: 0
クラスファイル BoxingKt.class
が生成されるので、javapしてみましょう。
Compiled from "Boxing.kt" public final class BoxingKt { public static final int foo(java.lang.Integer); Code: 0: aload_0 1: dup 2: ifnull 21 5: astore_1 6: nop 7: aload_1 8: checkcast #9 // class java/lang/Number 11: invokevirtual #13 // Method java/lang/Number.intValue:()I 14: istore_2 15: iload_2 16: iload_2 17: imul 18: goto 23 21: pop 22: iconst_0 23: ireturn }
まず、引数の型がjava.lang.Integer
になっています。これは、引数を渡す時にBoxingのコストが発生することを意味します。また、その値を使って計算する場合、Unboxingのコストが発生します。
この問題は、プリミティブな型をnullableにしたときに発生します。ジェネリクスでプリミティブ型相当を引数にしたときにBoxingが発生するのと理屈は同じです。
必ずしもこの点が問題にはならないとは思いますが、一般にKotlinのnullable typeがzero overheadというのは嘘だと言って良いでしょう。
冷やし中華はじめました、みたいなこと書いてみたかっただけです。はい。
これまでKlassicでは、メインのインタプリタは(あとで静的型をつけることを意識しつつ)動的型言語でしたが、少しずつ静的型を加えていっています。現在のところ、まだ多相型を扱えないという制限はあるものの、
val x = 1 // xはInt x = 2 // 再代入不可 mutable y = 1 // xはInt y = 2 // 再代入可能 val list = new ArrayList list.add(1) list.add(2) list.add(2) println(list) // リストリテラル。[1, 2, 3] println([1 2 3]) // [1 2 3] println([ 1 2 3 ]) // [1 2 3] val map = #["key": "value"]// マップリテラル。 println(map)
などのコードが動きます。多相型が必要なところは現在Dynamic
という型を導入することでごまかしています。階乗を計算するコードは、
def fact(n) = if(n < 2) 1 else (n * fact(n - 1)) println(fact(4))
のように書けますが、今のところ引数の型宣言を省略するとDynamic
になるというなんとも微妙な仕様になっています。
また、substring
関数の型は(Int, Int) => Dynamic
のようになっています。この辺はJavaとのinteroperabilityを考えつつ慎重に設計したいところです。ただ、Klassicの開発目的の一つとして、サブタイピングの適切な制限というのがあって、その辺は、Javaとのinteroperabilityを考えると使い勝手が下がるので難しいところです(もちろん多数の先行研究があるのは承知の上ですが、とりあえずしばらくはテキトーに実装してみて、つまづいたら先行研究を参照しようかと思います)。
きっかけは、昨夜の思いつきでした。
今日ふと思ったこと: JSONって、そもそもカンマ要らないんじゃね?
— Kota Mizushima (@kmizu) 2016年11月6日
{ "Foo" : "BAR" "BAR": "Baz"
"Hoge" : { "name" : "Hoge" } }
特に曖昧性なくパーズできるように思える。配列も同じく。
JSONでも以前から、末尾のカンマを許すようにしてほしいとかそういう要望があったと記憶していましたが、そもそもカンマを要らなくすれば解決では?というのが動機です。
NSONは次のような特徴を持っています。
まず最初の点についてですが、たとえば、
{ "x": 1 "y": 2}
のような記述ができるということです。また、改行で要素を区切って
{ "x" : 1 "y" : 2 }
のように書くこともできます。
その次の点ですが、これは最初の点と同じようなものです。
{ "like": ["Scala" "Nemerle" "Scheme"] }
このように、配列の要素をカンマで区切る必要がありません。
3番目の点ですが、これは、JavaScriptでは許されていたものの、JSONでは許されなくなった点の一つであり、たとえば、
{ x: 1 y: 2}
のような記述が許されます。
最後の点ですが、これはそのままです。JSONで正しいデータはNSONでも正しいデータです。たとえば、
{ "x": 1, "y": 1}
は正しいJSONのデータであり、かつ、正しいNSONのデータです。
詳しくは、以下のURLを参照してください。
GitHub - kmizu/nson: NSON: an object notation that is not a JSON but alike JSON.
NSONは構文上の実験であり、今後メンテナンスしていくかは正直微妙です。これを拡張していくことで何か書きやすいデータフォーマットが生まれる可能性もあるので、思いついたら何か手を加えていくかもしれません。
ちなみに、思いついてからNSONのパーザを書いて、ある程度動作するようになるまで3時間くらいでした(自作のKlassic言語のパーザがある程度流用できたので、ちょっとズルいかもしれません)。こと構文解析においてはさすがだな自分と自画自賛しておきます。
最近、Klassicと同時にOnionもちょくちょく更新するようになったので、変更点など書いていこうと思う。
今日は、メソッドや関数定義に、文ではなく式を取れるようにする改良を行った。今どきの言語だと当たり前だが、Onionを最初に開発した2004-2005年の時点ではそれほど当たり前ではなかったのだ…と思う。
というわけで、
class Adder { public: def add(x: Int, y: Int): Int = x + y; }
のような定義が可能になった。セミコロンが必須なところがださいので、この辺もじきに不要になるようにしたい(多少面倒だが)。
TwitterでScala関係のつぶやきをみていると、どうも、特に初学者の方に、
varを使ってはいけないので、Scalaは難しい…
という意見が散見されるようです。
しかし、Scalaを学び始めのときにいきなりvarを断つ必要はなく安心してvarを使ってもいいと思います (そもそもvarが全く不要なら言語仕様にあるわけないですし)。慣れれば、varを明らかに使わなくて 良い箇所はわかってくるので、そこからval/varを使うのを意識しても遅くないと思います。
もちろん、いつもでも全部var使ってるとどうかという議論はあるのですが、それはScalaに慣れてから 考えればよい話です。Scalaを学ぶのにvarを使わないという縛りがきついのなら、無理しなくていいよ というのが言いたいことです。
最近、Elixirがなんとなく盛り上がってきている気がするので、この機会に入門してみることにした。お題は相変わらずparser combinator。解説はめんどうくさいのでコードだけ貼り付けておく。
わかったこと。
f.(x)
という文法はちょっと気持ち悪い。def
で定義したものをオブジェクト化するときに、 &f/1
のように引数の数を明示しなければいけないのは、Erlang譲りっぽいけど、ちょっと面倒くさいString.slice
の第二引数で与える範囲がJavaとかのsubstring
と違ってちょっと迷ったmix
で簡単にプロジェクトの雛形とテストの雛形を生成できて便利f
のように書くだけで呼び出せるのはRubyっぽい文法は癖があるが、おおむねまっとうな言語だなあというのは初見の印象。