こんにちは、hachi8833です。
- リポジトリ: goby-lang/goby
- 公式サイト: https://goby-lang.org/
本記事ではGoby 0.1.9を用いています。1.0になるまでは仕様変更の可能性もありますのでご了承ください。
インストール方法や動かし方については第1回目をご覧ください。
注: GobyとRubyのどちらでも動くコードの冒頭には# Goby/Ruby
と、Gobyでのみ動くコードには# Goby
と表記することにします。
⚓Gobyの文法上の特徴(4)文字列とシンボルは同一
GobyにもRubyと同様に:symbol
のようなシンボルリテラル表記があります。しかしGobyのシンボルリテラルは、単なる文字列リテラルのショートハンドでしかありません。従って、:symbol
は常にString
クラスのオブジェクトである"symbol"
に変換されます。
# Goby
:apple.class
#» String
fruits = [:apple, :orange, :grape, :banana]
#» ["apple", "orange", "grape", "banana"]
fruits[0].class
#» String
ご存知のとおり、RubyにはSymbol
クラスがあります。GobyにはSymbol
クラスはありません。
# Ruby
[1] pry(main)> :symbol.class
=> Symbol
[2] pry(main)>
RubyではString
かSymbol
かを判定する一手間が生じがちで、RailsだとActiveSupport::HashWithIndifferentAccess
で戦うことがよくありますが、Gobyはその点の解消を図っています。
なお、Rubyにあるスペース含みの文字列をシンボルに変換する機能は、Gobyにはありません。スペース含みの文字列は普通に" "
や' '
で書きましょう。
# Goby
:"grape fruit" # この書き方はできない
#» unexpected : Line: 0
# Ruby
[2] pry(main)> :"grape fruit"
=> :"grape fruit"
⚓参考: 文字列のfreeze
について
現時点のGobyでは文字列のfreeze
はまだ導入されていませんが、いずれ導入したいという意向です。また、破壊的メソッドは極力減らすか、場合によっては完全になくすかもしれません。
Gobyで文字列リテラルのobject_id
を取ってみるとわかりますが、今は毎回オブジェクトIDが異なっています。
# Goby
"hello".object_id
#» 842353280544
"hello".object_id
#» 842350512064
"hello".object_id
#» 842353281344
もちろん、リテラルを変数に代入すればオブジェクトIDは定まります。
# Goby
str = "hello"
#» hello
str.object_id
#» 842353282208
str.object_id
#» 842353282208
なにしろ今のGobyはInteger
型であっても数値リテラルのオブジェクトIDが一定ではないので(´・ω・`)。
最適化は今後の課題と割り切っています。
# Goby
1.object_id
#» 842350513056
1.object_id
#» 842353284864
1.object_id
#» 842350514080
⚓Gobyの文法上の特徴(5)ハッシュリテラルのキーはシンボルリテラルのみ
Gobyのハッシュリテラル{ key: "value" }
はRubyと同じ要領で扱えますが、1つ重要な違いがあります。ハッシュのキーに使えるのは事実上シンボルリテラルだけです。もう少し正確に言うと「シンボルリテラルに変換可能な文字列」ですね。
次のように変数a
をこしらえてハッシュリテラルのキーに置くと、その場は通ってしまいますが、参照時に怒られます。Rubyのようにキーに一般的なオブジェクトを使うことはできません。
# Goby
» a = [1, 2, 3]
glocery = { apple: 1, orange: 2, a: 3 }
glocery[a]
#» TypeError: Expect argument to be String. got: Array
それだけではありません。次のように文字列リテラルをハッシュリテラルのキーとして使うことも許されません。キーは常にシンボルリテラルでなければなりません。
# Goby
glocery = { apple: 1, orange: 2, "grape": 3 }
#=> unexpected : Line: 0
当然、ロケット演算子=>
もGobyにはありません😎。
この仕様を見返してみて、オブジェクトをハッシュリテラルのキーに指定する時点で怒るのがよさそうにも思えましたが、それをやると変数名とシンボルリテラルがたまたま同じになったときにまで怒られてしまい、間違いなくうざくなるので、この方法がよいのだと思います。
⚓Gobyの文法上の特徴(6)文字列のエンコードはUTF-8一択
RubyではCSI方式に基づき、さまざまなエンコーディングを文字列オブジェクトに指定できます。マルチエンコーディングの扱いについてはRubyは最強の部類でしょう。
GobyのString
クラスはそのあたりをすっぱり割り切って、UTF-8一択にしています。当初はGo言語の素朴なstring
が文字列型に使われていたのですが、漢字などのマルチリンガル文字を正しくカウントできるようrune
も導入し、4バイトのUTF-8に対応すべくテストにも寿司ビールチェックを追加してあります。rune
はまだ徹底できてない気もするので、今後の課題かもしれません。
# https://github.com/goby-lang/goby/blob/54255ddc4b30b8daf6e5aad48e2aae2db8120aab/vm/string.go#L500
Name: "capitalize",
Fn: func(receiver Object, sourceLine int) builtinMethodBody {
return func(t *Thread, args []Object, blockFrame *normalCallFrame) Object {
str := receiver.(*StringObject).value
start := string([]rune(str)[0])
rest := string([]rune(str)[1:])
result := strings.ToUpper(start) + strings.ToLower(rest)
return t.vm.initStringObject(result)
}
},
⚓最近のGoby
⚓GobyのAPIドキュメントを更新中
結城はもともとPerlerなのですが、perldocはその点素晴らしいです。EXAMPLESのセクションはコピペでそれっぽく動く。それを見て「なーるほど、こういう関数(モジュール)か」とざっくり理解する。ドキュメントのあれこれはその後で読む。perldocはそんな感じ。
— 結城浩 (@hyuki) July 13, 2017
例の結城浩さんのツイートを意識してということもあり、最近ちまちまとGobyのAPIドキュメントやテストを更新するのが無上の楽しみです。
ドキュメントを更新してみると、思いもよらぬバグが見つかったりするのがまた楽しい😊。いっぺんに直すと迷惑になるので、ドキュメントにまずTODOでメモして、別プルリクで修正するようにしてます。
[1, 2, 3]
みたいな味も素っ気もないサンプルコードも、そのうちもう少し血の通ったものにしたいと思います。