2011/12/01

Project Lambda

このエントリーをはてなブックマークに追加

このエントリは Java Advent Calendar 2011 の一環で、第 1 日目のエントリーです。

やっぱり、櫻庭といえば Java SE の新しいところでしょう (これ去年も書いたなぁ ^ ^;;)。ということで、Java SE 8 の目玉機能となっている Project Lambda を取りあげます。

結果的に超長文になってしまいましたww

 

厳密にいえば、Lambda はクロージャではありません。

追記: ここでいっているクロージャはレキシカルスコープが使用できる無名関数のことを意味しています。 (るとさん、コメントありがとうございました)

 

では、ラムダ式とはなんなのか?

それはタスクを簡単に書くことを目的とした、単一メソッドのインタフェースのインスタンス生成を簡単に書くための簡易記法です。ようするにシンタックスシュガーでしかありません。

ここでいうタスクは、特にパラレルに処理するタスクのことです。

今年の 7 月から 9 月まで Java SE 7 のラウンチイベントで、いろいろなところで Fork/Join Framework の講演をさせていただいたのですが、この Fork/Join Framework は Project Lambda と深い関係をもっています。

というのも、Project Lambda ができたのは Fork/Join Framework 抜きでは語れないからです。つまり、Fork/Join Framework で処理するタスクを Project Lambda を使って簡単に書きましょうというのが、本来の目的であるからです。

ここらへんのことは、ITpro の Java 技術最前線などで何度か書いてきたのですが、もう一度まとめてみましょう。

Project Lambda 小史

櫻庭が知りうる限り、Java へのクロージャの導入について公に発言されたのは、2005 年の JavaOne の Technical General Session です。

この当時、Technical General Session で Java SE を担当していたのが Graham Hamilton です。

この時は、まだ Java SE 6 もリリースされていない頃です。じゃあ、なんで Java SE 7 の話をしたかというと、もともと Java SE 6 と Java SE 7 は一緒に仕様が検討されて、導入が簡単な機能を Java SE 6、大変なものを Java SE 7 にするということだったのです。

で、Graham Hamilton が Java SE 7 に導入するといって列挙したキーワードはクロージャ、friend (その後、Project Jigsaw に続きます)、XML リテラル (完全に抹殺されてしまいました) などです。

これを受けて、クロージャの仕様を提案したのが、Neal Gafter を中心にした Gilad Bracha、James Gosling、Peter van der Ahé のグループ。これが 2006 年のことです。

彼らの提案は、彼らの頭文字を取って BGGA と呼ばれていました。まだ、その提案は彼らのサイトで見ることができます。

この提案はレキシカルスコープを含んだ、本当の意味でのクロージャです。

これが大議論に発展してしまったのです。いわゆる炎上です。クロージャ導入に賛成のグループと反対のグループが真っ向から対抗してしまいました。

賛成派の急先鋒は、BGGA の Neal Gafter。これに対して反対派の急先鋒は Joshua Bloch。

この 2 人は知っている人は知っている、Java Puzzlers のコンビで大の仲良し。ところが、このクロージャ論議で仲違いしてしまったほど、議論が伯仲してしまったのです。

Joshua Bloch と Doug Lea、Bob Lee は BGGA に対抗してクロージャを使わない CICE を提案しています。後から考えると、CICE が提案してる内容がいちばん Project Lambda に近いですね。

また、これとは別に Stephen Colebourne らが FCM を提案しています。

このようにクロージャの提案に関して群雄割拠の状況になってしまって、まったく収集がつかなくなってしまいました。

そして、2008 年の 11 月の Devoxx 2008 において、Mark Reinhold がクロージャは見送る宣言をしてしまいました。ようするに誰もこの議論をまとめられなくなってしまったのだと思います。

ところが、ところが、次の年の Devoxx において、再び Mark Reinhold が Project Lambda を立ち上げると宣言したのです!!

なぜ、1 年で状況が変わってしまったのか。その理由がマルチコアの CPU の台頭なのです。

たくさんのコアがある状況で、性能をあげるには、すべてのコアを遊ばせないようにしなくてはなりません。Java で複数のコアを動作させるのに使うのは Thread です。でも、Thread をそのまま使うというのはありえません。通常は Concurrency Utilities で提供されているスレッドプールを使います。

ところが、Concurrency Utilities で想定されているタスクは粒度が大きいのです。たとえば、トランザクションの単位でタスクを割り振るとかですね。

粒度が大きいタスクで問題になるのは、同期が発生した場合や、競合が発生した場合です。たとえば、とあるオブジェクトをロックすると他のスレッドからは使えません。ロックが外れるまで他のスレッドは待たなくてはいけません。つまり、他のスレッドはロックが外れるまで遊んでしまうわけです。

なので、粒度の小さいタスクにして、同期のコストがなるべく小さくなるようにする必要があります。

だったら、Concurrency Utilities で粒度の小さいタスクを書けばいいと思いますが、残念ながらそれだとオーバーヘッドが非常に大きくなってしまうのです。

つまり、粒度の小さいタスクを扱うには、それ専用のフレームワークが必要になるわけです。それが JSR 166y の Fork/Join Framework です。

これで粒度の小さいタスクを書く準備はできました。バリバリとタスクを書いていきましょう。.... と思ったのですが、なかなかことはそううまく運びません。

Java でタスクを書くとしたら、インタフェースを定義して、無名クラスで記述するのが一番多いやり方だと思います。たとえば、イベント処理なんかがそうですね。こういうやつです。

        JButton button = new JButton("OK");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // イベント処理
                update();
            }
        });

でも、よく考えてみると実際に書きたい部分は update メソッドをコールする部分だけです。

なのに、無名クラスの定義やら、メソッドのオーバーライドやら無駄なものがいっぱい。

しかも、汎用のタスクを書けるようにしたら、シグネチャが異なるメソッドをいっぱいオーバーロードしなくてはいけません。たとえば、JSR 166y のおまけともいうべき extra166y で提供している ParallelArray クラスは、内部イテレーターでタスクをパラレルに処理できます (これについては後でまた書きます)。

ParallelArray クラスで処理するタスクは Ops クラスで定義しているインタフェースで書くのですが、int やら double やらの引数を変えたシグネチャの op メソッドを用意するため、なんと 100 種類以上もあります。

これらのインタフェースの種類を覚えるのも難儀ですよね。

で、もっとタスクを簡単に書けるようにしましょうというのが、Project Lambda の発端なわけです。

BGGA などそれまでの提案は、Java にクロージャを導入するということが目的になっていました。なので、議論がまとまらなくなってしまったわけです。

それに対して、Project Lambda の目的はクロージャを導入することではないのです。あくまでも、タスクを簡単に書けるようにしましょうというのが目的です。

その目的のために必要なことを検討していくということにしたために、やっと議論がまとまったわけです。

 

しかし、Project Lambda もあっさりと仕様が決まったわけではないです (実際、まだ最終決定はされていないです)。

Project Lambda の発足時に Mark Reinhold が Straw-Man Proposal という提案を行っています (Straw-Man というのはかかしのことですけど、たたき台的な意味で使われるようです)。

Straw-Man Proposal では

  • 関数形の導入
  • レキシカルスコープは検討していく (アノテーションを使って指定する)

ことを提案しています。

しかし、この後、レキシカルスコープはすぐに却下されてしまいました。そして、関数形も却下し、無名クラスのインスタンス生成を簡単に書く記法に落ち着いたのです。

記法も二転三転しています。

ここらへんの議論に関しては DeveloperWorkds での Brian Goetz のアーティクルが参考になります。

ということで、Project Lambda はクロージャではなくなったのです。

しかし、Project Lambda の目的を考えると、現在の仕様は妥当であると櫻庭は思っています。

ちなみに、Joshua Bloch と Neal Gafter ですが、Project Lambda の立ち上げ後、仲直りしたらしいです。とはいっても、その後 Java Puzzlers で 2 人の "Click and Hack, the Type-It Brothers" は復活していないのですが...

Project Lambda のインストール

Java SE 8 は OpenJDK において、毎週ビルドが公開されています。しかし、現状のビルド (2011/12/1 現在で build 14) では Project Lambda のソースはまだ取り込まれていません。

とはいうものの、Project Lambda がまったく実装されていないというわけではなく、ちゃんと実装が進んでいます。

最近になって、Lambda の評価用に JDK 7 に Project Lambda を組み込んだパッケージが公開されました。今回はこれを使って、Lambda を試してみたいと思います。

 

 

このサイトからダウンロードできるファイルにはインストーラはなく、単なる ZIP or tar.gz ファイルだけです。なので、適当なディレクトリで展開します。展開すると、JDK と同じディレクトリに構成になります。後は、普通の JDK の使い方と同じです。

ところが、残念なことに、これには ParallelArray クラスや Iterable インタフェースのパラレル処理版の Spliterable インタフェースは含まれていません。なので、一番の目的のパラレル処理を簡単に書くというところは検証できないのです。ちょっと残念ですね。

Project Lambda の仕様

Project Lambda というと、どうしても Lambda 式ばかり注目されてしまいますが、実をいうと Project Lambda の構成要素は Lambda 式以外もあります。

Project Lambda では次の 3 項目について仕様策定を行っています。

  • Lambda 式
  • メソッド参照
  • インタフェースのデフォルト実装

また、この 3 つには含まれませんが、重要な概念として Functional Interface があります。ということで、まず Functional Interface から説明します。

Functional Interface は簡単にいえば 1 つしかメソッドが定義されていないインタフェースのことです。以前は SAM (Single Abstract Method) インタフェースと呼ばれていましたが、現在は Functional Interface と呼ばれています。

たとえば、次のようなインタフェースが Functional Interface です。

interface FileFilter { boolean accept(File x); }

interface Runnable { void run(); }

interface Callable<T> { T call(); }

interface ActionListener { void actionPerformed(ActionEvent event); }

これらの Functional Interface のインスタンス生成を行うのが Lambda 式です。

Lambda 式

さて、一番重要な Lambda 式です。

定義云々はとりあえずおいておいて、先ほどの

        JButton button = new JButton("OK");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // イベント処理
                update();
            }
        });

を Lambda 式で書いてみましょう。

        button.addActionListener( (ActionEvent e) -> update() );

とっても簡単になりました。すばらしい!!

でも、もっと簡単になります。

        button.addActionListener( e -> update() );

静的型付けの Java なのに、関数の引数の型が省略できるのです!!

といっても、動的に型付けを行うのではなく、コンパイル時に型を推論して適切な型を割りふっています。これは Project Coin のダイヤモンド演算子と同じような感じです。

だいたいお分かりだと思いますが、Lambda 式は次のように定義できます。

        (引数1, 引数2, 引数3...) -> メソッド本体

以前はカッコが必要だったり、# が必要だったりしていましたが、現在は () -> だけで Lambda 式を表します。

もちろん、引数の型を書くこともできます。

        (引数1の型 引数1, 引数2の型 引数2, 引数3の型 引数3...) -> メソッド本体

型は省略できるので、あえて書く人は少ないと思いますが...

ちなみに、引数が 1 つの場合はカッコも省略できます。先ほどの ActionListener インタフェースの場合がそうですね。

では、もう少し例をあげてみましょう。

Swing でよく使うあんなコードも...

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame();
                    ...
                frame.setVisible(true);
            }
        });

こうなります。

        SwingUtilities.invokeLater( () -> {
            JFrame frame = new JFrame();
                ...
            frame.setVisible(true);
        });

すごいすっきりしました。なお、引数が 1 つの時はカッコが省略できましたが、引数がない場合はカッコは省略できません。

戻り値がある場合、式が 1 文であれば return は省略できます。1 文以上であれば return を書かなくてはいけません。ここら辺はちょっとやぼったいかも。

        Callable<Boolean> callable1 = () -> true;
 
        Callable<Boolean> callable2 = () -> {
            System.out.println("Call call()");             
            return false;
        };
 
        ExecutorService service = Executors.newFixedThreadPool(2);
        Future<Boolean> future1 = service.submit(callable1);
        Future<Boolean> future2 = service.submit(callable2);
 
        System.out.println("Callable1 result: " + future1.get()
                           + " Callable2 result: " + future2.get());

これを実行すると...

C:\lambda>java CallableTest
Call call()
Callable1 result: true Callable2 result: false

となります。

Functional Interface のメソッドをコールすることもできます。その時は、もともとインタフェースで定義されていたメソッド名でコールします。ここらへんも、普通のクロージャとは感覚が違いますね。

    interface Hello {
        public void sayHello();
    }
 
    public static void main(String[] args) throws Exception {
        Hello hello = () -> System.out.println("Hello, World!");
        hello.sayHello();
    }

実行すると、Hello, World! が出力されます。

このように、Lambda 式を使うととても簡単に記述できるようになります。まぁ、他の言語では当たり前かもしれませんが、Java では画期的ですwww

ところが、よく分らない部分もいくつかあって、その代表的なのが Comparator インタフェース。

Comparator インタフェースは compare メソッドと equals メソッドの 2 つのメソッドを定義しているのですが、なんと Lambda 式で書けてしまいます。Functional Interface の定義とは違うと思うんだけどなぁ...

        // Comparator を Lambda 式で生成
        Comparator<Integer> comparator = (x, y) -> x - y;
 
        System.out.println(comparator.compare(10, 12));
 
        // リストのソートに Comparator を使用する
        List<Integer> nums = Arrays.asList(10, 20, 8, 4, 30);
        Collections.sort(nums, comparator);
        System.out.println(nums);

これを実行するとこうなります。

C:\lambda>java CompTest
-2
[4, 8, 10, 20, 30]

というように、compare メソッドの本体が x - y になっています。どうなっているんだろう?

メソッド参照

つづいて、メソッド参照 (Method Reference)。関数型ではなくて、あくまでもメソッドに対する参照です。といってもたいした使い方ができるわけではありません。

たとえば、FileFilterインタフェースで読み取り専用のファイルをフィルタリングすることを考えます。すると、次のように何種類かの書き方ができます。

        // 読み取り専用のファイルだけをフィルタリングする
        FileFilter filter = new FileFilter() {
            public boolean accept(File f) {
                return f.canRead();
            }
        };

        FileFilter filter2 = (File f) -> f.canRead();

        FileFilter filter3 = f -> f.canRead();

        FileFilter filter4 = File#canRead;

最後の赤字の部分がメソッド参照を利用した書き方です。ようするに引数のメソッドを呼び出すだけの Lambda 式であれば、メソッドを指定するだけでいいということです。

ところが、まだ現状ではこのメソッド参照は実装されていないようです。

追記: Twitter で @bitter_fox さんから File::canReadの型式ではなく、File#canRead の型式でメソッド参照が実装されていると教えていただきました。ありがとうございます。

 

インタフェースのデフォルト実装

ここまで Lambda 式の書き方をいろいろと紹介してきましたが、本命の使い方はまだ紹介していません。

本命とはパラレルに処理するタスクを書くということです。ここでパラレルに処理するタスクとして、一番重要視されているのがループです。

しかし、普通に for 文などでループを書いても、それをパラレルにするのは難しいです。じゃあどうするかというと、内部イテレータを使用します。

内部イテレータは Ruby などの言語で採用されているので、知っている人は知っていると思いますが...

たとえば、コレクションの要素を 2 倍にしたコレクションを作成する場合を考えてみます。

Java の場合
  
    List<Integer> nums = Arrays.asList(0, 1, 2, 3, 4);
    List<Integer> nums2 = new ArrayList<Integer>();
    
    for (Integer num: nums) {
        nums2.add(num * 2);
    }

Groovy の場合

    def nums = [0, 1, 2, 3, 4]
    
    nums = nums.collect { it * 2 }

Groovy での赤で書いた部分がクロージャです。つまり、collect メソッドの引数にクロージャを渡していることになります。

重要なことはこのクロージャがループの中で独立になっているということです。他に依存していないので、この部分はパラレルに処理するのが簡単ということになります。

逆に Java の方は独立かどうかを判断するのが難しいです。

ということで、Java SE 8 からは Java でもコレクションに対して内部イテレータで処理できるようになります。

Oracle の人たちがよく出す例として、2011 年に卒業した人の成績の最大値を出すというのがあります。

今までの Java で普通に書くと、次のようになります。

        class Student {
            public String name;
            public int gradYear;
            public int score;
        }
 
        List<Student> students = ...;
         
        int highestScore = 0;
 
        for (Student s: students) {
            if (s.gradYear == 2011) {
                if (s.score > highestScore) {
                    highestScore = s.score;
                }
            }
        }

これを内部イテレータで記述してみます。

        int highestScore
            = students.filter(new Predicate<Student>() {
                public boolean eval(Student s) {
                    return s.gradYear == 2011;
                }
            }).map(new Mapper<Student, Integer>() {
                public Integer map(Student s) {
                    return s.score;
                }
             }).reduce(0, new Operator<Integer>() {
                public Integer eval(Integer left, Integer right) {
                    return Math.max(left, right);
                }
             });

filter メソッドや map メソッドなど、見慣れないメソッドが登場しました。

filter メソッドはコレクションの要素のフィルタリングをするメソッドです。引数の Predicate オブジェクトの eval メソッドの戻り値が true の要素だけをフィルタリングします。

map メソッドは新しいコレクションを作り直すメソッドです。Mapper オブジェクトの map メソッドの戻り値を新たな要素としたコレクションを作ります。reduce メソッドは要素を減らして、最終的に 1 つにするためのメソッドです。

といっていますが、実際には filter メソッドも map メソッドも戻り値は Iterable インタフェースですがww

ちなみに、Predicate インタフェースや Mapper インタフェースは java.util.functions パッケージで提供されています。

では、これを Lambda 式で書きかえてみます。

        int highestScore
            = students.filter( s -> s.gradYear == 2011 )
                      .map( s -> s.score )
                      .reduce(0, (left, right) -> Math.max(left, right));

はじめの for 文と if 文で書いていたのにくらべ、すごくスッキリしました。しかも、分りやすい。

では実行してみましょう。適当な Student オブジェクトを作って、実行すると次のようになりました。

C:\lambda>java IteratorTest
98

ちなみに reduce メソッドの Lambda 式をメソッド参照を使用して書くこともできます。

次に、これをパラレルに行うにはどうすればいいか。それもすごい簡単です。

        int highestScore
             = students.parallel()
                       .filter( s -> s.gradYear == 2011 )
                       .map( s -> s.score )
                       .reduce(0, (left, right) -> Math.max(left, right));

なんと、赤字で書いたように parallel メソッドを間に挟むだけです。ここではこれ以上触れませんが、機会があればここらへんもまた紹介したいとお思います。

さて、こういうようにコレクションに対するイテレーションを Lambda 式で書けることは分りました。しかし、問題はすべてのコレクションに filter メソッドや map メソッドを付け加えなければいけないということです。

しかし、たとえば Iterable インタフェースに filter メソッドや map メソッドを追加してしまったらどうなるでしょう。

インタフェースを実装するクラスは、インタフェースで定義したメソッドは必ず定義しなくてはなりません (もちろん抽象クラスは違います)。ということは、安易に Iterable インタフェースに filter メソッドなどを追加してしまうと、非常に多くのクラスが影響を受けてしまいます。

もちろん、自作のクラスもこの影響を逃れえません。

つまり、昔のソースをコンパイルし直したら、エラーだらけということになってしまうかもしれないのです。

しかし、これは Java のコンセプトとは食い違います。Java の一番重要なコンセプトは Compatibility is King です。コンパチビリティが常に優先されます。

しかし、Iterable インタフェースにメソッドを追加したら、これが壊れてしまうわけです。

では、どうするか?

その答えが、インタフェースのデフォルト実装です。

インタフェースの実装クラスが、インタフェースで定義したメソッドを実装していない場合、デフォルト実装が使われることになります。

デフォルト実装をどのように記述するかは、実際のコードを見てみましょう。Project Lambda を含んだ JDK にも src.zip が提供されており、それを解凍すると Iterable インタフェースなどを見ることができます。

以下に Iterable インタフェースを示します (コメントは省略しました)。

public interface Iterable<T> {
    Iterator<T> iterator();

    boolean isEmpty() 
        default Iterables.isEmpty;
        
    Iterable<T> filter(Predicate<? super T> predicate) 
        default Iterables.filter;
        
    Iterable<T> forEach(Block<? super T> block) 
        default Iterables.forEach;
        
    <U> Iterable<U> map(Mapper<? super T, ? extends U> mapper) 
        default Iterables.map;
        
 
         <<以下、省略>>        
}

赤で示したように、メソッドの定義の後に default を記述し、その後にデフォルトで使用するメソッドを記述します。ただし、ここで指定できるメソッドは static メソッドだけです。

ちなみに、デフォルト実装で使用している Iterables クラスも Java SE 8 で導入されたクラスで、java.util パッケージにあります。

このようにデフォルト実装を導入することで、既存のソースコードに影響を与えずに、インタフェースに機能を追加することができるのです。

終わりに

とても長くなってしまったのですが、最後にまとめておきます。

Project Lambda が仕様が決まるまで非常に長い道のりがありました。ここに来てやっと、仕様がまとまってきたのは、目的がキチンと決まっていることです。

その目的をもう一度書いておくと

パラレルに処理するタスクを、簡単に記述すること

です。

そのために、取った導入した手段が

Functional Interfaceのインスタンス生成を簡単に記述する Lambda 式

です。

これ以外に、次の機能も導入しています。

  • メソッド参照
  • インタフェースのデフォルト実装

クロージャをもとめていた人にとっては Project Lambda はものたりないものかもしれません。しかし、Project Lambda の本来の目的と、そして Compatibility is King という Java コンセプトを考え合わせると、現在の Project Lambda の仕様は妥当であると感じています。

(個人的には Straw-Man Proposal から関数型が抜けた時は残念に思いましたけど ^ ^;;)

そして、使ってみると分るのですが、意外に使えます。ぜひ、使ってみてください。

ちなみに、Java SE 9 以降で関数型復活という噂もあるので、Java SE 8 で Project Lambda が完結するのではなく、9, 10 と機能の向上を続けていくのだと思います。

しかし、どうしてもクロージャを使いたいというのであれば、JRuby なり Groovy なり Scala なりを使えばいいと思いますww

今日の一枚

このエントリーをはてなブックマークに追加

Kenny Burrell "Have Yourself a Soulful Little Christmas" (1966)

今年も 12 月はクリスマスアルバムです。

1 枚目はKenny Burrell の定番アルバム。櫻庭は Jazz ギターはあまり聞かないというか、ほとんど聞かないのですが、これはいいですよ。

ちょうど 60 年代の Chicago で録音されたので、シカゴブルースやソウルが出てきたころと重なるわけです。そういうにおいがしてきますね。タイトルからして Soulful だし。

そして、Jazz の醍醐味といえばインプロビゼーション。1 曲目の The Little Drummer Boy から、アドリブをばんばん聞かせてくれます。それをサポートするホーンもカッコいい。

Jazz の定番でもある My Favorite Things が一番かな。アップテンポの曲の方が Kenny Burrell のギターが活きてくるように感じます。惜しむらくは曲が短い。3 分半は短いですよ。10 分ぐらいやってくれないかなぁ。

2011/10/09

Sears' Fine Food

このエントリーをはてなブックマークに追加
Sears' World Famous 18 Swedish Pancakes, Sears' Fine Food, San Francisco

San Francisco に来ると毎回 1 度は来ている Sears' Fine Food です。もちろん朝ご飯。なので、ゆっくり朝ご飯を食べられる JavaOne 前か、会期後が多いですね。

今年も最終日にやってきました。

もちろん、スエーデン風パンケーキです。

でも、年々クオリティが落ちているような気がするのは気のせい? 来年はもういいかな。


Sears' Fine Food, San Francisco

Sears' World Famous 18 Swedish Pancakes, Sears' Fine Food, San Francisco

Firewood Cafe

このエントリーをはてなブックマークに追加
Cheese Burger, Firewood Café , San Francisco International Airport

長いようで短かった San Francisco 滞在も今日でおしまい。

空港で微妙におなかが減ってきたので、Firewood Cafe で腹ごしらえ。

チーズバーガーを食べてみたのですが、まぁ普通かな。空港内なので、そんなものかもしれません。

オーダーしたのはいいのですが、なかなか出てこない。かなり待ってしまいました。そうしたら、食べている最中に、最終登場案内の後、アナウンスで呼ばれてしまいました ^ ^;;

大急ぎで食べて、ゲートへ。何とか間に合ったのでよかった。


Firewood Café , San Francisco International Airport

Cheese Burger, Firewood Café , San Francisco International Airport

帰国

このエントリーをはてなブックマークに追加
Deep Blue

帰りも、もちろんデルタ。通路側がとれなかったので、帰りも窓側。でも、それはそれで楽しかったです。子供のようにずっと窓から外を見てました。

ごはんはあいかわらずおいしくない。去年はピザが出ましたけど、今年はラップサンド。斬新だ。タイスタイルと書かれているのですが、あまりタイっぽくはないです ><

というわけで、帰国しました。


Airline Meal, Delta Airline

Airline Meal, Delta Airline

Thai Style Vegetable Hot, Posh Wraps, Airline Meal, Delta Airline

Thai Style Vegetable Hot, Posh Wraps, Airline Meal, Delta Airline

JavaOne 2011 San Francisco まとめ

このエントリーをはてなブックマークに追加
Duke, Open House, JavaOne 2011 San Francisco

JavaOne 2011 の最後のエントリーなので、今年の JavaOne をまとめてみようと思います。

今年は去年に比べて、OOW と JavaOne がかなり切り離された感じです。でも、やっぱり同じ時に開催するのは間違っていると思っています。特に会場の問題はいかんともしがたいところです。

ホテルの部屋で一番問題なのは、天井が低いこと。

天井が低いので、プロジェクターのスクリーンも低くならざるをえません。そのため、少し後ろに座ってしまうと、スクリーンの下の方は全然見えません。

特に Hilton の Yosemite は広い部屋なのに、部屋の前方に梁があるため、なおさらスクリーンが低くなってしまいます。なので、一番後ろからだと、スクリーンの半分は見えません。これはひどすぎ。

BOF で少人数しかいないのであればともかく、ホテルでセッションをするのはダメですね。

ホテルでやるとしても Marriot のように天井が高い部屋がちゃんと用意してあればいいのですが....

後でも書きますが、プロジェクターの輝度が低くて見えづらいのも問題だと思っています。ほんと今回はプロジェクターに関する問題が多かったです。

プロジェクターがそういう状況であるのに、スクリーンに投影される字が小さすぎ。今回は特に字が小さいように感じます。

JavaOne はセッション資料のテンプレートがあるのですから、最小文字ポイントをちゃんと決めておいてほしかったと思います。

ここまでは主催側の問題ですが、プレゼンターにも問題があると思っています。

今年はセッション数が去年に比べて倍増したのですが、プレゼンターの質がそれに追いついていない感じです。特に JavaFX のセッションにそれを感じました。もうちょっとどうにかならないのかなぁ。

なんのための技術なのか、どういうところを狙っているのか、これが実現されると何がうれしいのかなどの話もなく、いきなり細かい話になってしまうセッションの多いこと、多いこと。ほんとにそれで聞いている人が理解できるのか、興味を持ってくれるのかなんてことをまったく考えていないと思われるセッションがいっぱいあります。

私が聞いたのはほとんど Oracle の人のセッションだったので、それが目立っていたのかもしれません。でも、Brian Goetz など去年まではセッションを持っていた大御所的な人たちのセッションがなくなってしまっているのも確かです。

若い人が出てきてはいけないというわけではありません。でも、JavaOne には世界中からデベロッパーが最新の情報を求めて集まるのですから、セッションを担当するのであればそれなりのプレゼンターの資質や準備が必要だと思っています。

もう 1 点。

Keynote の順番は絶対に間違っています。

Strategy を先にやらないで、Technical Keynote で各論を説明することに何の意味があるのでしょうか。

みなが興味ある Java SE とかはいいのですが、Tech Keynote の Java ME はかわいそうになるぐらい人が帰ってしまっていました。でも、次の日の Strategy Keynote の CDC と Java SE Embedded を統合するという話を聞いていれば、もっと多くの人が興味を持ってくれたはずです。

Tech Keynote のスピーカーも肝心なところはしゃべれないので、とてもやりにくかったと思います。

この順番は来年は絶対にやめてもらいたいです。

 

これ以外に、今年はとてもコストカットが目立った JavaOne でした。

コストカットされたところをあげてみましょう。

  • パンフレットがペラペラ
  • Mason Street にテントがなく、パラソルのみ
  • Keynote 会場のプロジェクターが連結式から、単独式 × 2 になった
  • 朝食がベーグルのみ
  • セッションのプロジェクターが安いものに変更され、そのために輝度不足が目立つ
  • コーヒや飲み物の提供がほとんどなし
  • Candy Bar が貧弱
  • Candy Bar 以外のお菓子も減った
  • ライブの人選が小粒になった。去年の Black Eyed Peas は現役バリバリだが、今年の Sting、Tome Petty は過去の人になりつつある
  • ライブの時の遊ぶところが狭くなったらしい
  • ライブの時に去年はアトラクションがいろいろあったのだが、今年は観覧車だけ

こうやってあげてみましたけど、櫻庭は一概にコストカットが悪いとは思っていません。パンフレットや食べるものが貧弱になったとしても全然かまわないと思います。

ただし、コストカットが JavaOne のクオリティを下げるようなことになっている場合は問題だと思います。なので、コストカットで問題なのはプロジェクターが安物になってしまったということだけです。

ご飯の提供がなくなったり、Mason St. を封鎖しなくなったとしてもいいんです。ただ、投影される資料が見にくくなるのは困るわけです。

 

また、今年の JavaOne に参加した上での要望としては、

  • 資料の公開。できれば BOF の資料も。これ書いている時にはすでに公開されているものもあるのですが、全部ではないのです。ちなみに去年の資料が見られないんですが....
  • セッションのムービーの公開。昔はムービーも公開していたんですけどねぇ... 資料に Demo とか書いてあるだけだと、悲しいです
  • セッション会場にテーブルが欲しい....
  • WiFiの強化。特に Hilton は最悪でした
  • 朝食を出すのであれば、朝一のセッションの前から
  • 天井が高い会場

 

なんか文句ばかりになってしまいそうなので、よかった点も上げておきます。

  • 話題ごとに部屋が決まっている。JavaFX は Nikko、Core Java だと Hilton など。これによって移動の時間がかなり減りました
  • ライブの時に、毛布とポンチョの配布。そんなことかといわれそうですが、これは大事です

 

そういえば、今年は JavaOne のテーマ音楽をとうとう聴かなくなってしまいました。

 

さて、JavaOne はこれくらいにして、サンフランシスコの街に関して。

今年は廃業してしまった店を多く見ました。やはり不況なのでしょうか。Westfield の中でも Cocola Bakery や Zazil も廃業していますし、その他にも店が入っていないところがいっぱいあります。元気なのはファストファッション系だけのような気がします。

個人的には本屋の Borders がなくなっていたのがいたかったです。Borders がなくなると、ダウンタウンには本屋が全然ないのです。Amazon が 1 人勝ちなんですかねぇ.....

そういえば、数年前に Disney Store がつぶれてしまったのですが、今年復活していました。その復活していた場所は、去年まで Sanrio があった場所。Sanrio も苦しかったんですかねぇ。

それはそうと、San Francisco のダウンタウンはいろんなところを掘り返しているようです。ケーブルカーが通る Powell St. は歩道が広くなってテーブルみたいなのが設置されていました。

近くには太陽電池も設置されています。スポンサーは Audi みたいですね。

渋谷の公園通りもそうでしたけど、Powell St. は違法駐車がとても多かったのですが、歩道を増やして車を止まれないようにしたのではないかと思います。

真相はなぞですけど。


Construction Work

いたる所で工事中

Sidewalk

追加された歩道

Sidewalk

テーブル?

Solar Cell

Audi のマークが!!

2011/10/08

Charley's Grilled Subs

このエントリーをはてなブックマークに追加

日経ソフトウエアの JavaOne のレポート記事を書いていたら、あっという間に夜中の 3 時。それから寝て、起きたらお昼近く。昨日の自転車の疲れもあって、体はだるいです。

元気があれば、科学アカデミーに行こうと思っていたのですが、去年に引き続き、今年もいけず。来年こそリベンジしよう!!

それはそうと、とりあえず何かを食べに行かないと。しかし、昨日肉とサンデーをあれだけ食べたので、それほどおなかは減っていません。

軽く食べるということで、Westfield の地下のフードコートにある Charley's Grilled Subs でチーズステーキ。日本でチーズステーキというかサブって食べたことないんですけど、いいと思うんですけどねぇ。

その後、Yerba Buena Garden で休憩。今日もフリートウィークがあって、ブルーインパルスが飛んでましたよ。写真は撮らなかったですけど。


Philly Cheesesteak, Charley's Grilled Subs, Westfield San Francisco Centre

Philly Cheesesteak, Charley's Grilled Subs, Westfield San Francisco Centre

Ame Restaurant

このエントリーをはてなブックマークに追加
Ame Restaurant, San Francisco

今年の JavaOne というか Oracle OpenWorld で最も名をあげたレストランといえば、St. Regis にある Ame

OpenWorld で Keynote をする予定だった SaleseForce の Mark Benioff が、勝手に Keynote をキャンセルさせられてしまって、その代わりにプライベートな講演をしたのが Ame だったのです。

前から一度いってみたいと思っていたので、予約を取って、いってみることにしました。

ところで、Ame というのはエイメと発音するのだとばかり思っていましたが、なんと「アメ」と発音するのだと。しかも、アメというのは雨のことだというではないですか。St Regis の日本語のページに雨と書いてあったので、てっきり自動翻訳をしたのがそのままになっているのかと思っていたのですが、本当に雨のことだったとは。

雨という名前の通り、日本のテイストをかなり取り入れたフレンチです。

今回はコースの A Taste of Ame をいただくことにしました。

前菜は刺身。魚のカルパッチョとかではなく、ほんとにメニューに Sashimi とあります。サービスの人がこれが鯛で、これが鮪といっているのが、すごいへんな感じww

とはいっても、刺身がそのままではなく、やはりカルパッチョ風にドレッシングなどで和えてあるものですが、それはそれでおいしい。

スープはキャロットジンジャースープ。バジルオイルが浮いているのですが、その香りがいいですね。見た目とは違い、かなりあっさりとしたスープです。

魚は鱈を焼いたものに酒をベースとしたソースでマリネしたもの。Sake Marinated Cod とあるのですが、酒だけでなく醤油がきいた味。これはすごい和食っぽいです。この鱈も油も全然感じさせず、すごいあっさり。

そして、肉料理は子牛のテンダーロイン。といってもステーキではなく、真空調理のような感じ。これはこれでおいしいのですが、やっぱりあっさり。なんかフレンチを食べた気が全然しません。

和食だとここでごはんが出てきますけど、フレンチなので後はデザートだけ。1 つ 1 つはおいしいんだけど、全体的にあっさりしすぎていて、物足りない感じです。

Three Preparations of Sashimi, A Taste of Ame, Ame Restaurant, San Francisco

Three Preparations of Sashimi, A Taste of Ame, Ame Restaurant, San Francisco

Three Preparations of Sashimi, A Taste of Ame, Ame Restaurant, San Francisco
A Taste of Ame, Ame Restaurant, San Francisco

Broiled Sake Marinated Alaska Black Cod in Shiso Broth, A Taste of Ame, Ame Restaurant, San Francisco

Sofrito Encrusted Veal Tenderloin, A Taste of Ame, Ame Restaurant, San Francisco
Sofrito Encrusted Veal Tenderloin, A Taste of Ame, Ame Restaurant, San Francisco

デザートはハイビスカスのバシュラン。アイスクリームにメレンゲを焼いたものが乗ってきます。でも、これはイマイチ。もうちょっとがんばってほしいなぁ。

ところで、料理はさておき、ここの店のドレスコードがよく分からんのです。OpenTable には Fine Dining と書いてあるし、Yelp にも Dressy と書いてあるのに、結構ジーンズでラフなかっこうのお客さんも多いのです。もちろん、スーツをびしっと決めている人もいるのですが。さて、どちらが正解なのかなぁ。

ついでのついで。昨日の The Spinnaker はサービスの人がクリントイーストウッドに似ていたのですが、今日の担当してくれた人はジャックニコルソンにすごい似ています。なんか偶然にしては、できすぎのような気もww


Hibiscus Vacherin, Ame Restaurant, San Francisco

Hibiscus Vacherin, Ame Restaurant, San Francisco

夜のお散歩

このエントリーをはてなブックマークに追加
Ferry Building

Ame にいって、今日の活動はおしまいのつもりだったのですが、あまりにもあっさりしすぎていて、なんかものたりない。で、もう少し何か食べたいので、夜の街をさまよってみました。

Muni Metro の F ラインに乗って Ferry Building にいき、そこから歩いて Pier 39 へ。以前は Pier 39 の方が全然賑わっていたのですが、今は Ferry Building の方が全然人が多い。

こういうところも時代の流れがあるんですね。

でも、Ferry Building は店が早く閉まってしまうのが残念。

Fisherman's Wharf をぶらぶらしていると、スプレー缶で絵を描くパフォーマンスをしている人が何人もいます。流行なの?


Cable Car

Ferry Building
San Francisco Carousel, Pier 39, Fisherman's Wharf

Pier 39 にあるカルーセル

Big Crane Machine

Pink Domo

クレーンゲームの中になぜかピンクのどーもくんが!

Ghirardelli Chocolate Caffé

このエントリーをはてなブックマークに追加
Ghiradelli Square, San Francisco

ということで、Ghirardelli Square まで歩いてきました。

今日は観光客モードで、Ghirardelli Chocolate Caffé で Hot Fudge Sundae です。ギラデリといえばホットファッジサンデーですね。メニューにも The World Famous と書いてあるし。

でも、実をいうと Hot Fudge Sunde を食べるのは初めて。ショコラショーとかをテイクアウトして飲んだことがあるのですが、いつも混雑しているので店に入ってサンデーを食べる気にならなかったわけです。

甘いのは予想はしていたけど、それにしても甘い....


The World Famous Hot Fudge Sundae, Ghirardelli Chocolate Caffé, Ghirardelli Square, San Francisco

The World Famous Hot Fudge Sundae, Ghirardelli Chocolate Caffé, Ghirardelli Square, San Francisco
The World Famous Hot Fudge Sundae, Ghiradelli Chocolate Caffé, Ghiradelli Square, San Francisco

2011/10/07

Lombard Street

このエントリーをはてなブックマークに追加
Lombard Street

今日は 1 日フリーなので、寺田さんと一緒にお出かけの予定。待ち合わせの時間の前に、Lombard Street (ロンバード ストリート)にいって、写真を撮ってきました。

というのも、次の JavaFX のバージョンのコードネームが Lombard だからなのです。

Lombard Street で有名なのは、Russian Hill のグネグネ坂の部分。実際には Presidio の方から North Beach まであり、Presidio から Van Ness Ave. までは 101 になっています。

まぁ、それはそれとしてグネグネの坂は 007 の映画でも使われている坂です。ここは午前中しか日が当たらないので、朝行ってきたわけです。

これで、これから JavaFX のプレゼンの背景の写真をここから使うことができます ^ ^;;

ついでに、すぐ隣の Sony のブラビアのスーパーボールの CM で使われた坂の写真も撮ってきましたよ。


Slope

_DSC1103

Slope

Agapanthus
Slope

ここが Bravia の CM の舞台

Lombard Street

Lombard Street

Lombard Street

Lombard Street

Lombard Street

Lombard Street
Lombard Street