半蔵門線徒歩

最近ちゃんと書いていませんでしたが、先週の土曜日にはメトロの半蔵門線を歩きました。渋谷駅から押上駅まで。線路の距離で 16.8 km 、歩きの距離で 18.7 km 。

いい加減見飽きた渋谷駅よりスタート。後で気がついたけど、今回で渋谷駅を通る路線をコンプリートしたみたい。
表参道駅青山一丁目駅は銀座線と共通なので歩き済み。
さらに既訪の永田町駅に近づくと、なにやら警官がいっぱいいた。なんだろうと思っていたら、永田町を過ぎたあたりで右翼の街宣車がいっぱい走っていたので、たぶんそれなんだろう。
ここから皇居を北から回り込む。オフィス街っぽいところを抜けると麹町に入り、半蔵門駅。東京の千代田区にこんな普通の街が、という感じの普通の街っぽく感じた。
靖国神社の前に出て、靖国通りを歩くとすぐ九段下駅。これも歩き済み。次の神保町駅も歩き済み。
皇居の東に出て、気象庁とかがある官庁街っぽい町になって、大手町駅。丸の内線で来たばかり。東京駅の北側を通って三越前駅。ここも歩き済み。
水天宮前駅は初めて。東京シティエアターミナルなるものが隣接していて、昔はここで搭乗手続きや出国審査をしていたらしい。知らんかった。
隅田川を渡って、清澄白河駅大江戸線で歩き済み。江東区の下町ゾーンだけど、ここはまだ比較的きれいな気がする。一方住吉駅は汚かった。新宿線で歩き済み。
人がいっぱいの錦糸町駅 (総武線で歩き済み) を通り抜けて、押上駅 (京成押上線で歩き済み) で終わり。


初めて見た駅は 2 駅だけで、目新しさはないけれど、わりと東京の要素を押さえた路線だと思いました。

横浜市高速鉄道 1 号線徒歩

昨日の土曜日は横浜市営地下鉄ブルーラインの前半です。湘南台駅から関内駅まで。線路の距離で 19.7 km 、歩きの距離で 23.4 km 。

駅前がパチンコ屋だらけの湘南台駅西口からスタート。小田急と相鉄は歩き済みなので、ここに来るのは最後かも。
湘南台公園を抜けて、田んぼゾーン。相鉄を歩いたときは田んぼを見ただけで田舎だーと思ったものですが、群馬や茨城を歩きまくったあとの今だと特に感動はありません。ちなみにぼくは岡山のど田舎の出身です。
坂を上って下飯田駅。そういえば横浜市は海沿い以外は坂だらけでした。
また坂を上りながら住宅街を抜けると立場駅。たてばと読むそうです。長後街道沿いに中田駅踊場駅まで緩やかに上り。そこから急に下って戸塚駅東海道線で歩き済みですがあんまり覚えてませんでした
柏尾川を渡り、閑静な住宅街になる。舞岡駅前にはヤマサキパンがあって田舎くさい。下永谷駅にはツバメが巣を作っていた。あと階段がつらい。
次の上永谷駅はイトーヨーカドーで開けていた。ここでご飯。暑さと坂で思ったより疲れた。
鎌倉街道に出て、港南中央駅。ここからは関内まで鎌倉街道に沿って歩く。ずっと街。ずっと平ら。
京急ぶりの上大岡駅。懐かしい。あんまり有名じゃない駅だけど (ぼくが知らないだけ?) 、結構大きい駅。「ゆめおおおか」なる複合施設の名前が間抜けっぽくて好きだった。
弘明寺駅ではおそらく弘明寺に続く参道で縁日をしていた。
蒔田駅のちょっと前に、「横浜市営地下鉄弟 1 号車両搬入の地」なる石碑があった (pdf) 。蒔田駅とその次の吉野町駅は、基本はビル街だけど商店街とかあって、古い感じの町並みだった。都会なので駅間が短い。
阪東橋駅。この辺から運河を埋め立てて作ったらしい大通り公園が関内駅まで続く。おっさんたちがビニールシートの上で将棋をしていて、なんとも微妙な雰囲気の公園だった。
伊勢崎長者町駅を通って、関内駅で終わり。


ここまでが正式名称では 1 号線で、残りの関内から横浜、新横浜を通ってあざみ野までは 3 号線らしい。

不満の記録

flagir を作るなどの過程で感じた Scala への不満を列挙。こんな記事を (日本語で) 公開しても誰も得しないし誰も読まないだろうから、やめようかなとも思ったんだけど。ぼくの勘違いなら指摘してもらえるかもしれないし、記録という意味もあるのでやっぱり公開。

文法

  • 束縛前の val 変数を参照できてしまった。かなりはまった。これは Scala のバグと言っていいと思う *1 。どう直すかというとなかなか難しいけれど。
object T {
  val foo = setup_foo
  val bar = 1

  def setup_foo = {
    bar // これが実行される時点では bar が 1 に束縛されていない
  }

  def main(args: Array[String]) {
    println(foo)  // 0 が出力される
  }
}
  • 空行があるかないかで意味が変わって、はまった。ちょっとスコープを作ろうと思っただけなのに *2
foo = 0
{ // syntax error
  val bar = 1
}
foo = 0

{ // OK
  val bar = 1
}
  • val で複数の変数が定義しにくい。
val x = 1, y = 1    // syntax error
val (x, y) = (1, 1) // 実際に Tuple を作るので、コアループでは使いたくない

val x, y, z = 1     // x == y == z == 1 になる。こんなの誰がうれしいんだ
val x@(y@z) = 1     // どうしても上の動作がしたいならこれでいいと思うんだが
  • val で同じ名前の変数を束縛できない (隠せない) 。ocaml の let はこれができていいですよね。
val x = 1
// ... x を使う ...
val x = 2 // error: x is already defined as value x
  • def の引数がパターンマッチしない。悲しい。
def foo((x, y): (Int, Int)) = x + y
  // error: identifier expected but '(' found.
  • 関数型プログラミングのイメージで書くと、どうしても f(x) を f x と書いてしまう。これはまあたぶんそのうち慣れる。
  • 引数に必ず型書くのが思った以上にだるい。これは慣れる気がしない。
  • 配列リテラルやリストリテラルでいちいち Array や List と打たなきゃいけない。xml リテラルなんぞ入れる前に必要なリテラルがあるだろう。
  • 1 つくらいよかったところも。placeholder としての _ はやはり便利。多重配列のマップでいちいち変数名考えなくていいのがうれしい。
# Ruby
matrices.map do |matrix|
  matrix.map do |column|
    column.map do |element|
      element + 1
    end
  end
end
# Scala
matrices map { _ map { _ map { element => element + 1 } } }

一応、いつぞやの dmap があれば Ruby でも簡単に書けないこともない。

matrices.dmap.dmap.dmap.map {|element| element + 1 }

  • 型推論が弱すぎて頼りない。new Array(n) だけ書くと Array[Nothing] と推論するので何かと推論失敗する。Array 使うなってことですか。
(0 until 3) map { n => n + 1 } toArray  // OK
(0 until 3).toArray map { n => n + 1 }  // error: missing parameter type
  • パターンマッチが型安全じゃない。asInstanceOf を使わなくても実行時に stuck することがある。要するに Obj.magic が自分で定義できちゃう。警告されるとは言え、かなりかっこ悪い。理由は (想像通りなら) JavaVM の仕様のせいなんだろうけど。
object Obj {
  def magic[A](v: AnyRef): A = {
    (List(v) match { case x:List[A] => x }).head
      // warning: non variable type-argument Int in type pattern is unchecked
      // since it is eliminated by erasure
  }
}

val a:Int = Obj.magic("foo")
  // String を Int に無理やりキャストしているがコンパイルは通る
  // (実行したら java.lang.ClassCastException)
  • とはいえ、静的型チェック自体はやはりとてもよい。Ruby と違って、コンパイルが通ったときに安心感 (達成感?) がある。

環境・その他

  • 便利メソッドがなさすぎて息苦しい。sort 、flatten 、each_cons 、 each_slice あたりは普通に欲しい。あと可変長配列ってないのかな。JavaVector を直接使えって?
  • やっぱりコンパイルと起動が遅い。ghc より遅い。ちょっと書いて実行して直して、を繰り返すスタイルだとかなりストレスがたまる。
  • Java 関係のツールが無条件にいらつく。生理的に受け付けない。
  • オブジェクトを作るとみるみる遅くなる。直接の原因は JavaVM なんだろうけど、Scala 側も実用向けの細かい最適化はまだまだ? リフレクションとかの関係でアグレッシブな最適化はできないんだっけ?
for (n <- 0 until 100000000) { // 18 秒
  val (x, y) = (1, 1)
  x
}
for (n <- 0 until 100000000) { // 7 秒
  val x = 1
  val y = 1
  x
}
for (n <- 0 until 100000000) { // 32 秒
  for (i <- 0 until 2) {
  }
}

val range = i <- 0 until 2
for (n <- 0 until 100000000) { // 7.5 秒
  for (range) {
  }
}
  • とはいえ、ライブラリが充実しているのと (起動以外の) 動作速度が速いのはいいこと。そういうのが必要になるプログラムはめったに書かないんだけど。

*1:Ruby でも宣言前 (代入前) の変数を参照することはできるけれど、そもそも定義前のメソッドが呼べないので、こういう問題はない。

*2:ちなみに Ruby 1.9 でも空行があるとないとで意味が変わるところがありました。さてどこでしょう。