2014年4月12日土曜日

Programming in Scala, First Edition: Chapter 5

5. Basic Types and Operations
  scalaの方について更に掘り下げる。
  javaと同じ部分も多いが、java以上の部分もある。
  Strings, Int, Short, Byte, Float, Double, Char, Boolean
  演算子と優先順位。
  暗黙変換がこれらの型をjava以上に使いやすくしている。

5.1 Some basic types
  Byte, Short, Int, Longは符号付整数で8bit-64bit
  Float, Doubleは32bit単精度浮動小数と64bit倍精度浮動小数
  Charは16bit符号なしunicode。StringはimmutableのCharのsequence
  Booleanはtrue or false
  String以外はjava.lang、全てがscalaで定義されている。
    scala.Intがfull nameだが、自動でimportされているのでIntで良い。
  integral types, numeric types
  これらはjavaと同じでjavaのprimitiveのコンパイル時に返還される。
  javaと同じで小文字でも使えるが、大文字推奨。

5.2 Literals
  リテラルと言うのは固定値をコードに直接書く手段。
    5.1の全ての型にリテラル表記がある。
    raw strings, symbols以外はjavaのリテラルと同じ。
  Integer literals
    通常10進、0x,0Xで16進、0で8進、l,LでLong、他はInt
    ByteやShortのリテラルはなくて、範囲内のIntのリテラルを割り当てる。
      val little: Byte = 11L はNG。Longは小さくても割り当てられない。
      演算は桁の多い方に合わせられる。
  Floating point literals
    F,fでFloat, d, DでDouble, 省略したらDouble。
    e,Eの指数表記も使える。
  Character literals
    unicode、''で囲む。\0-\377までは8進、\u0044でunicodeで16進
    変数名でも何処でも\u0044等のコード表記可能。
      これによってnon-ASCIIも使える。
    エスケープシーケンス \n \b \t \f \r \\ \" \'
      \rは行頭戻る。\fは横方向はそのままで一行下に進む。\n = \f\r
  String literals
    "で囲む。エスケープはCharと同じ。
    """で囲むと。raw string。改行も含めて"""以外はすべて書ける。
      ?? """はエスケープできない??
    複数行にまたがる時は|と.stripMarginで行頭をそろえられる。
      println("""| hoge
                 | fuga """.stripMargin)
  Symbol literals
    'identでSymbol。identは英数文字なら何でもOK。
    実際はSymbol("ident")のfactory methodが呼ばれて生成される。
    型無しの物はscalaでは扱えないため。
    同じidentなら同じobjectになる。(interned)
  Boolean literals
    true, false

5.3 Operators are methods
  scalaではOperatorsもmethods。表記法が違うだけ。
  1 + 1 は (1).+(1)と同じ。Intクラスの+メソッドが呼ばれているだけ。
  メソッドはoverloadされる。polymorphism
    同じな名前でも引数の型や数で別定義となる。
  infix, prefix, postfixの記法がある。
  prefixはunary(単項)
    unary_Opsでメソッド名になる。
    -3 は 3.unary_-
    +, -, !, ~の4つだけがprefixとして使える。
      unary_*を定義しても*pとしては使えない。
  ?? postfixは推奨されていない ?? 下記を使う様に言われた。
    import scala.language.postfixOps
    compiler option -language:postfixOps
  ** -featureで実行すると詳しい説明が出た。
  どんなoperatorが使えるかは、typeのクラスのメソッド宣言をAPI仕様書で見る。

5.4 Arithmetic operations
  numeric typesには+,-,*,/,%の演算子が使える。
  Doubleの%(modulo or remainder)もある。
    Q=P%M は Q=P-M*Int (Intは M*Int ≦ P の最大の整数)
      scalaではtruncate(切り捨て)
    IEEE754はround(四捨五入)で定義している。
      Math.IEEEremainder(6.1, 4.0)とすれば使える。
    ** 他にceil,floor,euclidean等のmodulo定義もあるらしい。
  +,-はunary(単項)prefix演算子として使える。
    +は-との対照性を保つためでつけなくても同じ。
    ** ただし、存在しているの注意は必要
    ** 1 + 2の+の前で改行すると(1); (2).unary_+()と解釈される。
       ** なので、改行の前に演算子+を置くようにする。

5.5 Relational and logical operations
  <,>,<=,>=の比較演算子と!の否定演算子。
  ||, &&はJavaやCと同じでshort-circuitedで右項は評価されない可能性がる。
    ||, &&はメソッドなので右項はパラメータ。
       1 < 3 || 2 > 3 は (1 < 3).||(2 > 3)
    メソッド呼び出しでは通常はパラメータは先に評価される。
      by-value parameter (b: Boolean)
    遅延評価を使えばパラメータ、右項を評価しないことも出来る。
      by-name parameter(b:=> Boolean)
  ** scalaはlexical scope。clojureが重くなるという欠点はある。

5.6 Bitwise operations
  &,|,^,~,<<,>>,>>>
  integer typeのメソッド
  >>は符号ビットが保持される。
  >>>は符号ビットに0になる。

5.7 Object equality
  ==,!=
  nullやnullかもしれないものとの比較も出来る。例外は飛ばない。
  左項のメソッドとして実行される。動作はメソッドの定義に依存する。
    多くは他の型とも比較できる。
    多くはjavaと異なり内容を比較している。
  eq,neでリファレンスを比較できる。
    javaのオブジェクトに直接マッピングされるものに対してのみ適用。

5.8 Operator precedence and associativity
  演算子記法の優先順位は、演算子の「最初の文字」に依存して決まる。
    その他特殊文字 > *,/,% > +,- > =,! > : > <,> > & > ^ > | > その他文字
    例外として=で終わる代入系は一番低い
  通常は左結合、「:で終わる」演算子はレシーバが右結合
  結合順序によらず、オペランドは左から右に評価される。
    a ::: (b ::: c) // a, b, cの順で評価
    (c.:::(b)).:::(a) // c, b, aの順で評価
    ** 評価順序は難しい。。。
  ** 最初の文字とか、終わりの文字とかが動作に影響するのは覚えにくい。。。
  ** でも、これが全てがメソッドなのに自然な演算子に見えるカラクリ。

5.9 Rich wrappers
  基本型にはそのRich wrappersが存在して、色々なメソッドが定義されている。
    暗黙変換によってメソッドが使えるようになっているが、これは後で出てくる。
    scala.runtime.RichByte等で定義されている。
  何があるかはAPIドキュメントを参照する。

5.10 Conclusion
  scalaでは演算子もすべてメソッド。暗黙変換で便利なメソッドを追加できる。

0 件のコメント:

コメントを投稿