しまてく

学んだ技術を書きためるブログ

[scala][勉強会] Scala会議#1に参加してきました。

Scala会議とは

恐らく日本で行われているScalaの勉強会の中でもっとも大きい規模のものと
なったのではないでしょうか。

以下のURLで録画が見れます。
http://www.ustream.tv/channel/scala-kaigi

以下、僕がメモった事や感じた事をまとめていきます。

イントロ : @j5ik2o さん

http://www.slideshare.net/j5ik2o/scala-9039767

オラクル青山センターにて行われたのですが、いきなりJavaをDisったのでビビりましたw
あとPHPはいつもの扱いな感じ。

会の方針として、「内輪で盛り上がらない」というのを全面に押し出していたのが
とても好感がもてました。

sbt徹底解説 : @xuwei_k さん

http://www.slideshare.net/KenjiYoshida/scalakaigi1sbt

sbtとは

ビルドツールの一種で、sbt自体がScalaで作られている。
sbtには以下の2系統ある。今後は0.10系統を使っていくのがいいだろう。

  1. 0.7系統
  2. 0.10系統

SBTを使う理由として、早いというのももちろんあるが、akka, scalaz, scalate, unfiltered等多くのプロジェクトがSBTを利用しているという事実がある。

jarファイル1つだけなので用意から起動が楽チン

バージョンの設定が超簡単
set scalaVersion := "2.9.0-1"

とするだけでコンパイルに使用されるScalaのバージョンが2.9.0-1になる。

sbtコンソールはコマンドの補完が聞いたり履歴を保存してくれたりするので便利。

注意点

以下をちゃんと設定しないと結構落ちるらしい。

  1. CSMClassUnloadingEnabled
  2. MaxPermSize
IDEとの連携

開発、デバッグIDEから行い、ビルドはsbtでやるのが正しいみたい。
※タイムラインを見ていると
IDEからデバッグしたい時は、sbt起動時に「-Xdebug」を指定するとEclipseからリモートでバッグできる。とのお告げが。
TODO:後で試してみよう。

設定ファイルのDSL

よく使われる、ライブラリ依存定義の構文

val twitter4j = "org.twitter4j" % "twitter4j" % "2.2.4"

というのは

val twitter4j = sbt.toGroupID("org.twitter4j").%("twitter4j").%("2.2.4")

と等価。
「%」というメソッドが存在しており、scalaメソッド呼び出しの為の「.」を省略できるのでこういったDSLが書けるんですね。

UnfilteredとかFinagleの話。そしてScalaの闇について : @yuroyoro さん

http://dl.dropbox.com/u/261418/20110828_scalaconf01_introducing_unfiltered_and_finagle/index.html#0

いきなりウキャス語で解読不能w

Unfiltered

https://github.com/n8han/Unfiltered
http://unfiltered.lessis.me/

非同期I/Oを対象としたツールキット。静的コンテンツは特に考えられてない。
以下のようなところで使われている。

  1. Remember The Milk
  2. Novus
  3. Trust Metrics

このプレゼン資料もUnfilteredのPicture-showというのを用いて作成されている。

コンセプト

パターンマッチング
関数合成
疎結合コンポーネント
組み込みサーバ

Unfilteredを使うと素早く・強力なサーバが書ける。

Finagle

https://github.com/twitter/finagle

twitter検索APIのバックエンドに使用されている。
JVM / NIO / Netty という環境で動作するもの。

プロトコルには依存しないので以下ようなものが使える。

  1. HTTP/HTTPS
  2. HTTP streaming (Comet)
  3. Thrift
  4. memcached
  5. ... more

Futureをやり取りする作りになっているので、すべての処理はFutureのチェーンとして実装され、型安全に非同期処理が保証される。
※node.jsでは開発者が"気をつけ"なければならない。

まとめ

Scalaは並行や同時実行がと相性が良い!
日本人エンジニアは英語に怯んでアーリーアダプターまかせになっているので、文句を垂れ流す前に自分らがアーリーアダプターになって情報発信していこう!
周りの環境のせいにして、自分が努力をする事を怠るな。

Scalaz - とある型クラスのライブラリ : @kmizu さん

http://scalaz.github.com/scalaz/

Scalazでは☆とか★とか∧とか∨とかのUnicode記号が多用されている!

Scalazとは?

Scalaの標準ライブラリにないアレコレを集めた便利パッケージ(Haskellian御用達)
I/O モナドまである。
Option / Listなんかも便利に拡張されているので使うと幸せになれるかも。

サンプルいっぱい
https://github.com/scalaz/scalaz/tree/master/example/src/main/scala/scalaz/example

とりあえず以下の2行をimportしとけば使える。
import scalaz._; // 小文字のscala
import Scalaz._; // 大文字のScala

List#toNel

NotEmptyListを返す。
NonEmptyListを使えば空リストでは無いことが保証されるのでhead, tailが必ず成功する。
reduceLeft, reduceRightでも同様に確実に成功する。

Option#orZero

OptionのorZeroは型ごとのゼロ相当の値(Zero[T] traitをextendsしたもので定義した値)が返る。

いろんなZero
http://scalaz.github.com/scalaz/scalaz-2.9.0-1-6.0.1/doc/index.html#scalaz.Zero$

i.orZero は ~i とも書ける。

Option#getOrElseの短縮

opt.getOrElse(false) と書くところを opt | false と書ける。
直感的!!

Zipper

純粋関数型イテレータ。要素更新もO(1)で高速にできる。

ParatialApply

型パラメータの部分適用(カリー化)ができる。

まとめ

Scalaは仕様がしっかりしてるので公式から仕様書を読むべき。
日本語でまとまった情報が欲しい場合は以下のURLへ。
https://sites.google.com/site/scalajp/

全体のまとめ

LTまでまとめる力がなかったのでセッションだけの振り返りで。
全体を通してすごくクオリティの高い発表者の方々でとても刺激を受けました。


個人的に斬新だったのが「スイーツ募金」というもの。
このお金で買い出しに行ってセッションの間のおやつやジュースに充てるというものでした。合理的ですね。


Scala会議は今後も継続して行っていく方針なので、これからScalaを始める方は要チェックですね。
内輪ネタで盛り上がらない!宣言をしている勉強会なのでとても安心して参加できると思います。


ただこの会を通して一つ残念だったのが女性エンジニアが一人もいないこと!
そのせいで会場がややスメリーな感じでした><


次回は女性Scalalianが参加してくれるといいなー。スイーツタイムあるし。

[ネタ] モテるC++女子力を磨くための4つの心得

1. あえてCのキャストを使ってみる

あえてCのキャストを使うようにしましょう。そして勉強会などの場で好みの男がいたら話しかけ、わざとらしくキャストを実行してみましょう。そして「あ〜ん! このキャスト本当にマジでチョームカつくんですけどぉぉお〜!」と言って、男に「どうしたの?」と言わせましょう。言わせたらもう大成功。「キャストとか詳しくなくてぇ〜! ずっとコレ使ってるんですけどぉ〜! 使いにくいんですぅ〜! ぷんぷくり〜ん(怒)」と言いましょう。だいたいの男は新しいキャストを使いたがる習性があるので、C++の新しい4つのキャストを使っているはずです。

そこで男が「新しいキャストにしないの?」と言ってくるはず(無闇にreinterpret_castを勧める男はその時点でガン無視OK)。そう言われたらあなたは「なんかなんかぁ〜! 最近新しい5つのキャストが人気なんでしょー!? あれってどうなんですかぁ? 新しいの使いたいんですけどわかんなぁぁああい!! 私かわいそーなコ★」と返します。すると男は「4つのキャストでしょ? 5つは出てないよ。本当に良くわからないみたいだね。どんなのが使いたいの?」という話になって、次の休みの日にふたりでキャスト選びのペアプロができるというわけです。あなたのC++女子力が高ければ、男があなたをdynamic_castしてくれるかも!?

2. template <>を使うとモテる

「多重継承」や「演算子の多重定義」をする際に便利な「template <>」を使うと、C++の男性ユーザーは「なんかこのテンプレート便利だなぁ」や「特殊化してあげたいかも」と思ってくれます。よくできたテンプレートは必需品になるので「template <>」を多用することによって、男性はあなたを無くてはならない女の子と勘違いしてくれるのです。そういうコードにするとエラーが発生した時にコンパイルのエラーメッセージが意味不明になりますが気にしないようにしましょう。

3. とりあえず男には「えー! なにそれ!?  知りたい知りたーい♪」と言っておく

懇親会などで男が女性に話すことといえばBoostなどのライブラリやC++0xの話ばかり。よって、女性にとってどうでもいい話ばかりです。でもそこで適当に「へぇーそうなんですかぁ〜?」とか「よくわかんないですけどすごいんですねぇ」と返してしまうと、さすがの男も「この女Boost::lambdaも知らないな」と気がついてしまいます。ダメ女だとバレたら終わりです。そこは無意味にテンションをあげて、「えー! なにそれ!?  知りたい知りたーい♪」と言っておくのが正解。たとえ興味がないコードでも、コンパイラと実行環境でその場を乗り切りましょう。実行しながらにコードを読んでくれる女性に男は弱いのです。

いろいろと話を聞いたあと、「〇〇は〇〇で、〇〇が〇〇なんですね! 覚えたぞぉ! メモメモ!」とコメントすればパーフェクト。続けて頭に指をさしてくるくる回しつつ「シーアウト!! ・・・ エンドエル!エンドエル!」と言って、「どうしたの?」と男に言わせるのもアリ。そこで「私の標準出力に吐き出しているのでありますっ☆」と言えばC++女子力アップ! そこでまた男は「この子生粋のC++erかも!?」と思ってくれます。私はFC++歴もC++/CLI歴もありませんが、こういうテクニックを使えば知識がない私のようなバカ女のほうがモテたりするのです。男は優越感に浸りたいですからね。

4. ペアプロではクラスをnewできない女をアピールせよ

男とペアプロに入ったら、真っ先に手近なクラスを探して「あーん! 私これnewできないんですよねぇ〜(悲)」と言いましょう。するとほぼ100パーセント「どうして? 純粋仮想関数があるの?」と聞かれるので、「純粋仮想関数はないしnewしたいけどnewできないんですっ><」と返答しましょう。ここでまた100パーセント「純粋仮想関数がないのにどうしてnewできないの?」と聞かれるので、うつむいて3〜5秒ほど間をおいてからボソッとこう言います。「……だって、……だって、newしたら殺さないとメモリリークが発生しちゃうじゃないですかぁっ! インスタンスちゃんかわいそうですぅ! スタックなら平気なのにぃぃ〜(悲)。私が殺さないといけないんですよ……」と身を震わせて言うのです。

その瞬間、あなたのC++女子力がアップします。きっと男は「なんて優しい天使のようなコなんだろう! 絶対に開放してやるぞ! コイツは俺の女だ!」と心のなかで誓い、あなたに惚れ込むはずです。意中の男と付き合うことになったら、そんなことは忘れて好きなだけスマートポインタを使って大丈夫です。「newできないんじゃなかったっけ?」と言われたら「大丈夫になった」とか「慣れた」、「スマートポインタなら参照カウンタがなくなれば開放されるから平気」と言っておけばOKです。


探したけどC++女子力がなかったのでついカッとなって書いた。
公開はするけど後悔はしない。
いろいろツッコミどころがあるけどご愛嬌。

若手IT勉強会を振り返ってみた

先日12/11に若手IT勉強会を行いました。
内容はJohn Resigが執筆中のSecrets of the JavaScript Ninjaの
8章:With Statementsです。

Secrets of the JavaScript Ninjaとは

Secrets of the JavaScript Ninja

Secrets of the JavaScript Ninja

jQueryの作者であるJohn Resigが絶賛執筆中のJavaScript本です。
現在はまだ未完の為、電子書籍という形で購入して読み進めています。

8章:With Statements

JavaScriptにおけるwithステートメントというのは大分嫌われ者だったりします。
その理由として遅いというのが強くあり、なおかつその使い方が難しい為
正しく使えていないというのが現実問題としてあるようです。

しかしResig曰く、正しく使えばこんなにパワフルなものはないという事です。

それではなにがすごいのでしょうか?

プロトタイプコールを減らせる

例えば以下の例のように、prototypeを辿るコストを節約できます。

Object.extend(String.prototype.escapeHTML, {
    div: document.createElement('div'),
    text: document.createTextNode('')
});
with (String.prototype.escapeHTML) div.appendChild(text);
タイプ量が減る(コードの可読性向上)

下の例ではwithを使わないとたくさん「this.」をつける必要があります。

var Rect = Base.extend({
    constructor: function(left, top, width, height) {
        this.left = left;
        this.top = top;
        this.width = width;
        this.height = height;
        this.right = left + width;
        this.bottom = top + height;
    },
    contains: function(x, y) {
        with (this)
          return x >= left && x <= right && y >= top && y <= bottom;
    },
    toString: function() {
        with (this) return [left, top, width, height].join(",");
    }
});
オブジェクト指向で書ける。

下の例ではcloakedという外からは絶対に触られることのないプライベート変数を作ることができます。

function Ninja(){with(this){
    // プライベート変数
    var cloaked = false;

    // パブリック変数
    this.swings = 0;

    // プライベートメソッド
    function addSwing(){
        return ++swings;
    }

    // パブリックメソッド
    this.swingSword = function(){
        cloak( false );
        return addSwing();
    };
    this.cloak = function(value){
        return value != null ?
            cloaked = value : cloaked;
    };
}}

いいところばかりじゃない

下のコード実行にかかる時間を測定したところやっぱりwith使うと遅い。

var obj = { foo: "bar" }, value;
// "No With"
for ( var i = 0; i < 1000; i++ ) {
    value = obj.foo;
}
// "Using With"
with(obj){
    for ( var i = 0; i < 1000; i++ ){
        value = foo;
    }
}
// "Using With, No Access"
with(obj){
    for ( var i = 0; i < 1000; i++ ){
        value = "no test";
    }
}


結果

平均 最小 最大 偏差
with 不使用 0.14 0 1 0.35
with 使用 1.58 1 2 0.50
with 使用 / アクセスしない 1.38 1 2 0.49

これだけだとよくわからないので自分でも測定。
http://www.cimadai.cz.cc/apps/with#summary
個々のマシンや実行環境による誤差はありますが、大体の傾向はこれで読めます。


上のグラフから見ると、withを使うとwithに渡したオブジェクトのプロパティを
触ろうが触るまいが劇的にパフォーマンスが落ちるというのが分かります。

まとめ

ある程度のパフォーマンス低下があるということを踏まえた上で、withを使うことがメリットと
判断できる場合に限りwithを導入してみるといいのかもしれませんね。

振り返り

若手IT勉強会も22回継続してやってきました。


勉強会の初めのきっかけは、懇親会などでは何度も言っているのですがid:amachangの影響が
非常にあります。
id:amachangの発表を見たり、勉強会やろうぜ!という話を聞いて「あぁ、俺もやろうかな」
という感じで勉強会を始めました。


最初のうちは自分の勉強の為にやっていたのですがそのうち人も増えていき、自分を含めた
若手エンジニアでどんどん勉強したい!という思いに変わり、読書会/コードリーディング/
ust中継/LT/発表などいろいろやってきました。


若手IT勉強会は毎回来てくれるなじみのメンバーと新しく参加してくれる人が半々くらい
なのですが、回を重ねるごとに自分を含めて毎回来ている人はどんどん詳しくなっていって
基本的なところは流しがちになっているなぁ、というのを感じていました。


元々は若手IT勉強会という名が表している通り若手に対して門戸を広げたいという思いもあり
基礎をおざなりにするのはちょっと違うのかな、と思い始めていました。


そこで若手IT勉強会を振り返ってみて、勉強会の方針としてどの層をターゲットにしようか、
という事を考えました。
その結果いま新卒〜3年目あたりの人*1を対象に、プログラム楽しいよ、JavaScript楽しいよ
的な事を勉強会を通じて教えられたら素晴らしいかなぁなどという考えに至りました。


まだまだ僕も勉強中だし大それたことは言えないですが、1年そこそこで腐ってプログラムを
辞めてしまうのはこの業界にとって良いことではないのではないでしょうか。


というようなことを22回目の懇親会の場で打ち明けたところ、みなさん快くやりたいように
やればいいと言ってくれたので今後の基本方針として下の2点を念頭に置いて勉強会運営を
していきたいと思います。

  1. 勉強会の技術レベルを若手(初級者)に合わせる。
  2. 新しい人にどんどん参加してもらう。


ただこれだけだと今まで継続してやってきている人は物足りないと思いますし、自分もいろいろ
チャレンジしたい気持ちもあるのでなにか別の勉強会を作るか、、他の勉強会に参加するか、、、


いずれにせよ若手IT勉強会の立ち位置としては若手中の若手の為の勉強会というスタンスで
今後進めようと思いますので、今後ともよろしくお願いします。

次回宣伝

次回は2011/01/29 14:00- 第9章 Code Evaluationやります。
Objective-Jとかおもしろい言語がでてきたりします。
http://atnd.org/events/10996

よろしくお願いしますー

*1:自分よりも全然すごいエンジニアも多かったりするのですが。。。

Ruby1.9.2の$LOAD_PATHにはカレントディレクトリが含まれなくなった

Ruby1.8系の環境で動いていたスクリプトRuby1.9.2を新しくいれた環境に持ってったら動かなくなったので
調べてみたら含まれなくなったらしい。

#この一行の追加で対応
$LOAD_PATH.push('.')

SecretsOfTheJavaScriptNinja 3章

はじめに

このエントリは若手IT勉強会のSecretsOfTheJavaScriptNinja読書会の為の
まとめエントリです。
拙い翻訳をしながらざっくりまとめてます。

Secrets of the JavaScript Ninjaとは

Secrets of the JavaScript Ninja

Secrets of the JavaScript Ninja

jQueryの作者であるJohn Resigが絶賛執筆中のJavaScript本です。
現在はまだ未完の為、電子書籍という形で購入して読み進めていきます。

3章の内容

  • 関数の重要性の概要
  • オブジェクトとして関数を使う方法
  • 関数のコンテキスト
  • 可変引数の扱い
  • 関数のタイプ決定

関数定義

関数の定義方法として、大きく分けて2つ
// (1) オーソドックスな方法
function foo(){
    return true;
}

// (2) 無名関数を使う方法
var bar = function(){
    return true;
};
window.baz = function(){
    return true;
};

これらの定義方法はグローバルスコープで定義される場合、完全に等しいものになります。
 

関数のスコープ

function stealthCheck(){
    var ret = stealth() == stealth();
    assert( ret, "returnステートメントの下には行く事はないが、このretはtrueになる。" );
    return true;
    function stealth(){ return true; }
}
stealthCheck();

関数は特別扱いをされていて、「function foo(){}」のように定義された関数の場合は
関数を呼び出す個所よりも後ろで定義されていても呼び出し可能という特性があります。


ただし、「var foo = function(){}」のような無名関数の場合は、コード中で定義を行った場所以降
でしか呼び出すことはできません。

無名関数

  • (普通の)無名関数
// こんな感じでコールバックなどで使ったり。
setInterval(function(){
    // この無名関数は100ミリ秒ごとに呼ばれる
}, 100);
  • 名前付き無名関数

一見して矛盾しているような関数ですが、限定的に名前が付いている関数の事です。
一言で言えば「関数の中からは名前付き」「関数の外からは無名関数」って事ですね。

var ninja = {
    yell: function yell(n){
        // この関数の中でだけyellという名前が使える。
        return n > 0 ? yell(n-1) + "a" : "hiy";
    }
};
assert( ninja.yell(4) == "hiyaaaa", "ちゃんと関数内で参照できる。" );
var samurai = { yell: ninja.yell };
var ninja = {};
assert( samurai.yell(4) == "hiyaaaa", "関数をコピーしても大丈夫。" );


ただ、より良い方法として、argumentsオブジェクトのcalleeプロパティを使用する方法があります。

var ninja = {
    yell: function(n){
        return n > 0 ? arguments.callee(n-1) + "a" : "hiy";
    }
};
assert( ninja.yell(4) == "hiyaaaa", "arguments.calleeでも自己参照ができる。" );

名前付き無名変数は古いブラウザでは使えないものもあったり、やや冗長になりがちなので
関数のなかで自分自身を参照したい場合はaruguments.calleeを用いるのがいいのではないでしょうか。

オブジェクトとしての関数

JavaScriptでは関数(Functionオブジェクト)もObjectオブジェクトから派生しているオブジェクトなので
以下のようなObjectオブジェクトの特性を持っています。

  1. プロパティを持てる
  2. prototypeを持てる
  3. オブジェクトの能力を持っている(派生してるからね)

違うところは、関数として呼び出せる所です。

var obj = {};
var fn = function(){};
obj.prop = "some value";
fn.prop = "some value";
assert( obj.prop == fn.prop, "オブジェクトも関数もプロパティを持てる" );

関数の保持

実際にjQueryの内部でイベントハンドラのコールバック関数の保持をするのにやっているような処理の例

var store = {
    id: 1,
    cache: {},
    add: function( fn ) {
        if ( !fn.id ) {
            fn.id = store.id++;
            return !!(store.cache[fn.id] = fn);
        }
    }
};
function ninja(){}
assert( store.add( ninja ), "関数は安全に追加される。" );
assert( !store.add( ninja ), "同じものは1度しか追加されない。" );

キャッシュ機能付き関数

名前でDOM要素を取得する際にキャッシュに入れておき、次の要求時に即座に返す方法

function getElements( name ) {
    return getElements.cache[ name ] = getElements.cache[ name ] || document.getElementsByTagName( name );
}
getElements.cache = {};

高速化にはすごく寄与するけど、メモリの使いすぎには注意するべきだよ、と。

関数のコンテキスト

「関数のコンテキスト == "実行されている関数を含むオブジェクト"」です。
例えば、オブジェクトの内部では上書かれない限りそのコンテキストは常にそのオブジェクト
への参照を保持します。

var katana = {
    isSharp: true,
    use: function(){
        this.isSharp = !this.isSharp; // オブジェクト自身のプロパティを触れる。
    }
};
katana.use();
assert( !katana.isSharp, "Verify the value of isSharp has been changed." );


しかし、オブジェクトのプロパティとして定義されない関数のコンテキストは
グローバルになります。

function foo(){
    assert( this === window, "グローバルオブジェクト(ブラウザで実行する場合はwindow)になる" );
}
コンテキストを修正する2つの方法
  1. Function#call
  2. Function#apply

の2つです。
それぞれ用途は同じですが、使い方が違います。


どちらも第1引数は同じで、関数を呼んだ後のコンテキストとなるオブジェクトです。
callは第2引数以降が呼び出す関数の引数になります(ばらばらで渡す)。
applyは第2引数が呼び出す関数の引数になります(配列として渡す)。

function add(a, b){
    return a + b;
}
assert( add.call(this, 1, 2) == 3, ".call() takes individual arguments" );
assert( add.apply(this, [1, 2]) == 3, ".apply() takes an array of arguments");
ループ

forを隠ぺいしたループの実装

// この関数をどっかで定義しておく
function loop(array, fn){
    for ( var i = 0; i < array.length; i++ )
        if ( fn.call( array, array[i], i ) === false )
            break;
}

// 実際に使うのはこんな感じ
// jQuery.eachの実装と大体同じようなもの。
var num = 0;
loop([0, 1, 2], function(value, i){
    assert(value == num++, "Make sure the contents are as we expect it.");
});

上記の例だと、loop関数の中でcallメソッドを使ってコンテキストをarrayにしているので、
loop関数に渡したコールバック関数のなかでthisを参照するとオリジナルの配列にアクセスできます。

配列内の最大値・最小値

正直に最大値や最小値を求めようとするよりも良い方法があります。
Mathオブジェクトのminメソッドとmaxメソッドを借りてしまいましょう。

function smallest(array){
    return Math.min.apply( Math, array );
}
function largest(array){
    return Math.max.apply( Math, array );
}
assert(smallest([0, 1, 2, 3]) == 0, "Locate the smallest value.");
assert(largest([0, 1, 2, 3]) == 3, "Locate the largest value.");

関数のlength

全ての関数には、関数自体にlengthプロパティがあります。
さらに、argumentsオブジェクトにもlengthプロパティがあります。

これらの違いは、

  • 関数のlengthはその関数が期待する引数の数
  • argumentsオブジェクトのlengthは実際に渡された引数の数

となります。

function foo(a,b){
    assert(foo.length === 2, "期待する引数は2つ");
    assert(arguments.length === 3, "渡された引数は3つ");
}
foo(1,2,3);

これを使うと、引数の数の違いによるメソッドオーバーロードができますよーという例が
本には書いてありました。

関数の型

指定されたオブジェクトが本当に関数で、呼び出すことができるのか?という判定をする
クロスブラウザな方法の例をご紹介します。


大抵はtypeofステートメントだけで十分に関数かどうか判定できます。

function ninja(){}
assert( typeof ninja == "function", "Functions have a type of function" );


しかし以下のようなブラウザを相手にする時にはtypeofステートメントでは上手くいきません。