名称 | 内容 | 入力 | 出力 |
---|---|---|---|
プリプロセッサ | #defineや#includeなどを変換 | c | c |
コンパイラ | アセンブリ言語へ変換 | c | s |
アセンブラ | オブジェクトファイル(機械語が入っているファイル)を生成 | s | o |
リンカ | 実行可能ファイルを生成 | o | exeなど |
インタプリタ | 直接実行できないファイルを解釈して実行, sh/py/php/他のCPU用の実行可能ファイルなど | なし |
追記
内容が非常にアレであったため、大幅に書き換えた。
名称 | 内容 | 入力 | 出力 |
---|---|---|---|
プリプロセッサ | #defineや#includeなどを変換 | c | c |
コンパイラ | アセンブリ言語へ変換 | c | s |
アセンブラ | オブジェクトファイル(機械語が入っているファイル)を生成 | s | o |
リンカ | 実行可能ファイルを生成 | o | exeなど |
インタプリタ | 直接実行できないファイルを解釈して実行, sh/py/php/他のCPU用の実行可能ファイルなど | なし |
内容が非常にアレであったため、大幅に書き換えた。
let hoge = 'hoge'
同じ名前の別の変数を定義すること。OCaml由来。
両方の値に同じ名前を付けると、先に付けたほうの名前が「見えなくなる」というだけです。これを「シャドウイング(shadowing)」と言いますが、F#において、値が変わっているように見えるのは実は値を上書きしているわけではなく、別の値に同じ名前を付けているだけなのです。
(前提知識) // 16進数 1桁4ビット // 8進数 1桁3ビット // 16ビット部分をまとめて命令 // 命令の中身をopcodeとoperand // opcode operand // [89][01] // trapなどは8ビットずつに命令が分かれている // 4444 // その他の命令文は // 133333 // という構成。
脱REPL的なものを目指す。
Scalaメモ(コンパイル、main) - garbage truck
コードはこんな感じ。
trait.scala
trait Programmer { def coding = println("コーディングします") } // クラスが明示的に継承を行わない場合、extendsを使用してトレイトをミックスイン class Person(val name: String) extends Programmer trait Designer { def design = println("デザインします") } object Trait { def main(args: Array[String]) { // ほかのクラス/オブジェクトを継承する場合、withキーワードでトレイトをミックスインする var p1 = new Person("taro") p1.coding var p2 = new Person("taro") with Designer p2.coding p2.design } }
コマンド
$ scala -version Scala code runner version 2.10.3 -- Copyright 2002-2013, LAMP/EPFL $ scalac trait.scala (コンパイルしてクラスファイルTraitが生成される) $ scala Trait コーディングします コーディングします デザインします
複数のトレイトを使用した場合、コンストラクタが実行される順番は、 スーパークラスのコンストラクタのあとに自分自身のコンストラクタが呼ばれて その後ミックスインしている。
parant.scala
class Parent { println("Parent") } class Child extends Parent { println("Child") } trait A { println("trait A") } trait B { println("trait B") } trait C { println("trait C") } object Parent { def main(args: Array[String]) { val c = new Child with A with B with C // println(c) } }
コマンド
$ scalac parent.scala $ scala Parent Parent Child trait A trait B trait C
複数実装したトレイトの名前(シグネチャ)が同じ場合、
これらをまとめてミックスインしたらエラーになるので、
そのメソッドは必ずオーバーライドする必要がある。
trait Programmer { def write = println("コードを書きます") } trait Writer { def write = println("記事を書きます") } // このまま書くとerror: class Person inherits conflicting members:とかなる // class Person extends Programmer with Writer class Person extends Programmer with Writer { // なのでwriteメソッドをオーバーライドする必要がある override def write = println("ドキュメントを書きます") } object Write { def main(args: Array[String]) { var p = new Person println(p) println(p.write) } }
superを利用してトレイトのwriteを呼び出す。
trait Programmer { def write = println("コードを書きます") } trait Writer { def write = println("記事を書きます") } class Person extends Programmer with Writer { override def write = super.write } object Write { def main(args: Array[String]) { var p = new Person println(p) println(p.write) } }
$ scalac write.scala $ scala Write Person@46fde259 記事を書きます
abstract宣言されたメソッドの中でsuperの呼び出しを行っている。 この場合、メソッドの具体的な定義がしてあるクラスやトレイトの後で ミックスインされているのであれば正しく動く。
定義内容が動的に束縛される。
こういう処理をやるためにはabstract overrideを使う。
abstract class Engineer { println ("class Engineer constructor") def work(time:Int) } class Person extends Engineer { println ("class Person constructor") def work(time:Int) { println ("Person#work start") println ("1つのタスクを"+time+"分で行います") println ("Person#work end") } } trait Programmer extends Engineer { println("trait Programmer constructor") abstract override def work(time:Int) = { println("Programmer#work start") super.work(time - 15) println("Programmer#work end") } } object Engineer { def main(args: Array[String]) { var p1 = new Person println(p1.work(60)) var p2 = new Person with Programmer println(p2.work(60)) } }
workメソッドを呼ぶとProgrammerトレイトのworkメソッドを呼び、そのあとにPersonクラスのworkを実行する。
$ scala Engineer class Engineer constructor class Person constructor Person#work start 1つのタスクを60分で行います Person#work end class Engineer constructor class Person constructor trait Programmer constructor Programmer#work start Person#work start 1つのタスクを45分で行います Person#work end Programmer#work end
abstract class Engineer { println ("class Engineer constructor") def work(time:Int) } class Person extends Engineer { println ("class Person constructor") def work(time:Int) { println ("Person#work start") println ("1つのタスクを"+time+"分で行います") println ("Person#work end") } } trait Programmer extends Engineer { println("trait Programmer constructor") abstract override def work(time:Int) = { println("Programmer#work start") super.work(time - 15) println("Programmer#work end") } } trait Agiler extends Engineer { println("trait Agiler constructor") abstract override def work(time:Int) = { println("Programmer#work start") super.work(time / 2) println("Programmer#work end") } } object Engineer { def main(args: Array[String]) { var p4 = new Person with Programmer with Agiler println(p4.work(60)) // (60/2)-15 var p3 = new Person with Agiler with Programmer println(p3.work(60)) // (60-15)/2 } }
一般的にはコンストラクタやメソッドを使用するとき、引数を使用してパラメータ化する
型のパラメータ化とは、それと同じようにクラスやメソッドなどで使用する型そのものをパラメータ化再利用性を高める機能である。
型パラメータ名を指定していなくても型推論でString型だったりAny型にしたりできる。
型パラメータをString型に指定しておいてString型以外の要素を渡そうとするとコンパイルエラーにできる。
elcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45). Type in expressions to have them evaluated. Type :help for more information. scala> val sList = List[String]("a","b","c") sList: List[String] = List(a, b, c) scala> val sList = List("a","b","c") sList: List[String] = List(a, b, c) scala> sList.head res0: String = a scala> val sList = List("a","b",1) sList: List[Any] = List(a, b, 1) scala> val sList = List[String]("a","b",1) <console>:7: error: type mismatch; found : Int(1) required: String val sList = List[String]("a","b",1) ^
下の例だとMySampleのparamフィールドはString型として使えるようになる。
class MySample[A] { var param:A = _ // 型パラメータの型を指定する def get:A = param def set(param:A) = this.param = param } object Sample { def main(args: Array[String]) { val x = new MySample[String] x.set("hello") println(x.get) } }