2009年 07月 07日

Ruby っぽいブロックのとりかた

object Main extends Application {
	def rubylike (s:Int, e:Int)(f:Int => Unit) = {
		(s to e).foreach { i =>
			f(i)
		}
	}

	rubylike(1, 10) { i =>
		println(i)
	}
}

部分的にカリー化して最後に関数をひとつだけとるようにすると、いい感じに書ける

2009年 06月 05日

クラスメソッドとインスタンスメソッドの定義

どうやら static なんとか、みたいに書いてクラスメソッドをつくる方法はないようだ?

class ModelBase (initarg:Any) {
	// class method
	def create (args: (Symbol, Any)*) = {
		val ret = this.getClass.newInstance.asInstanceOf[ModelBase]

		for ( (key, value) <- args) {
			ret(key) = value
		}

		ret
	}

	// instance method
	def update (key:Symbol, value:Any):Unit = {
		println(key, value)
	}
}

class User (a:Any) extends ModelBase(a) {
	def update_session ():String = {
		"......."
	}
}

object User extends User(null)

val user = User.create('name -> "cho45", 'session_key -> "...")

println(user)
println(user.update_session) //=> type error (user が ModelBase にキャストされてるから……)

object を class とは別に継承して定義して (これ、名前空間が別なんだろうか……) あげるみたいだ。

あと、こういうスーパークラスにインスタンス化をおいだす処理をどう書いたらいいかわからない……

こういうときのための generics か……

class ModelBase [T <: ModelBase[T]] (initarg:Any) {
	// class method
	def create (args: (Symbol, Any)*) = {
		val ret = this.getClass.newInstance.asInstanceOf[T]

		for ( (key, value) <- args) {
			ret(key) = value
		}

		ret
	}

	// instance method

	def update (key:Symbol, value:Any):Unit = {
		println(key, value)
	}
}

class User (a:Any) extends ModelBase[User](a) {
	def update_session ():String = {
		"......."
	}
}

object User extends User(null)

val user = User.create('name -> "cho45", 'session_key -> "...")

println(user)
println(user.update_session)

クラス名からインスタンスがつくれない

val con = classOf[Symbol].getConstructor(classOf[String])

Exception in thread "main" java.lang.ExceptionInInitializerError
        at Main.main(scala.scala)
Caused by: java.lang.NoSuchMethodException: Main$User$.<init>(java.lang.Object)
        at java.lang.Class.getConstructor0(Class.java:2678)
        at java.lang.Class.getConstructor(Class.java:1629)
        at Main$ModelBase.create(scala.scala:13)
        at Main$.<init>(scala.scala:38)
        at Main$.<clinit>(scala.scala)
        ... 1 more

というエラーでにっちもさっちもいかない……

2009年 05月 31日

思うところ

Scala らしさ、というのがよくわからない。Scala であってもクラス作りまくってほげほげするという Java らしさを受け継ぎつつ書くのがいいんだろうか。というより Java のライブラリを利用すると自然とそうなってしまう……

2009年 05月 29日

web.xml filter, 自分で Dispatch

Lift 見つつ最低限な部分を自分で再実装

  • 全部のリクエストを受け取ってなんかしたいなら filter を使う
  • filter では、何もせずに chain.doFilter すれば static ファイルとかをいい感じにやってくれる。

web.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
	<filter>
		<filter-name>HttpRequestDispatcher</filter-name>
		<filter-class>net.lowreal.skirts.HttpRequestDispatcher</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>HttpRequestDispatcher</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>
package net.lowreal.skirts

import javax.servlet._
import javax.servlet.http.{HttpServlet, HttpServletResponse, HttpServletRequest}

class HttpRequestDispatcher extends Filter {
	val static = """^/(?:css|js|images|static).*""".r

	def init (filterConfig: FilterConfig) = {
		println("init")
	}

	def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) = {
		println("doFilter")
		(request, response) match {
			case (req: HttpServletRequest, res: HttpServletResponse) =>
				println("")
				println(req)
				req.getRequestURI match {
					case static() =>
						println("static")
						chain.doFilter(request, response)
					case _ =>
						println("dispatch")
						res.setContentType("text/html")
						res.getWriter.println { """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">""" }
						res.getWriter.println {
							<html>
								<head><title>Hello World</title></head>

								<link rel="stylesheet" type="text/css" href="/css/base.css" media="screen,tv"/>
								<!-- script type="text/javascript" src="/js/site-script.js"></script -->
							<body>
								<h1>Request</h1>
								<pre>Method: { req.getMethod }</pre>
								<pre>RequestURI: { req.getRequestURI }</pre>
								<pre>QueryString: { req.getQueryString }</pre>
								<h1>Raw</h1>
								<pre>{ req }</pre>
							</body>
							</html>
						}
				}
			case _ => chain.doFilter(request, response)
		}
	}

	def destroy () = {
		println("destroy")
	}
}

skirts っていう名前で簡単なフレームワークを作ろうと思ってる。とりあえず Lift は気にいらなかったので、コードは参考にしつつも使わない方向に……

skirts = scala / 周りをとりまく何か / 美少女

2009年 05月 28日

スカラクロウラ - アクター

うーんよくわからない。while(true)/receive と loop/react の違いもよくわからない (スレッド作るかそうじゃないかだけの違い?)

クローラっぽいのを練習がてら書いてみた。あんまりわかりやすくはないなぁという気もする。もっといい書きかたあるのかな。

  • 一度に走るリクエストは2つまで
    • あらかじめ2つリクエストを出す Actor を作ってそれのキューにいれていく
  • List あたりが微妙にわかりにくい。普通に shift/push したい

http://gist.github.com/119257

あれこれ最初、スカラクロウラとかエントリで言いたかっただけだったのに、全くそんなこと忘れてエントリ書いてた

2009年 05月 27日

部分適用・メソッド呼びだしの syntax suger・デフォルト引数

メモメモ。簡単な Singleton Logger を実装してみる

//#!scala

object Logger {
	var level = 0

	def log (message: String, level: Int) {
		if (this.level <= level) {
			println(message)
		}
	}

	def log (message: String):Unit = log(message, 1)

	def debug = log(_: String, 0);
	def info  = log(_: String, 1);
	def warn  = log(_: String, 2);
	def error = log(_: String, 3);
	def fatal = log(_: String, 4);

	// この例の場合はこうしたほうがいい気がする
	// def log (message: String):Unit = info
}

Logger.level = 1

Logger debug "debug"
Logger info "info"
Logger warn "warn"

部分適用は _ と型さえ書けばいいっぽい? 引数の順番に制限はないようだ

Logger foo argLogger.foo(arg) の syntax sugar らしい。引数一つのときに省略ができるというルールではなくて、レシーバも含めた syntax sugar のようだ

デフォルト引数は Ruby とかのように仮引数に書くことはできなくて、overload で定義するっぽい。このとき overload する側のメソッドは、返り値の型の宣言が必要らしい