恋するプログラムをJavascriptで書いていくことにした

そういえば去年の最終Haskell読書会で、だれかと恋するプログラムの本の話になってYahooの日本語形態素解析API使えば出来んじゃないか?という思考に至ったので、気の向いたときにやっていくことにした。

ProductName 恋するプログラム―Rubyでつくる人工無脳
秋山 智俊
毎日コミュニケーションズ / ?円 ( 2005-04 )


3-3

function Responder(name) {
  this.name = name;
  this.response = function (input) {
    return input + "ってなに?"
  };
}

function Unmo(name) {
  this.name = name;
  this.responder = new Responder('What');
  this.dialogue = function (input) {
    return this.responder.response(input);
  };
  this.responder_name = function () {
    return this.responder.name;
  };
}

var u = new Unmo('proto');
var input = "あれ";

console.log(u.dialogue(input));

復刊リクエストも動いているようなので復刊されるといいですね。

なんでも富士山2011

なにげに初ふじさんメッセ。娘の塗り絵が展示されているというので行ってみた。でも普段はいかないよねー。

1298200849 1298200837

ついでに富士山ひらら

1298200843

去年、吉原祇園祭で食べたものよりは美味しかったけど、ひららの量が少ない。3,4口でなくなる量は如何なものか?けんちん汁に鍋用薄餅が入った感じしかしない。あとは、やたら切れやすくて子供には食べにくそうだった。米系のものだときりたんぽあたりが競合するんだけど、洗練度的にまだまだな気がするなぁ。どっちかというと、鍋投入用の餅と同じような位置づけなのでそっち方面での開発余地はある気がするけどなぁ。

お湯でゆがいて納豆和えるとかもいけそうな気がすんだけどなぁ。まぁ頑張って欲しいところ。

1298200831

おまけ。留守番していたはな。

1298200825

マンションの理事会

今日のマンションの理事会は最終回で決算の説明が主な内容。

ちょうど一年くらい前に簿記の三級を取ったのだけど、貸借対照表がサクサク読めて、疑問点も鋭く質問できて、初めてその効果を実感したのであった。同時に貸借対照表読めてもコスト削減につながらないというかそれはまた別の話だよねと感じたのであった。

例えば去年は消火器の総入れ替えしたけど、相場がどんだけでどこで買えばコストをどんだけ削減できるとかそういう情報は数字からはわからないし、管理会社のほぼ言いなりになった。そういうのは地区の会合で色々情報交換してみないと全然つかめない(先週そういう情報が出てきたのでタイミングが悪かった。)。

マンション理事が任期一年というのはマンション管理会社にとっては扱いやすい仕組みなんだなぁと改めて感心した。任期二年だったら二年目かなり口出すもんな。

それから役員の選出を階ごとに回していくというのが一般的に行われていることだと思うが、役員に前向きでない(地域にあんま関わっていないとか、法人契約で借りているだけとか)戸の対応とか結構悩んだ。ペナルティはあまり効果ないし、理事会出席に報酬を導入するというのもあまり意味が無い。そもそも、出ないのは出ないことによるデメリットがないわけでそういう人達に協調を説いても仕方ないよなぁと。自分もそういう立場だったら、気持よく無視するしなぁ。

今年マンションの理事長になってみて、住民どうしのトラブルとかには遭遇しなかったけど、仕組みとして色々裏側から眺めることが出来たのはかなり勉強になった。マンションに入居したら理事長を経験するのは割と有効なことだと思い知らされた。

大変だったけどねー

出羽の里という酒造好適米

蔵の華は知っているのだけど出羽の里とい酒造好適米があるのね。昨日、東の麓という純米酒を見つけて購入したときに知った。

しかも山形の酒造組合がプッシュするため製作したビデオがあった。

そういえば、東の麓買うときに店主が「ここの純米酒は本醸造(特別本醸造かな?)よりも値段が安いんですよね」と言ってたけど、出羽の里使うとコストが抑えられるってことかな。

杉山フルーツの生ゼリー

二年くらい前に行ったきりだったが、みんなが食べたいと言ったのでまた行ってみた。

そういえば、高糖度トマトを使用した生フルーツゼリーはブログで見かけて気になっていたので購入

1298158599

これは美味かった。トマトなのに砂糖が入ってんじゃないかってくらい甘い。トマト好き兼ゼリー好きの娘と息子にスマッシュヒット。

僕はパッションフルーツを選択。これも酸味が効いていて種のプツプツ感とゼリーの固さが絶妙で美味かった。

1298158615

一方、フルーツミックスは前回同様イマイチ響かなかった。多分、ゼリーと果汁が分離しているのはあんま好みじゃないんだな。娘はゼリーと果実を分離しながらおいしそうに食べてたけど。

次のコミュニティFで勉強会の際にはおやつ候補にあげておこうかな。買えるかどうかわからんけど。

「Javascriptパターン」を読んだ

Perl Best PracticesのJavascript版という位置づけの本かな(でも薄い)

ProductName JavaScriptパターン ―優れたアプリケーションのための作法
Stoyan Stefanov
オライリージャパン / 2940円 ( 2011-02-16 )


まえがきにもこう書いてある

この本は入門書ではありません。Javascriptの技をもう一段上に引き上げたい、そういう開発者やプログラマを想定しています。

Perl Best PracticesとかエキスパートPythonプログラミングを読んでるようなヒトが「Javascriptのお作法ってどうすればいいのかね?」となったときに役立つことが書いてあると思う。

二章にコーディングの作法が載っているでひと通り目を通すと良い感じ。

ちなみに個人的には最近読書会でJavascriptの名前空間ってどう管理すんだよ?という疑問がわいてそのままだったのだけど5章に丁寧に書いてあったのですっきりして良かった。

6章はコンストラクタと継承の話で、これだけに一章を割いている。クラスっぽく書くやり方をクラシカル、プロトタイプベースの継承をモダンって読んで両方紹介してた。

7章はいわゆるデザパタ。GoFのデザインパターンのうちの9つを紹介しているが、この章はあまり興味が持てなかったので流し読みした。

8章はブラウザでのパターンの紹介。

4,5,6章が特に面白く読めた。

JGPは良いJavascriptの文法を学ぼうという本なのに対して、本書は実用的なJavascriptを書くにはどうしたらよいかに対してヒントを与える本かな。

今日の畑(110219)

久々に行ったら雑草が生えてきてたので抜きまくった。あとは牛肥入れて石灰撒いて、ジャガイモを植える準備をしてきた。ちなみに紅あかりを植えることにしたが、娘がコロッケ作りたいって言ってたのが選定の理由。

ソラマメは育ってきた。スナップエンドウ(右)は4株植えてみたけど寒さ対策してなかったので2株しか残ってない。

1298110114 1298110098

春菊はちょっと間引いた。大きくなったらとっとと収穫したい。右はニンニクと春菊

1298110092 1298110108

浅葱も新芽が出てきたので来月辺りから収穫できるようになるかな。

1298110120

JGP 2章の例外処理

JGP読んでてよくわからなかったのが、throwするのはnameとmessageのプロパティを含むオブジェクトリテラルを投げるというところで、

try {
  throw {name:"TestError", message:"oops"}
} catch(e) {
  console.dir(e);
}

のあたり。Errorオブジェクト投げないのはなんでだろか?

var e = new Error("oops");
console.dir(e);

ってやるとnameとmessage(と他に幾つか)のプロパティに値が入ってるから、直接nameにエラーに対応する名前入れるだけでいいじゃんという判断なんだろうか?

そしたらErrorオブジェクトを用意する必要ない気がすんだけど。

ProductName JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス
Douglas Crockford
オライリージャパン / 1890円 ( 2008-12-22 )


なんか深い理由があるんだろうかね。

Javascriptで末尾最適化

元ネタはspencertipping / js-in-ten-minutes

Function.prototype.tail = function () {return [this, arguments]};
Function.prototype.call_with_tco = function () {
  var c = [this, arguments];
  var escape = arguments[arguments.length-1];
  while(c[0] !== escape)
    c = c[0].apply(this, c[1]);
  return escape.apply(this,c[1]);
};

// var sum  = function (n,acc) { return n > 0 ? sum(n-1,acc+n) : acc};
var sum2 = function (n,acc,k) { return n > 0 ? sum2.tail (n-1,acc+n,k) : k.tail (acc);};
var id   = function (x) {return x};
console.log(sum2.call_with_tco(100000,0,id));

これはDelimited Continuationになっているらしい。コードの動きは分かるけど継続とDelimited Continuationの違いが良くわからん。

選曲候補を記録するスクリプトをPythonで書いた

DJ選曲術を読んだり田中フミヤのviaのダイジェストを見たりしてたら、選曲というものが楽しくなってきた。どういう曲のつながりを気持いいと思うかは結局自分をよく知ることになるので意味のある行為ではないかと思う。

で、iTunesで聴いてる曲のつながりを記録するCUIアプリをPythonで書いてみた。単にヘッドとテイルを記録するだけの有向グラフなんだけど、sqliteにぶち込んでいるので後から検索するとき便利だと思う。データが溜まったらチェインをたどりながらplaylistに書きだすようなスクリプトも用意しようかな。

あとは選曲のつながりぐあいをnetworkxとかcytoscape視覚化して見てみたいという個人的な興味もあったりするのでそういうデータが欲しかったりする。

djutil

h(head)を押すとヘッドに現在聴いてるiTunesの曲名が、t(tail)だとテイルに挿入されてヘッドとテイルが揃うとグラフとして追加されるようにしてある。q押すとquitするようにしてあるんだけどquitしないのでなんかおかしい。後でどうにかする

そのうちGitHubで管理する予定

以下コード

#!/usr/bin/python
# -*- encoding:utf-8 -*-

# kzfm <kerolinq@gmail.com>

import curses
import os
from ScriptingBridge import *

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine,Column,Integer,String,ForeignKey,UniqueConstraint
from sqlalchemy.orm import scoped_session,sessionmaker

DATABASE = '/Users/kzfm/djutil.db'
engine = create_engine('sqlite:///'+DATABASE)
Session = scoped_session(sessionmaker(autocommit=False,
                                      autoflush=False,
                                      bind=engine))
Base = declarative_base(bind=engine)

class Music(Base):
    __tablename__ = 'music'
    __table_args__ = (UniqueConstraint('title','artist'),{})
    id = Column(Integer, primary_key=True)
    title  = Column(String(128))
    artist = Column(String(128))

class Graph(Base):
    __tablename__ = 'graph'
    __table_args__ = (UniqueConstraint('head','tail'),{})
    id = Column(Integer, primary_key=True)
    head = Column(Integer, ForeignKey('music.id'))
    tail = Column(Integer, ForeignKey('music.id'))

def main(stdscr):
    if not os.path.isfile(DATABASE):
        Base.metadata.create_all()

    session = Session()

    iTunes = SBApplication.applicationWithBundleIdentifier_("com.apple.iTunes")
    stdscr.nodelay(1)
    head_music = None
    tail_music = None

    while True:
        c = stdscr.getch()
        y,x = stdscr.getyx()
        if c == ord('h'):
            artist = iTunes.currentTrack().artist()
            title  = iTunes.currentTrack().name()
            head_music = session.query(Music).filter(Music.artist == artist) \
                                             .filter(Music.title == title) \
                                             .first()
            if head_music == None:
                head_music = Music(artist=artist,title=title)
                session.add(head_music)
                session.commit()

            if tail_music != None:
                mg = session.query(Graph).filter(Graph.head == head_music.id) \
                                             .filter(Graph.tail == tail_music.id) \
                                             .first()
                if mg == None:
                    mg = Graph(head=head_music.id,tail=tail_music.id)
                    session.add(mg)
                    session.commit()

                stdscr.addstr("%s / %s -> %s / %s" % (head_music.title,head_music.artist,tail_music.title,tail_music.artist))
                stdscr.move(y+1, 0)

                tail_music = None
            else:
                stdscr.addstr("%s / %s -> [] / []" % (head_music.title,head_music.artist))
                stdscr.move(y, 0)

        elif c == ord('t'):
            artist = iTunes.currentTrack().artist()
            title  = iTunes.currentTrack().name()
            tail_music = session.query(Music).filter(Music.artist == artist) \
                                .filter(Music.title == title) \
                                .first()

            if tail_music == None:
                tail_music = Music(artist=artist,title=title)
                session.add(tail_music)
                session.commit()

            if head_music != None:
                mg = session.query(Graph).filter(Graph.head == head_music.id) \
                                             .filter(Graph.tail == tail_music.id) \
                                             .first()
                if mg == None:
                    mg = Graph(head=head_music.id,tail=tail_music.id)
                    session.add(mg)
                    session.commit()

                stdscr.addstr("%s / %s -> %s / %s" % (head_music.title,head_music.artist,tail_music.title,tail_music.artist))
                stdscr.move(y+1, 0)
                tail_music = None

            else:
                stdscr.addstr("[] / [] -> %s / %s" % (tail_music.title,tail_music.artist))
                stdscr.move(y, 0)
        elif c == ord('q'):
            exit
        elif c != -1:
            # debug
            stdscr.addstr(str(c))
            stdscr.refresh()
            stdscr.move(0, 0)

if __name__ == '__main__':
    curses.wrapper(main)