サーバーサイド jQuery をやってみる!
最近、社内で PHP Spidermonkey が流行って(?)いるようです><!
Cybozu Inside Out: SpiderMonkeyを使ってPHPでサーバーサイドJavaScript
id:ama-ch さすがです><
というわけで
僕も、 PHP の Spidermonkey でどのくらいのことが出来るのか試してみました><
まず、 Hello, world!
<?php // new して $js = new JSContext(); // print 関数作って $js->registerFunction(function($v) { print $v; }, 'print'); // こんにちはこんにちは! $js->evaluateScript('print("Hello, world!!")');
Hello, world!
おおお、簡単!
次は、 id:m-hiyama さんが作った minidom.js を読み込んでみる!
minidom.js は Pure JavaScript による DOM の実装です!
詳しくはこちら
100% JavaScriptによる、簡易なDOM/SAXの実装 - 檜山正幸のキマイラ飼育記
<?php $js = new JSContext(); $js->registerFunction(function($v) { print $v; }, 'print'); // minidom.js を読み込んで $js->evaluateScript(file_get_contents('http://www.chimaira.org/tools/minidom.js.txt')); // div 要素を作ってみる! $js->evaluateScript('print(document.createElement("div").toString(0))');
<div ></div>
なんかでたー!
おおお! minidom.js ++
調子に乗って、 John Resig さんが作った htmlparser.js を読み込んでみる!
htmlparser は Pure JavaScript で書かれた HTML パーサーです!
詳しくはこちら
John Resig - Pure JavaScript HTML Parser
<?php $js = new JSContext(); $js->registerFunction(function($v) { print $v; }, 'print'); $js->evaluateScript(file_get_contents('http://www.chimaira.org/tools/minidom.js.txt')); // htmlparserjs を読み込む! $js->evaluateScript(file_get_contents('http://ejohn.org/files/htmlparser.js')); // JavaScript を用意! $script = <<< END HTMLParser("<html><body>foo<div>bar</div>baz</body></html>", { start: function(tag) { print(tag + "(start)\\n"); }, chars: function(text) { print(text + "(text)\\n"); }, end: function(tag) { print(tag + "(end)\\n"); } }) END; // 実行!!1 $js->evaluateScript($script);
どきどき
html(start) body(start) foo(text) div(start) bar(text) div(end) baz(text) body(end) html(end)
おおおお、ちゃんとパースできたあああ
パースして DOM を構築してみる
こんどは、 htmlparser でパースした HTML を minidom.js の DOM 実装に乗せてみる
<?php $js = new JSContext(); $js->registerFunction(function($v) { print $v; }, 'print'); $js->evaluateScript(file_get_contents('http://www.chimaira.org/tools/minidom.js.txt')); $js->evaluateScript(file_get_contents('http://ejohn.org/files/htmlparser.js')); // ちょっと htmlparser と minidom を拡張 $js->evaluateScript(file_get_contents('http://amachang.sakura.ne.jp/misc/php_jquery/fix.js')); // html を読み込んでみる! $js->assign('html', file_get_contents('http://amachang.sakura.ne.jp/misc/php_jquery/pasee.html')); // パース実行! $js->evaluateScript('parseHtml(html, document);'); // toSource で DOM 構造を見て見る! print $js->evaluateScript('document.documentElement.toSource()');
#2={_root:#1={_root:#1#, ownerDocument:#1#, parentNode:null, nodeType:9, nodeName:"#document", _name:"main", _idMap:{}, childNodes:[#2#], firstChild:#2#, lastChild:#2#, documentElement:#2#, implementa ....
おおお、なんかパースできてそう!!
jQuery を使ってみる!
でっきるかなー!
<?php $js = new JSContext(); $js->registerFunction(function($v) { print $v; }, 'print'); $js->evaluateScript(file_get_contents('http://www.chimaira.org/tools/minidom.js.txt')); $js->evaluateScript(file_get_contents('http://ejohn.org/files/htmlparser.js')); $js->evaluateScript(file_get_contents('http://amachang.sakura.ne.jp/misc/php_jquery/fix.js')); $js->assign('html', file_get_contents('http://amachang.sakura.ne.jp/misc/php_jquery/pasee.html')); $js->evaluateScript('parseHtml(html, document)'); // jquery を読み込む! $js->evaluateScript(file_get_contents('http://code.jquery.com/jquery.js')); // JavaScript を実行! print $js->evaluateScript('Array.join($(".hoge"), "\n")');
<div class="hoge" >foo</div> <div class="hoge" >bar</div> <div class="hoge" >baz</div>
きたーヽ(;'□')ノ
というわけで
なんとか PHP の Spidermonkey で jQuery を動かすことが出来ました!ぱちぱちー
でも、適当かつ無理やり動かしてるので jQuery でも動かない機能が多々あると思います><
ごめんなさいごめんなさい><
まあ、ともあれ JavaScript がサーバーサイドで動くってーのはめっちゃ楽しいですね!
ではではーヽ(`・ω・´;)ノ
Java でアスキーアート画像を生成する
と言う訳で書いてみました
"-D" オプションでいろいろ設定できます。
import java.lang.String; import java.lang.System; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.File; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.awt.GraphicsEnvironment; import java.awt.Font; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.awt.RenderingHints; import javax.imageio.ImageIO; public class CreateImage { private static String P(String name, String def) { return System.getProperty(name, def); } public static void main(String[] args) throws Exception { final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in, P("charset", "UTF-8"))); final Collection<String> list = new LinkedList<String>(); final int width = Integer.parseInt(P("width", "600")); final int height = Integer.parseInt(P("height", "400")); GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font font = Font.createFont(Font.TRUETYPE_FONT, new File(P("fontpath", "ipagp-mona.ttf"))); env.registerFont(font); String line; while ((line = reader.readLine()) != null) { list.add(line); } final int lineLength = list.size(); final float fontHeight = height / lineLength; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VBGR); g.setColor(Color.WHITE); g.fillRect(0, 0, image.getWidth(), image.getHeight()); g.setColor(Color.BLACK); g.setFont(font.deriveFont(fontHeight)); Iterator<String> it = list.iterator(); for (int i = 0; it.hasNext(); i++) { g.drawString(it.next(), 10, i * fontHeight + fontHeight); } ImageIO.write(image, "png", new File(P("output", "hoge.png"))); } }
Jython がおもしろい
仕事で Jython を使う機会があって
ほぼ、初めて Jython を触ったんですけど、めっちゃおもしろい。
Java のクラスが何も考えずに使えちゃう。
たとえば、 HTML (not XHTML) をパースして XPath で取得するコードとかを nekohtml と xalan で以下のように書ける
from java.io import FileInputStream from org.xml.sax import InputSource from org.cyberneko.html.parsers import DOMParser from org.apache.xpath import XPathAPI # input source = InputSource(FileInputStream('test.html')) source.setEncoding('UTF-8') # parse parser = DOMParser() parser.parse(source) doc = parser.getDocument() # xpath evaluate print XPathAPI.selectNodeList(doc, '/HTML/BODY/*').item(0)
ほんと楽に Java のクラスが使えて感動した。
てか、このサンプル java のクラス以外使ってないっていう。
後は id:nishiohirokazu の Jython 本を買えば完璧ですね!
Java でラムダ
λ... λ... ちょっととおりますよ
はじめに
C++ Template の勉強をしていて、気がついた。
- ネストした(内側から外側が見える)名前-値の空間が存在し
- 値から名前-値の空間を生成することが可能で
- その空間を生成するための情報を値として扱え
- 名前-値の空間の中の一つ以上の値を取り出せると
ラムダが出来る。
という訳で Java でラムダを作ってみた
import static java.lang.System.out; public class Hoge { public static void main (String args[]) { // チャーチ数 0 final λ zero = new λ () { λ call (final λ f) { return new λ () { λ call (final λ x) { return x; }}; }}; // チャーチ数の succ final λ succ = new λ () { λ call (final λ n) { return new λ () { λ call (final λ f) { return new λ () { λ call (final λ x) { return f.call(n.call(f).call(x)); }}; }}; }}; // チャーチ数の plus final λ plus = new λ () { λ call (final λ n) { return new λ () { λ call (final λ m) { return new λ () { λ call (final λ f) { return new λ () { λ call (final λ x) { return m.call(f).call(n.call(f).call(x)); }}; }}; }}; }}; out.println( // ((0++)++)+((0++)+((0++)++)) // 2+(1+2) // 2+3 // 5 plus.call(succ.call(succ.call(zero))) .call( plus.call(succ.call(zero)) .call(succ.call(succ.call(zero)))) // int 化 .call(new λ () { λ call (final λ b) { return new V () { int v() { return b.v() + 1; }}; }}) .call(new V() { int v() { return 0; }}) ); // y combinator final λ y = new λ () { λ call (final λ f) { return new λ () { λ call (final λ g) { return new λ () { λ call (final λ m) { return f.call(g.call(g)).call(m); }}; }}.call(new λ () { λ call (final λ g) { return new λ () { λ call (final λ m) { return f.call(g.call(g)).call(m); }}; }}); }}; // fibonatti final λ fib = y.call(new λ () { λ call (final λ fib) { return new λ () { λ call (final λ a) { return (a.v() < 2) ? a : new V () { int v() { return fib.call(new V() {int v() { return a.v() - 1; }}).v() + fib.call(new V() { int v() { return a.v() - 2; }}).v(); }}; }}; }}); out.println( // fib(10) = 55 fib.call(new V () { int v() { return 10; }}) ); } } abstract class λ { abstract λ call(λ a); λ call(V a) { return this.call((λ)a); } int v() { throw new RuntimeException(); } } abstract class V extends λ { λ call(λ a) { throw new RuntimeException(); } abstract int v(); public String toString() { return "" + this.v(); } }
Java のλの特徴
見ての通り、無名クラスはそのスコープの final な変数を扱えるのでそれを使ってネストした名前-値の空間が出来る。
しかも、 final しか扱えないのでインスタンスフィールドを使わなければ参照透明だ。
ただ、 a = λx.a(x -1) のように再帰的なことを書こうと思うと、コンパイル時に「a がまだ初期化されてない」と怒られるので y コンビネータが必要。
(追記) 更なる勉強
コメント欄で id:alohakun に教えて貰った 結論:結局、Javaはクロージャを使えるの? - lethevert is a programmer のコメント欄がめちゃめちゃ面白いです。
Java 5 の型推論が分からない
なんぞこれ><
Javaの型推論Utilsクラス - yukobaのブログ
ってことでやってみた
これは OK
import java.util.ArrayList; import static java.lang.System.out; public class Main { public static <S, T> T cast(S o) { return (T) o; } public static void main(String[] args) { ArrayList a = new ArrayList(); ArrayList<String> b = cast(a); b.add("hoge"); b.add("fuga"); out.println(b); Hoge c = cast(a); // キャストできない場合は実行時例外になる } } class Hoge {}
$ javac -Xlint:unchecked Main.java && java Main Main.java:7: warning: [unchecked] unchecked cast found : S required: T public static <S, T> T cast(S o) { return (T) o; } ^ 1 warning [hoge, fuga] Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList at Main.main(Main.java:22)
でもなんでこれはダメ?
import java.util.ArrayList; import static java.lang.System.out; public class Main { public static <S, T> T cast(S o) { return (T) o; } public static void hoge(ArrayList<String> a) { a.add("piyo"); } public static void main(String[] args) { ArrayList a = new ArrayList(); hoge(cast(a)); out.println(a); } }
$ javac -Xlint:unchecked Main.java && java Main Main.java:6: warning: [unchecked] unchecked cast found : S required: T public static <S, T> T cast(S o) { return (T) o; } ^ Main.java:15: hoge(java.util.ArrayList<java.lang.String>) in Main cannot be applied to (java.lang.Object) hoge(cast(a)); ^ 1 error 1 warning
hoge の引数の型 ArrayList
まとめ
わからない><
わーい \(^o^)/ JS で書ける IRC ボットライブラリできたよー
どうしても IRC ボットを JavaScript で作りたくて
Rhino を勉強したよ!><
で
できたよー\(^o^)/
ダウンロード (CodeRepos だよ)
http://svn.coderepos.org/share/lang/java/jsbot/org/coderepos/botchang/Botchang.java
使い方
- まずここから js.jar (Rhino) を拾ってくる -> http://www.mozilla-japan.org/rhino/download.html
- 次に pircbot.jar (PircBot) を拾ってくる -> PircBot - Java IRC Bot Framework (Java IRC API for Bots)
- 次に これ を org/coderepos/botchang/ ってディレクトリに入れて javac でコンパイルする!
- で、以下みたいな JS のファイルを作る
defineClass('org.coderepos.botchang.Botchang'); // ニックネームとエンコードの名前 var botchang = new Botchang('botchang', 'utf-8'); // verbose (デバッグ用 botchang.verbose = true; // 接続 botchang.connect('irc.freenode.net'); // チャンネルに join する botchang.joinChannel('#1981'); // メッセージハンドラ botchang.onMessage = function(channel, sender, login, hostname, message) { if (message.match(/^botchang/)) { botchang.sendMessage(channel, 'My name is botchang'); } else if (message.match(/^change nick:(.*)$/)) { botchang.nick = RegExp.$1; // dynamic change nick } }; // たとえば、 Notice をハンドリングしたかったら以下のように関数追加 botchang.onNotice = function(channel, sender, login, hostname, notice) { //... };
で、最後に org.mozilla.javascript.tools.shell.Main を java コマンドで実行してこの JS を渡してやるだけ!><*1
java -cp ".:js.jar:pircbot.jar" org.mozilla.javascript.tools.shell.Main sample.js
ちなみに
onMessage や onNotice や sendMessage や nick の変更だけじゃなくて、いろいろできます><
短いからソース読んでみて><
あと、
ぜんぜんテストしてないよー! CodeRepos だからみんなテストとかしてしてー
たのしー
\(^o^)/