ひしだまの変更履歴

ひしだまHPの更新履歴。
主にTRPGリプレイの元ネタ集、プログラミング技術メモと自作ソフト、好きなゲームや音楽です。

EMPTY_LISTとNil

2015-05-04 10:58:55 | PG(Scala)

Java・Scalaで何も無い事を表すキーワード』を書いたら、コメントを貰った。ライブラリーとキーワードを混同しない方がよいとのこと。

確かに空のリストと空のオプションを表すものについては、Javaでは実際によく使うメソッドの方を記載したので、異なって見えるかも。
というわけで、その部分の修正版。

JavaScala説明
EMPTY_LIST Nil 空のListインスタンス。
EMPTY None 空のOptionインスタンス。

JavaもScalaもどちらもライブラリーの一部なので、使い方は以下のような感じ。(Listの例)
どちらもキーワードっぽい使い方だ。 

JavaScala
import static java.util.Collections.EMPTY_LIST;
import java.util.List;
import scala.collection.immutable.Nil
import scala.collection.immutable.List
List<?> emptyList = EMPTY_LIST; val emptyList = Nil
@SuppressWarnings("unchecked")
List<String> emptyList = (List<String>)EMPTY_LIST;
val emptyList: List[String] = Nil
あるいは
val emptyList = Nil: List[String]
あるいは
val emptyList = Nil.asInstanceOf[List[String]]

ただ、これだと目的の要素の型を明示するのが不便なので、普通は以下のようにする。
どちらもメソッド呼び出しの使い方だ。

JavaScala
import java.util.Collections;
import java.util.List;
import scala.collection.immutable.List
List<String> emptyList = Collections.emptyList(); val emptyList = List.empty[String]

※今回のScalaの例ではJavaと対比させる為にimport文を明記したが、実際にはscala.collection.immutableパッケージのクラス(やオブジェクト等)は暗黙にインポートされているので、記述する必要は無い(というか記述しないのが普通)。
(それもあって、Nilはライブラリーという意識ではなく、キーワードと勘違いされるのかもしれないが^^;)


あと、冒頭に掲載した表では、JavaのOptionalについて「EMPTY」を載せた。
これは実際にOptionalクラスのソースに書かれている名前ではあるのだが、 可視性がprivateなのでEMPTY_LISTの様に直接使うことは出来ない^^;
そういう理由で、前回のブログではメソッド呼び出しの形式の方を書いた。

なお、空のオプションの記述方法は以下のようになる。(ScalaのNoneなんか出て来なーいw) 

JavaScala
import java.util.Optional; import scala.Option
Optional<String> emptyOption = Optional.empty(); val emptyOption = Option.empty[String]
String s = null;
Optional<String> emptyOption = Optional.ofNullable(s);
val s: String = null
val emptyOption = Option(s)
Optional<String> emptyOption = Optional.ofNullable(null); val emptyOption = Option(null: String)

※Scalaではscalaパッケージのクラス群は暗黙にインポートされるので、このimport文は記述しないのが普通。


Java・Scalaで何も無い事を表すキーワード

2015-04-19 15:30:18 | PG(Scala)

けっこう昔にも話題になってたと思うんだけど、Scalaで「何も無い事を表すキーワードが多すぎる」って言う人がいるみたい?
(ぐるぐるさんの『Scalaのnull/Nothing/Nil/Noneはやりすぎなのか?』を見て思い出した)

でもねー、Javaと比べてみても、多すぎると言うほど多くは無いと思うんだよね。 

JavaScala説明
null null 何も参照していないことを示す値。
null type(空型) Null nullの型。
Collections.emptyList() Nil 空のListインスタンス。
Optional.empty() None 空のOptionインスタンス。
void Unit メソッドで戻り値が無いときに使う型。
- Nothing 値が無い型? 

Javaに無くてScalaだけに有るのは、Nothingのみ。
少なくとも、Javaと比較して多すぎるって言ってる人は、Javaを知らないだけなのでは?
(とか言っといて、自分はJavaもScalaも基本的なことしか知らないので、他にもいっぱいあるのかもしれないけど^^;)

(文句を言うのなら、Listの::クラス::メソッドの方が、よっぽどややこしいと思う^^;) 


Scala2.10のさわり

2013-06-08 23:36:56 | PG(Scala)

ひさびさにScalaネタ。
Scala2.10が出たので変化した箇所を調べたいなーと前から思ってたんだけど、たまたま2.10.2が出たことだし、xuweiさんのScala2.10 以降に入るかもしれない機能まとめを参考にしつつ、興味ある部分を見てみた。
(ドラクエ10が全職業でレベル50になったから小休止中で時間が出来たとか、そんな事は無いですよ?w)

まずいつも調べているのが、MapとかList(Seq)のコレクションメソッドが追加されているかどうか。
今回はtoくらいしか目立つものは無かったかな。あ、toVectorも追加されてたけど、今まで無かったのかって感じ(笑)
applyOrElseやrunWithはPartialFunction関係みたいで、使いどころがイマイチよく分からないし(爆)
そういえばdeprecated(非推奨)だったメソッドが削除されたみたいだけど、自分のページでは非推奨メソッドはそもそも書いてなかったので、影響は無いw

REPLでもコマンドに増減がある。2.9で導入されて2.10で廃止されたのもあるみたい^^;
便利なのが、「:warning」コマンド!
非推奨な文法を使ったりすると「re-run with -deprecation for details」という警告が出て、詳細を知りたければ、今まではscalaコマンドに「-deprecation」を付けて再起動して同じ文を実行する必要があった。
今回からは警告が出たら「:warn」と入れるだけで詳細情報が表示される!

Scala2.10で文法的に大きな追加は以下のものかな。
値クラス
implicit class
文字列の補間
implicit classはpimp my libraryパターンに替わるもので便利なので、押さえておきたい。
文字列の補間は、整形に便利そう。DSLを作る際とかにも何かに使えるかも?

ClassManifestが非推奨になったのはちょっとびっくり。
代わりに新設されたClassTagは、メソッド名が違うだけでClassManifestとほとんど同じ使い方っぽいけど。

新設されたDynamicはなかなか面白い。
エンティティーとかを自動生成するライブラリーでは使い道がありそうな気がする。

日付関連では、噂のJodaTimeとやらは入っていないのかな?
durationという、期間(時間)を表すパッケージは新設されたみたいだけど、これだけでは何とも^^;

あと、dbcはばっさり削除されたみたい。
それなりに面白い仕組みだったんだけどなー(まともに使ったことないけど(爆))


Javaの例をScalaに変換して説明してみる

2012-05-19 11:46:56 | PG(Scala)

Javaのオブジェクト指向っぽい説明の例を、Scalaに書き換えてScalaを説明してみる。
Scalaはオブジェクト指向と関数型が融合された言語なので、ベースとしてJavaと似たオブジェクト指向(クラス)が使える。


Javaのインターフェースは、Scalaではトレイトで書く。

trait 政党 {
  def 政策を作成する() : 政策
}

defでメソッドを定義する。(Scalaは関数型言語でもあるが、クラスやトレイト内に定義するのは関数ではなくメソッド。場面に応じて、メソッドは関数に(自動的に)変換して使われる)
Javaとは違い(Pascalと似て)、メソッドの戻り値の型(や変数の型)はコロンで区切って後ろに書く。
抽象メソッドの宣言はabstractキーワードをつける必要は無く、メソッド本体を記述しないだけ。
また、可視性は、何も書かない場合はpublicになる。

世界に一つしか無い官僚機構は以下のような感じで書ける。

object 官僚 {
  def 政策を実施する(s: 政党) : 結果 = {
    try {
      val dummy =  s.政策を作成する()
    } catch {
      case e: Exception =>
    }
    new 天下り先()
  }
}

(トップレベルに書かれた)objectは、シングルトンオブジェクトとなる。つまりnewしなくても自動的にVM内に1つだけインスタンスが作られる。
(トップレベルでなくクラス内に書かれたobjectはクラスをインスタンス化する際にそのインスタンス毎に作られる(staticの代わりではない)ので注意)

メソッド本体は、戻り型の指定の後ろに「=」を付けてその後ろに書く。
各文の末尾のセミコロンは省略可能。Scalaでは普通は書かない。
メソッドの戻り値としては、波括弧でくくられたブロックの一番最後の値が返る。したがって「return」は書かない。(Javaと違って、メソッド内の途中でreturnで抜けることは基本的にしない)

try~catchの機能はJavaと同じだが、catch句の書き方がちょっと違う。(Scalaのmatch式の書き方に近い)
caseの「=>」の後ろに例外処理を書くのだが、官僚は握りつぶしている(何も処理しない)ので、例としては良くないな^^;


トレイトをミックスイン(「インターフェースを実装する」のと同じような意味)してクラスを書くには以下の様にする。

class 自党 extends 政党 {
  override def 政策を作成する() : 政策 = new 我田引鉄()
}

class 共党 extends 政党 {
  override def 政策を作成する() : 政策 = new 実現不可能な理想論()
}

メソッドをオーバーライドする際はoverrideを付ける。Javaでは@Overrideアノテーションだったが、Scalaでは言語内で規定されたキーワードとなっている。
(抽象メソッドをオーバーライドする際はoverrideを付けなくてもいい(付けないのが多数派だ)が、個人的には付けた方が良いと思っている。オーバーライドしていることが一目瞭然だし、親クラスのメソッド名を変えたときにコンパイルエラーになってくれるし)

メソッド本体が1つの式で収まる場合は、波括弧のブロックにする必要が無い。
(Scalaの構文としては、メソッド本体は1つの式を指定するだけ。複数の文を書きたい場合に波括弧のブロックを利用するという扱い)

インスタンスをnewで作ることはJavaと同じ。
ただし、コンストラクターの引数が無い場合は丸括弧も省略できる。

val 元祖自党 = new 自党()
var 亀下新党 = new 自党
var 石井新党 = new 自党
var 橋原新党 = new 自党

変数はvarまたはvalで定義する。
valは、Javaでのfinal変数と同じ。つまり、valで定義した変数には他の値を再代入することが出来ない。変数が別のインスタンスを指すことが出来ないというだけで、変数内のインスタンスの中の値が書き換えられないわけではない。Scala(関数型の考え方?)としては、インスタンス内が書き換えられないようにクラス(イミュータブルなクラス)を作るのが望ましい。

イミュータブルなクラスでは、インスタンス内の一部を書き換えたい場合は、書き換えずに新しいインスタンスを生成する形となる。
今回の政党の機能としては扱っていないが、政党間で党員の移動(自党から民党への移籍等)は非常に頻繁に起こるので、インスタンス内の党員の一覧は書き換え可能な方がやりやすいだろう。
(個人的には、現在のScalaがJavaVM上で動いている以上はインスタンスを大量に生成するのは効率が悪いので、大量に書き換えが発生しそうな用途ならミュータブルにした方がいいと思う。ぜひ、Scalaにはイミュータブルでも効率の良いScalaVMを作って欲しいw)

あと、自分は手続き型言語歴が長いので、変数へ「代入する」という言葉を使うが、Scalaでは「束縛する(bind?)」と言うのが正しいっぽい。
変数名やメソッド名などに値を束縛する(割り当てる・固定する)というニュアンスなんだと思う。


既存のクラスを継承したクラスは以下の様に書く。

class 民党 extends 自党

独自のメソッドやフィールドを定義しない場合は、クラス定義の波括弧が省略できる。


コンストラクターの引数で渡された値をフィールドに保持するだけの場合、クラス名の直後に引数(フィールド定義を兼ねる)を指定するような書き方が出来る。

class 委譲政党(protected val s: 政党) extends 政党 {
  override def 政策を作成する() = s.政策を作成する() //他の政党に委譲する
}

val 公党 = new 委譲政党(元祖自党)
val 社党 = new 委譲政党(元祖自党)

メソッドの戻り値の型がメソッド本体から推測できる場合は、defの型の指定は省略することが出来る。

ちなみに、Javaと同じような書き方をすると、以下の様にくどくなる。

class 委譲政党 extends 政党 {
  protected var s:政党 = null
  def this(s: 政党) = {
    this()
    this.s = s
  }
  override def 政策を作成する() = s.政策を作成する() //他の政党に委譲する
}

Scalaのクラスでは基本コンストラクターというものが必ず出来る。クラス名の直後に引数を書くとそれが基本コンストラクターの引数となる(省略された場合は引数なしのコンストラクターとなる)。
それ以外のコンストラクター(補助コンストラクター)はthisという名前のメソッドを定義するような書き方をする。
上記のthisメソッドでは、先頭でthis()を呼び出しているが。def thisで作った補助コンストラクターは必ず(自分より前に定義された)他のコンストラクターを呼び出す必要がある。ここら辺はJavaのコンストラクターとは考え方が違うところ。


基本的にはJavaのオブジェクト指向で出来る事はScalaでも出来るが、Scala独自の考え方で異なっている部分もある。

Scalaの勉強としては、次のステップはList操作(ScalaではSeqというクラス)を勉強するのが良いと思う。関数型を生かした便利メソッドがいっぱい出てくるがw、foreachが基本でfiltermap辺りがまず重要。


Play2.0 Eclipse設定作成時にソースを添付する方法

2012-04-28 01:40:54 | PG(Scala)

ueshinさんがTwitterでeclipsifyにwith-source=trueという便利なものがあるとつぶやいていたので、ほほう!と思って試してみたら、上手くいかなかった(爆)

色々教えていただいた結果、とりあえず何とかする手順は分かったので、メモ。

…それにしても、こんなにハマるとは思わなかったなぁ(苦笑)