脳みその中身

Inside of My Brain

オッサンの得意技

人は誰も『貯○池』を持っている

「腹が立つ」と「怒る」の間の『堪忍袋』のようなものがそれであり、
(今現在の己の能力や状況では) 解の出ない問題に直面したとき、いったん棚上げにする『棚』がそれである。
電気回路における『コンデンサ』のような『貯○池』は、人間が社会生活を営む上で、欠くべからざる機能であると言える。

何を「貯める」のか…

それは、怒りであり、虚無であり、無力な『すべての問い』である。

つまり、理解不能(もしくは、理解なんぞしてやるもんか…)なこと。
(今の自分の力では)どうにもらないこと。
そうした問題を目の当たりにしたときには、人は、退避場所にそれらを送る。

どのくらい「貯められる」のか…

『オトナ』であるほど、『デキタ人間』であるほど、許容量 — つまり貯め込むことのできる量 — は、より大きいとされる。
なぜなら、それらの問題の大半は、『我慢』を強いる。
そして、一般に、『オトナ』は『子供』よりも余計に『我慢』できるはずであるからだ。

たしかにそのはずである。
自らを振り返るに…
子供時代と比べれば、すこしは我慢に長けたような気はする。
( 百貨店の玩具売り場で、「ダメ!」と言われてこの世の終わりのようにショックを受けた子供時代の僕よりは幾分マシである…という程度には、)
今年 51歳になる僕は我慢強い。

理由は単純である。
オッサンが、公衆の面前で駄々をこねるのは、見ていられないほどイタイ光景であるからだ。オッサン本人以外には誰も気にしないが…

オッサンが持つ能力は、この奇妙な自意識だけではない。
もうひとつの、オッサンの最特技は『鈍さ』である。
『したたかさ』と言っても良い。

換言すれば、オッサンは不感症である。
長い人生の間に、敏感な部分を他人にいじくりまわされ、それ以上に自分でいじくりまわしたあげく、押しも押されもせぬ立派な不感症になったのだ。

とにもかくにも、斯くして、くだらない自意識を持つ、不感症のオッサンが誕生したわけである。

我慢の限界

しかし、我慢の『限界』は厳然と存在する。

オッサンにだって…である。

理由は、そもそも我慢は身体に悪いから…だ。
身体に悪いことは、一定の許容量を超えると、身体が拒否するのである。

脳みその最前線から、理解不能・回答不能な問題は、いったん『退避場所』に送られるが、退避場所の許容量を超えると、身体が拒否する。

身体が拒否したあげく、それらはどこへ行くのか

それらは、トコロテンのように押し出されていく。
押し出されていく先は、忘却の彼方であったりもするが、必要に応じて、脳みその最前線に押し戻される。

オッサンは、このあたりの仕分けが得意である。

オッサンの得意技『忘却』と『反芻』

オッサンの最強の得意技は『忘却』なので、忘れる能力には何の問題も無い。

しかしオッサンは、あえて忘れないで、再び対峙するべく、脳みその最前線にそれらの問題を押し戻すのだ。
まるで、牛の反芻である。

今の自分の能力では、答えの出ない問題に直面した場合、
オッサンは、いったん退避場所たる『心の棚』にそれらの問題をいったん『棚上げ』にする。
当事者のオッサン以外には、『逃避』と映るかも知れないがそうではない。

オッサンは案外忙しい。
その瞬間に、せねばならぬ仕事がある。
早押しクイズのように押さねばならぬボタンがある。

検証や再考が必要な問題は、いったん棚上げするが、あとでちゃんと棚から下ろして対峙するのだ。

オッサンは、オッサン家のイタチとは違うのだ。
やつらは、オッサンのことを

  • 自動エサ出し機
  • オートクソ取り機
  • エサ出しクソ取りロボット

としか思っていない『忘恩の徒』だが、
オッサンは断じてそうではない。

オッサンには、『反芻』という最強能力があるのだ。
この『反芻機能』が壊滅しない限り、オッサンは無敵である。

(;´Д`)はぁはぁ…

松本人志とわかりにくい映画『さや侍』(ネタバレ極力なし)

『さや侍』を観た。

松本人志監督の最新作である。
松本人志は、自らを天才と名乗る。
その行為は、とくに日本人の気質にはそぐわない。

彼の作る笑いは、その多くがアドリブである。
お題をひとつ決めて、やりとりしていく中に、他の誰にも置けない位置に、思いも付かない至極のピースをバシバシと置く。
天才はひらめきとセットで語られる。
たしかに「ひらめく」のだろうと思う。

松本人志は、「笑いの理屈」を解明し説明可能にしたいと思い続けているらしい。
かつて、故 桂枝雀が「緊張と緩和」というヒントを呈して以来、そのことを考え続けているのだと言う。

「ひらめき」と「理屈」は相反するように聞こえる。
彼は、再現性のある「理屈」として「笑い」を留め置きたいのだと思う。
もしかしてそれは、「笑いに値しない薄っぺらな戯れ言が笑いと認められていること」に対する猛烈な怒りなのかもしれない。

ともあれ、松本人志は、「ひらめきの人」であるがゆえに、「理屈の人」である。
なぜなら、「彼のひらめき」は「リアルタイムのその瞬間」に超高速で理屈を計算し、自分の語彙の中から「そぐう言葉」を検索し、「最適なタイミング」と「最適な言い方」で場に投げ放つものだからである。

言うならば、理屈を計算した「脚本家」「監督」としての自分と、「演者」としての自分の二人羽織である。
この二人は同一の人間が行うことが望ましいように思える。
だから、これまでの彼の映画は監督兼主役であったのだろう。

しかし、この『さや侍』は、「そうでない初の作品」である。

超高速で「計算された理屈を駆使できる人間」が、たっぷり時間をかけて、「監督」という役割のみに徹した初の作品である。

松本人志は、すでに芸能界で大きな立場にあり、ファンもたいへんに多い。

一方、彼の笑いは、暴走気味に走りやすく、ときに聞く者を置いてきぼりにする傾向がある。
個人的な見解だが、コンビを組む浜田雅功の役割は、「聞く者を置いてきぼりにさせない」という一点にあるように感じる。
旧い漫画の話で恐縮だが、Gu-Guガンモにおけるスニーカーの役割である。
※ スニーカーがなければガンモは空を思うように飛ぶことが出来ない

松本人志を構成する笑いの本質とは、浜田雅功のツッコミなしには、「商品」として「受け入れられない」笑いであると極論しても良いのかも知れない。
しかし、「万人にわかるようにする」という努力は、先の譬えをなぞるなら、「加減して飛ぶ」という努力である。
しかし、彼は、その都度その都度、力の限り羽根を羽ばたかせて、勝負したいのだ。
松本人志は、思いっきりの松本人志を、毎回、客に投げつけたいのだ。

この欲求が彼の根幹をなすのだから、彼の映画はわかりにくい。
「客のレベル」という話ではない。
「客の覚悟」という話である。

「楽しませてくれること」を期待して、何の「覚悟」もなく、ただぼーっと『さや侍』を観ても、消化不良感しか得られない。
いまどきのハリウッド映画によくあるように「グイグイと引き込まれる感じ」は、『さや侍』には存在しないのだ。
ある人が「爆薬の量」と称した「派手さ」も一向に与えてはもらえない。

こういうと、『さや侍』は、人気者の芸人 松本人志が、その笑いの才能だけを頼りに、本来怠るべきでない「グイグイと引き込まれる感じ」だの「派手さ」だのを盛り込むことに横着して、適当に作ったものなのだと聞こえるかもしれない。

実際、Web上で漏れ聞こえてくる『さや侍』の評価は芳しくない。
しかしそれは、松本人志の「客に阿る(おもねる)ことを排する決意」ゆえである。

「こんなつまらない作品を二度観ようとは思わない」
どこかのだれかのそんな Tweet を目にした。

しかし、客の覚悟なしには、二度三度観なければ、『さや侍』の価値は理解できない。

「いや、僕は、ちゃんと感動したよ。涙したよ。」と思う方には、再度繰り返したい。
あなたも、松本人志が『さや侍』に込めたモノを味わい尽くしてはいない。
一度観た程度では、「わかりやすくするため」の努力を排してさえ、込めようとしたモノの半分しか理解できていない。

そこには「答」がある。

「親子とは」「生きるとは」「死ぬとは」「男とは」「侍とは」「戦うとは」「守るとは」「遺すとは」「命の美醜とは」という『普遍的な答のあるはずのない禅問答』に対するひとつの答がある。
『さや侍』がくれる答の姿は、万人が同様に同意できるものではない。
しかし、ひとつの「純粋な」答である。
今の時代だからこそ誰も語らない答がある。
現代人が10人集まって、夜通し語り合っても、たどり着けない類の「見失っている答」がある。

僕自身、一度目に観た感想は、
「のこり15分あたりまでは面白くも何ともないギャグネタが続く。板尾的な肩すかしネタ多し。ただし、最後の15分は感動ラッシュ!ここまではこの15分のためにあったのだ。この良さが分からない奴は、父親の資格無し!」
という Tweet の通り、薄いものだった。
(正確には、「残り22分ほど」だった)

二度目に観たときは、42チャプター中39番目のチャプターから観た。
「感動はしたものの、それが何の感動だったか」を確認したい欲求からだった。
だからといって「板尾的な肩すかしネタ」で構成される前半の1時間20分は観る必要が無いと思っていた。

観た後、触られたことのない 心の部分を触られた気がした。
しかし「侍」なんて時代錯誤な価値観は、現代を生きるのに何の役にも立たないとも感じた。

三度目は、最初から最後まで観た。
娘たえの手を、自ら初めて取る能見勘十郎の行動の意味に気付いた。
「さや」の本当の意味に初めて気付いた。

たまらずすぐに、四度目を観た。
四度目は、主人公の野見勘十郎と娘たえとの時系列のシーンと、対応する感情や意識の変化を書き出しながら観た。
僕の四度目の見方は、やりすぎでもある。
感じるべきものを考えてしまうのでは、本末転倒である。
「いまの笑いは何が面白かったかというと…」と説明するのに似ている。

しかし、鍵になるシーンと想像される気持ちを書き出すことで、鍵になるシーンと鍵になるシーンとの間のディテイルの細やかさに多く気付かされた。
メモを取るというおよそ感受性と関わりの無い行動とはうらはらに、もっとも感動し、嗚咽した。

これから自分の人生に消化不良になったとき、僕はまた『さや侍』を観ようと思う。

多くの人に『さや侍』を観て欲しいと思う。
そこに詰め込まれたすべてを吸い尽くす覚悟で、何度も観て欲しい。
能見勘十郎が一度だけ微笑むシーンや、一度だけ娘の手をとったシーンや、一度だけ「さや」に刀身を収めたシーンを観て欲しい。

乞食でしょうか?クレーマーでしょうか?

20分ばかり前の @kura_kj8_luv さんの Tweet

@masason 『津波』の影響でsoftbank商品が『流失』し解約に行きました。しかし本体支払いが済んでおらず全額支払いが済むまで続くと言われました。『津波』で使用できなくなり、解約せざる終えないのに支払いが続くなんて考えられません!この対応には大変憤りを覚えました!

…で、またわけのわからないことに、これをRTする人が何人も…

津波のせいで流失したのは、確かに、@kura_kj8_luv さんのせいではありませんが、同時に @masason さんのせいでもありません。

『津波』のせいです。

Softbank としては、実に当たり前の対応です。

Softbankの対応に『考えられません!』『大変憤りを覚えます!』…てのは筋が違います。

クレーマーでもなく、乞食でもないのであれば、脳みそを通して Tweet しましょう。

携帯カンニング事件について思う

再発防止…会場で、携帯が使えなくすればすむので、必要なだけジャマーを設置する…以上解決。

マスコミの加熱…バカなのか、わざとなのか…

『「頭の良い協力者」の知り合いがいなくても、できるカンニング法』
という一点が、従来のカンニングと違うだけのこと。

それ以外は、「新手」でもなんでもない。

マスコミは、よほど、世論誘導の方向性に関するイニシアチブを持ち続けたいのですねぇ。
一般社会とネット社会の常識のずれ…なんて言ってますが、常識なんて、立場や個性によって「ずれるもの」です。
車社会になって、「交通ルール」や「交通道徳」が必要になったように、ネット社会でのリテラシーを持たずには生活できなくなってきているのは自明です。

「携帯で撮影した画像をOCRでテキスト化して、Yahoo知恵袋に投稿したにちがいない」とかぬかしていた自称専門家がテレビに出ていました。

A) シャッター音を消さなければならない
B) 民生の日本語OCR技術はまだまだミスが多い
C) 問題用紙全体を写すには、そうとう「目立つおかしな格好」をしなければならない

しまいには、「協力者が…」とか言い出すのを目の当たりにすると、もー、バカかと…

ね、面倒すぎるでしょ?
今どきの高校生なら、片手でガラケーで問題を入力するくらい簡単にできるわけですから。

ジャマーの件も、写メじゃなくて手入力じゃね?って件も、普通に考えて、最初に思いつかないのは不自然。
よっぽどマスコミがバカなのか、もしくは…
「ね!すっげーでしょ!怖いでしょ!ネットって生活を脅かす存在なんだよ!」
と問題を事実以上に大きく見せたかったのか。
手口のすべてを殊更に『ハイテク』にする必要があったのか。
(手入力じゃ、アナログだから、画像 > OCR > 自動投稿 というシナリオに持って行きたかったのか)

ま、んなこたどーでもいーけど、色々そのあたりのこと考えていたら、妄想が膨らみだしたので、メモ。

Continue reading

FileMaker で Google Apps (Gmail) の PermanentLink を取得するカスタム関数

自分用に、Google Apps の個々のメールの PermanentLink を取得する FileMaker の カスタム関数を作りました。

理屈は、別記事:Google Apps (Gmail) で PermanentLink を取得する方法 の通りです。

____________________
GetGmailURL ( webviewerObjectName ; shvaOption )
____________________

// Created: 2011/02/15
// by bison
//
// Parameter:
//  webviewerObjectName : Webビューアのオブジェクト名
//  shvaOption : 0 の場合 shvaパラメータを省略します。
//   1 もしくは 空値 ( "" ) の場合は ?shva=1 を付けます。
// Explanation:
//  GMail (Google Apps) の個別メッセージURLの場合、
//  個々のメッセージのパーマネントURL を返します。
//  それ以外の場合、当該Webビューアで表示中のURLを返します。
/////////////////
Let (
[
$myurl = GetLayoutObjectAttribute ( webviewerObjectName ; "source" ) ;
$gmailJudgeText = "https://mail.google.com/mail/" ;
$startPos = Length ( $gmailJudgeText ) ;
$gmailFlag = Left ( $myurl ; $startPos ) = $gmailJudgeText ;
$spos = Position ( $myurl ; "/" ; 1 ; PatternCount ( $myurl ; "/" ) ) // Position of last slash
] ;

Case ( $gmailFlag ;
	Replace ( $myurl ; $startPos ; $spos - $startPos ;
	Case ( shvaOption = 0 or IsEmpty ( shvaOption ) ; "/#all" ;
	"/?shva=1/#all" ) )
	; $myurl ) // Case
)

____________________

※ shvaOption については、
Gmail’s SHVA Parameter
Gmailで日本語を検索した際の不具合
あたりを参照してください。

Google Apps (Gmail) で PermanentLink を取得する方法

Google Apps や Gmail で個々のメッセージを表示しているときの URL の一部は、状況に応じて変化します。

受信箱にあるメッセージの場合 — #inbox
ラベル経由の場合 — #label
検索の結果経由の場合 — #search
など…

とは言え、受信箱内のメールをアーカイブした場合も、 受信箱にあったときと同じ URL で当該メールは表示されるようになっているはずです。
( 僕の記憶があっていれば、以前は、アーカイブされたメールは、受信箱にあったときの URL では表示できなかったと思いますが、いつからか、仕様が変わったようです )

「なっているはず」なのですが…

メールによっては、状況が変わる前の URL では、表示されない場合があります

そういう場合、#inbox や #label/[labelname] や#search/[検索語] などを #all に置き換えてやれば表示されます。

例)
受信箱にある
https://mail.google.com/mail/#inbox/12e274e35ad122f5
のメールに、_Business というラベルを付加して、アーカイブすると、

https://mail.google.com/mail/#label/_Business/12e274e35ad122f5
https://mail.google.com/mail/#inbox/12e274e35ad122f5

のどちらでも表示されるはずだが、後者では、表示されない場合がある。
( すでに inbox に存在しないわけだから、表示されない方が自然な感じを受けますが )

これでは、ラベルを付けたり外したり、アーカイブしたりすると、リンクが切れる場合があるという話になってしまう。

そこで…
https://mail.google.com/mail/#all/12e274e35ad122f5
というように、当該部分を #all にしてしまえば、パーマネントリンクになる…ということのようです。

ペルソナの決め方と調査のあり方

商業プロジェクトの初期段階で、「ペルソナ (想定ユーザ) をどうするか」という話に よくなります。
ペルソナ (想定ユーザ)
アドホックなペルソナ ( 調査やデータなしに「こんな感じじゃね?」と推察した仮のペルソナ ) にすべてを託すことは危険ですし、「だからちゃんと調査してデータに基づいたペルソナを決めるべき」という指南書は数多く見受けられます。
そして、これらの意見に対して、僕自身、異を唱えるつもりは全くありません。

「調査の必要がない」つまり「調査しなくても結果は明かである」というケースであっても、(後述する) 調査の結果見えてくる潜在特性の発見 などの重要性を考えれば、調査に基づいた 本来の意味のペルソナ が重要なことは明白です。

それでも僕は、まず、アドホックなペルソナを無視して始めたプロジェクトは失敗すると断言できます。

最も初期の段階で詳細なアドホックペルソナを設定せよ!

プロジェクトの一番最初に、出来る限り、詳細で厳密な アドホックな (仮の) ペルソナを設定することが肝要なのです。

(「その重要性がわからない」「面倒だ」といったアフォな場合を除けば、) アドホックなペルソナの正当なベネフィットがいくつかあるからに他なりません。

重要なベネフィットは、いったい何でしょう?

決して
「時間的・金銭的に、調査しない方がコストが低い
ということではありません。
それは…「売り手の先入観を利用する」…ということです。

売り手側の先入観を利用せよ!

「仮」のペルソナから始めることの利点

実は、先入観 なしにゼロから調査して、正解に辿り着くのは、効率的ではありません。
そもそも、先入観の無い人は存在しません。
先入観は、あって然るべき…であり、先入観ありきの作戦でいった方が合理的なのです。
問題は、先入観の無い見方をしているかのような勘違い意識にこそあるのです。

先入観は、否定するものではなく、疑うものなのです。
疑うためには、「先入観なしで!」と言っていては疑えません。
「先入観?もちろんあるよ!正しいかどうかは怪しいもんやけど…」
…ってなバランスが一番良いのです。

先入観を利用するには、まず…
先入観を具体的にリスト化することから始めます。
そして、調査によって、実態の検証を行い、先入観と実態との間で、整合を図るのです。

アドホックなペルソナは、あくまで、たたき台であり、都度、「仮」のペルソナです。
「仮」ということは、「正しい点も間違っている点もないまぜになっている状態」なのですから、この状態を整理して、より真正の実態に近づけるためにこそ調査をするわけです。
言い換えるなら、先入観の間違いさがし」という目的で調査を行うのです。

顧客の顕在特性は 間違いさがしで検証せよ!

顧客の特性は、便宜上「顕在特性」と「潜在特性」に大別できます。

前項で、「間違いさがし」と言ったのは、「顕在特性」を検証する ということです。

例を挙げると…大学に通うために新入生がアパートを探しているとします。
この場合、学校との距離や家賃などの条件が、その他の条件(間取/築年など)に比べてより重要であることは、調査の結果明らかになっています。
保護者の金銭的条件と、新入生自身の通学の利便性が、他の条件より優先されるということです。
つまり「多少 古かったり狭かったりしても、学校に近くて、予算の範囲内であることの方が重要」であることがわかります。

顧客の潜在特性を発見せよ!

さて実は、調査の目的は、顕在特性の実態が想定した先入観と合致しているかどうかの検証だけではありません。
調査の結果、「へぇーそーやったんやー!」というような、調査した側もされた側も知らなかったような特性が浮かび上がることがあります。
顧客の特性
これを「顧客自身も意識していない特性」という意味で、ここでは『潜在特性』と呼ぶことにしましょうか。
これは、思いもかけず見つかることもありますが、ある程度、見つけるための工夫を仕掛けることが大切です。

例えば…

  • 書きたくなるような 記述式の設問をひとつふたつ設ける

※ 当然ですが、「なんでもいいからコメントを…」ではなく、ある程度テーマを絞って、回答者にとって書きやすくしておくことも重要になるでしょう

  • プロジェクト内容と一見関わりのないような設問も設ける

という方法は、有効です。

記述式の設問は、書く/書かない だけでなく、回答の文字数や、内容の解析 など後の解析次第で複合的な有益な情報元になりますし、
関係のないような設問は、「箸休め」のような働きをし、回答者を調査に対して協力的にしてくれる効果があるようです。
この場合、気をつけたいことは…メインの設問とは逆の属性の設問にすべきであるという点です。
メインの設問が比較的シンプルで淡泊に回答できるものであれば、これらの設問は、ほんの少しひねったものに、
状況などの客観的なものに対しての設問がメインであれば、個人の嗜好などの主観的なものにすべきでしょう。

調査属性の種別

データは嘘をつく

データは数値という形式になりますから、「データは嘘をつかない」「数値は公正であり、データは真正なモノである」と盲信しがちですから、正しく採られなかったデータは必ずと言っていいほど「誤解」を誘発します。

データとは、調査の結果です。
したがって、調査の方法により、データは変わります。

  • 何を知りたいのか

という基本的なことのためには、アンケートの内容が重要であることは言を俟ちません。

しかし、実際には、(内容だけでなく)

  • 誰にアンケートを採るのか
  • どういう手段でアンケートを採るのか (街頭 / サイト / メール / 商品添付のハガキ など)
  • アンケートの告知にどういう手段が使われるのか (懸賞サイト / メール など)
  • アンケートに応えるインセンティブの有無 (プレゼントなど)

といった アンケート実施方法ごとの小さな差異も大きく影響してきます。

典型的な例として、実際に某サイトで十年近く前に行われた調査の話をしましょう。

あるサイトで、多数の方々に対して

  • インターネットにを使用する頻度と時間
  • インターネットを使用する目的
  • 年齢・性別

などのアンケートが行われました。

なんと「95% 以上の 30代女性は、毎日 1時間以上、3つ以上の目的のために経常的に、インターネットを使っている」という結果が出ました。

しかしもちろん、この結果を真性のデータと受け取ってはいけません。

なぜなら、このアンケート調査が行われたのは、ヤングミセスをターゲットとする あるポータルサイトで行われたものだからです。
(インターネット上で行われているアンケートですから、アンケートに応えるためには当該サイトにアクセスしなければならないことは自明です)
ここまで極端にバイアスの存在を無視したケースは、さほど多くはありませんが、わかりにくいけれど 調査目的と調査手法がずれているケースは、大変に多いです。
そして、そのようなチグハグな調査は、調査費用をドブに捨てたことになるだけでなく、プロジェクト自体を誤った方向に導くことになるのです。

ペルソナは複数設定せよ!

アドホックなペルソナを設定して調査を行った結果、相反する属性が出る場合があります。
「あります」と言いましたが、相反する属性は出るものなのです。
だからと言って、ひとりのペルソナが、(調査の結果顕著であるとわかった) 属性のすべてを持っているわけがありません。
勘違いしないでください。
ペルソナは複数設定する必要があります。

仮に、ある服飾デザインメーカーの調査により、身長162cm 以上の人と、体重 45kg以下の人が、ドット模様のブラウスが好きであるというデータ結果が出たと仮定します。
身長 162cm以上で、体重 45kg以下の、極端にスレンダーな女性が、特に水玉ブラウズを好むのでしょうか?
違うはずです。

ペルソナの属性は尖らせよ!

多くの場合、複数設定したペルソナは、プライオリティをちゃんとつけることで、マーケティングの指針として大いに役立ちますが、集約しすぎた平均データは、何も教えてくれません。
勘違いしないでいただきたいのですが…
『尖らせる』というのは、極端にせよという意味ではありません。

先の例であれば、身長が比較的高い女性に好まれるからといって、170cm以上の女性にしか似合わない水玉ブラウスでは売れないでしょう。

より『具体的に』『明確に』するということです。

上記の例であれば…
水玉のブラウスを「好き」だから買うのか、「無難だから」買うのか
水玉ブラウスは嫌いな人の分布はどうなっているのか
といったあたりも追加調査が必要でしょう。

追加調査の結果、「無難だから」ではなく「好きだから」水玉ブラウスを買うという顕著な結果が出れば、水玉ブラウス嫌いな人の分布調査結果は軽視しても構わないでしょうが、「無難だから」買うのであれば、嫌いな人の分布状態は、大きな指針になるはずです。

FileMaker Dictionary 関数

FileMaker Dictionary Functions
以下の blockquote部分は上記出典ページの段落、直後の日本語は内容の拙訳です。
拙訳への具体的な「ちげーよバカ!」な突っ込みは大歓迎です。
※ 万一のトラブルは、出典サイトはもちろん、(たとえそれが僕の拙訳のせいだとしても) 一切関知しませんのであしからず。

素晴らしいカスタム関数を発表してくれた sixfriedrice.com の Jesse Antunes / Geoff Coffey に感謝します。


Since many people were impressed with my named parameters article, I decided to write up another post about the dictionary functions. Actually in all fairness I think three people actually liked it. Vincenzo Menanno, Chris Wack and Sam Barnum this post’s for you!

“named parameters (名前付きパラメータ)” 記事 への皆さんの食いつきがなかなかにすばらしいので、”the Dictionary functions” についての別の post を書くことにしました。
まあ、公平にみて、3人の人たちがこれを気に入ってくれると考えています。
Vincenzo Menanno, Chris Wack and Sam Barnum この post は君たち向けです!

Note: This article was revised November 23, 2007. I added the handyDictReplace function. -Geoff

Note: この記事は、2007/11/23 に改訂しました。
重宝な DictReplace 関数を付け足しました。 – Geoff

First I must warn you, I have left the names of the custom functions the same as the functions we use internally. This means they may seem a little obtuse so feel free to change them. I’m also not getting to in-depth into how they actually work because it could take an extra 5 pages or so (yea I know Geoff… I’m lazy… deal with it). I’m sure most of you will get them pretty quickly despite my inept explanations. Oh yea, I also suggest going back and reading the named parameters post before getting into this post otherwise it probably won’t make much sense.

Enjoy…

まず、最初の注意として…
内部的に使っているカスタム関数の名前はそのまま残しました。
ちょこっとダサイかも知れませんので、自由に変更してください。
それに、どのように振る舞うかの詳細についてまでは触れていません。
そこまでやると、簡単にもう5ページくらいかかってしまうので…はいはい面倒くさがりでごめんね。
ほとんどの方は、私のダサダサな説明などいらないくらいにサクっとおわかりになるでしょうし。
そうそう、 以前に post した “named parameters” の記事についても読んでいただいておいた方がよろしいでしょう。
じゃないと、あんまわからない話になってしまうかも。

楽しんでください…

Note: For the duration of this article I will refer to the custom functionPassParameter( name ; value ) in my previous post as #( ). This saves me 12 key strokes and won’t confuse me because that’s what I call it internally.

Note; 以前 “PassParameter ( name ; value )” として紹介したカスタム関数を#( )としています。こいつのおかげで、12キーストローク楽になりましたし、関数の内部で使っているので別に自分は混乱しないです。( bison 注:2011/02/12 21:09:18 修正しますた。by 今泉さんのありがたいツッコミ)

Using a Dictionary in the Script Result

スクリプト結果で、Dictionary を使う

I actually posted this in the comments of the Named Parameters post. The idea here is that you can not only use the named parameter idea in your script parameters but in your script results as well. So just place your dictionary values in the script result dialog of the Exit Script script step and you’ve go yourself named script results. I like to create a little shortcut to access them like so:

さて、これについては、”Named Parameters” の記事のコメントで post しました。
このアイデアがここで意味するものは…
named parameter のアイデアは、スクリプトパラメータだけでなく、スクリプト結果でも同様に使えるんだよ…ということです。
ですから、スクリプト終了のスクリプトステップの スクリプト結果のダイアログに、あなたの dictionary の値を置いたものをスクリプト結果と名付けて処理を進めれるわけです。
私は、以下のようなちょっとしたショートカットを作るのが好きです;

Name: #R ( name )

Definition:

DictGet ( Get (ScriptResult) ; name )

Checking for a Name in the Dictionary

Dictionary の中の名前をチェックする

There’s also a point where you may want to check if your dictionary contains a certain value. You could do this by simple using your DictGet() custom function on your Dict. By design, a call to the DictGet() will return empty if the name you are looking for isn’t there. That’s when I made DictContains?

また、「特定の値が あなたの dictionary の中に含まれているかどうか」をチェックしたいときもあるでしょう。
これは、シンプルに あなたの Dect について、DictGet ( ) カスタム関数を使うことで可能です。仕組みとして、あなたが探しているものがそこに無ければ、DictGet ( ) をコールすると、空値が返ります。
それで、DictContains? を作ったのです。

Name: DictContains? ( dict, name )

Definition
Let (
 pattern = "<:" & name & ":=";  Position(dict; pattern; 1; 1) > 0
)

All this is doing is checking the dictionary structure for the name of the value you are looking for and returning true if it finds the value and false if it doesn’t.

これが行うことのすべては、あなたが探している値の名前で、dictionary 構造 をチェックして、存在すれば true を返し、存在しなければ false を返すということです。

Note: This will not find any nested dictionary values. So if you were to store a dictionary within a dictionary ie. #( “Account” ; #( “Name” ; “Jesse” ) & #( “Job” ; “Writing confusing custom functions” ) ) you wouldn’t be able to use the DictContains? custom function to see if Job is in the dictionary because it is inside the account dictionary.

Note: 入れ子になった distionary の値は見つけられません。
ですから譬えば…
#( “Account” ; #( “Name” ; “Jesse” ) & #( “Job” ; “Writing confusing custom functions” ) )
といった dictrionary において、”Job” が dictionary にあるかどうかをチェックするのに
DictContains? を使うことはできません。
なぜなら、”Job” は、Account dictionary の内部に存在するからです。

Removing an Entry from a Dictionary

Dictionary から エントリを削除する

You never know when, but there will be a point where you think… “Man, I wish I could remove a value from my dictionary.” Well, maybe you won’t… but I wrote this thing anyway. If you happen to bump into this situation, you can use the nifty function below. DictRemove() simply removes the dictionary name/value pair specified from the dictionary passed in.

いつとは言えませんが、こう考えることもあるでしょう。
「なあ、オイラの dictionary の中から値を削除したいんだけど…」
…まあ、ないかもしれませんが…とにかくそれについて書きました。
もし、ばったり、そんな状況に出くわしたなら、下記の気の利いた関数を使うことができます。
DictRemove ( ) は、特定の name/value のペアを、受け渡された dictionary からシンプルに削除します。

Name: DictRemove ( dict , name )

Definition:

Let(
[
 pattern = "<:" & name & ":=";  entry_start = Position( dict ; pattern ; 1 ; 1);  entry_end = Position( dict ; ":>" ; entry_start + 1; 1);
 dict_beginning = If( entry_start > 0 ; Left ( dict ; entry_start - 1 ) );
 rest_of_dict = Middle( dict ; entry_end + 2 ; 999999 );
 new_dict = dict_beginning & rest_of_dict
];

If( entry_start > 0 ; new_dict ; dict )
)

Replacing an Entry in a Dictionary

Dictionary のエントリを置換する

This function is primarily for convenience. It combines DictRemove with a new entry to effectively replace a value in the dictionary in one shot:

この関数は、やたら便利だったらありゃしません。
DictRemove と新エントリを結合して、一発で dictionary 中の値を効果的に置き換えます。

Name: DictReplace ( dict, name, value )

DictRemove(dict, name) & #(name, value)

Returning the Top Name in a Dictionary

Dictionary 中の Top Name を返す

This custom function was designed to return the name of the first name-value pair in the dictionary. Nothing too special, but I if used in conjunction with the DictRemove() function above, you can pop off the top value of the dictionary with ease.

このカスタム関数は、dictionary 中の 最初の name/value のペアの name を返します。
特別なことは何もしていませんが、上記の DictRemove ( ) 関数と連携させて使うと、簡単に、最初の値を消すことができます。

Name: DictFirst( dict )

Definition:

Let(
   [startValue = "<:";    endValue = ":=";    positionOfStartValue= Position( dict ; startValue ; 1 ; 1 );    endOfStartValue= If( positionOfStartValue > 0 ; positionOfStartValue  + Length(startvalue); -1 );
   beginningOfEndValue= Position( dict; endValue; endOfStartValue; 1 );
   found = If( beginningOfEndValue > -1 and endOfStartValue > -1 ; True; False );
   lengthFoundValue = beginningOfEndValue - endOfStartValue;
   foundValue = Middle( dict; endOfStartValue ; lengthFoundValue )];

   If( found ; foundValue ; "" )
)

Adding to a Dictionary

Dictionary に追加する

This custom function is ridiculously easy. It’s really just a shortcut that looks a little more succinct then actually performing the action manually.

このカスタム関数は、バカほど簡単です。
実際に手動で行うよりほんの少し簡潔にしたショートカットです。

Name:DictAdd( dict; name; value )

Definition:

 dict & #( name ; value )

Dictionary To String

Dictionaryを文字列に

This is quite frankly my favorite custom function ever. Serioulsy, I have a ton of ridiculous functions that no one uses but me, but this is the creme de la creme. I’ll get slightly more indepth about this function because it can be a little tricky to understand. Here is the signature of the function:

これは、実際率直に言って、お気に入りのカスタム関数です。
マジに、自分以外だれが使うねん…な関数を山ほど使っていますが、こいつは、最高です。
ただ理解するのにちょこっとトリッキーかも知れないので、やや詳細に言及します。
これがこの関数の書式です。

Name: DictToString
Parameters:
Dict: A dictionary of your choosing
Format: format you would like to display the data in.

The real magic of this function comes from the Format parameter. This parameter will dictate how you want the data displayed. The function goes through each and every dictionary entry and will put it into whichever format you specific. To achieve this functionality a replace is performed on the Format. $name is replaced with the name of the dictionary entry and $value is replaced with the value of the dictionary entry. Here is the function:

この関数のキモは、Format parameter です。
このパラメータには、「どのようにデータを表示させたいか」を記述します。
この関数は、個々の dictionary エントリに対して実行され、あなたの指定したフォーマットに仕上げます。
$name は、dictionary エントリの name と、$value は、value と置き換えられます。
以下がその関数です。

Name: DictToString( Dict ; Format )

Definition:

 Let(
  [
  firstName  = DictFirst ( dict );
  rawdata = DictGet(dict; firstName) ;
  data = If( not IsEmpty( DictFirst( rawdata ) ) ; DictToString( rawdata ; Format ); rawdata );
  rest = DictRemove( dict ; firstName )

   ];
    If( not IsEmpty(firstName) ;
   Substitute(
                format;
                ["$name"; firstName  ];
                ["$value"; data ]
               )
               &
           If (
                not IsEmpty(rest);
                DictToString(rest; Format)
              )
 ; dict )
)

Let’s say your Format parameter is:
たとえば、あなたのフォーマットパラメータが以下のようだったとします。

`"$name is $value"`

and your dictionary is

そして、あなたの dictionary がこうだったとします。

`<:Jesse:=nuts:>`

the output would be

すると、出力はこうなります。

`Jesse is Nuts`

You can now basically output your dictionaries in any format you so desire. Such as…. you guessed it…. XML.

基本的に、どんなフォーマットにでも思いのままに、あなたの dictionary を出力できます。
たとえば…考えてみそ…XMLとか…

Dictionary To XML

Dictionary を XML に

So once you understand the DictToString() custom function, the DictToXML() function is just a shortcut that I wrote so I don’t have to write the funky format over and over. Here is is:

さて、DictToString ( ) を理解したところで、DictToXML ( ) 関数は、
なんども繰り返し土臭いフォーマットを書かずにすむように作った
単なるショートカットです。
それはこうです。

Name: DictToXML ( dict )

Definition:

DictToString ( dict , "<$name>$value<$name>" )

Let’s say you setup your dictionary like so #( “account” ; #( “name” ; “Jesse” ) & #( “birthday” ; “Yesterday” ) ). You’ll notice that I have put a pair of dictionaries within another dictionary named account. The DictToXML function (really the DictToString() function does the bulk of the work but you get the point) will actually iterate through the outside and inside dictionary and output the following:

さて、あなたの dictionary を

#( “account” ; #( “name” ; “Jesse” ) & #( “birthday” ; “Yesterday” ) )

と設定したとします。
ふたつの dictionary をアカウントという名前のもうひとつの dictionaryに入れたことがわかりますね。
DictToXML 関数 (ほとんどの機能を DictToString ( ) 関数が行うわけではありますが) は、外側と内側の dictionary を行ったり来たりして、以下を出力します。

<account>
<name>Jesse</name>
<birthday>Yesterday</birthday>
</account>

This can be very useful for creating tidbits of xml to post to web actions. Sweet Huh?

Webアクションに post するtidbits の XML を生成するのにピッタリだしょ?よかんべ?


  1. FileMaker – マルチプルスクリプトパラメータの受け渡し
  2. マルチプルパラメータのスクリプトへの受け渡し – 応用編
  3. FileMaker Dictionary 関数 (このエントリ)

マルチプルパラメータのスクリプトへの受け渡し – 応用編

Passing Multiple Parameters to Scripts – Advanced

以下の blockquote部分は上記出典ページの段落、直後の日本語は内容の拙訳です。
拙訳への具体的な「ちげーよバカ!」な突っ込みは大歓迎です。
※ 万一のトラブルは、出典サイトはもちろん、(たとえそれが僕の拙訳のせいだとしても) 一切関知しませんのであしからず。

素晴らしいカスタム関数を発表してくれた sixfriedrice.com の Jesse Antunes / Geoff Coffey に感謝します。


Wouldn’t it be nice if whenever you need a parameter you could just ask for it by name? Lets say that you have a create order script and you want to pass the script the name, street and zip code of the customer. If you were stuck with just the regular old FileMaker functions there ain’t no way that’s happening. But after you are done with this post, you will be able to get the name of your customer with the simple function: GetParameter( “customerName” ).

もし、パラメータを使いたいときはいつでも名前で呼び出せるとしたら、いい感じじゃないですか?
受注スクリプトがあったとしましょう。
そして、そのスクリプトに対して、顧客の名前/住所/郵便番号を受け渡したいとします。
もし、あなたが、FileMakerに元々ある関数で立ち往生しているばかりだとしたら、これはどうにもできません。
しかし、この post の内容をやっつけた後だとしたなら、シンプルな関数で、顧客の名前をとりだすことができるでしょう:
GetParameter (“customerName” )

Alright, since your interest is hopefully already piqued, I’m just going to go ahead and tell you the functions right away. There are three of them. I know that sounds like a lot but if you give me a chance to explain myself, trust me your going to love it and once you get used to them you’ll never go back.

さて、もう十分興味を刺激することはできたでしょうから、その関数の話の中身にさっさと移りましょう。
3つあります。
こう言うと大変そうでしょ?
でも、まあだまされたと思って説明を聞いてくださいな。
あまりに気に入ってしまって、これなしの世界に戻れなくなりますから。

Name:  PassParameter
Parameters:  name,  value
Formula:  "<:" & Substitute( name; ["="; "/="]; [":"; "/:"] ; [">"; "/>"]; ["<" ; "/<"]   ) & ":="                  & Substitute( value; ["="; "/="]; [":"; "/:"] ; [">"; "/>"]; ["<" ; "/<"]   ) & ":>"

Name:  DictGet
Parameters:  dict, name
Formula:  Let( [
              match="<:" & Substitute( name ; ["="; "/="]; [":"; "/:"] ; [">"; "/>"]; ["<" ; "/<"]   ) & ":=";               pstart = Position(dict; match; 1; 1);               start = pstart + Length(match);               end = Position(dict ; ":>"; start; 1);
              len = If(end = 0; 999999999; end - start)];

              If (pstart = 0; "";
              Substitute(Middle(dict; start; len); ["/:"; ":"]; ["/="; "="] ; ["/>"; ">"] ; ["/<" ; "<" ]))
)

Name:  GetParameter
Parameter:  name
Formula:  DictGet(Get(ScriptParameter); name)

These different functions are probably a little bit confusing right now so lets go through them one by one.

たぶん、これらの別々の関数を見て、ちょこっと脳みそがこんがらがっちゃったでしょうから、ひとつひとつ説明していくことにしましょう。

PassParameter( name ; value )

This custom function is your bread and butter. You use it every time you want to pass a parameter to another script. name is the name of the parameter your are passing and value is the actual text that you want to send over. So for instance if you were sending the name of your customer to a script you would use:

これが基本です。
別のスクリプトにパラメータを受け渡したいときには、これを使います。
name というのは、受け渡したいパラメータの名前で、value は受け渡したい値そのものです。
したがって、仮に、顧客の名前をスクリプトに渡したい場合はこうなります。

PassParameter( "customer" ;  "Joe Blow" )

If you want to pass multiple parameters to our order creation script would just string this custom function together using the ampersand like so:

もし、受注システムに対して、複数のパラメータを受け渡したいのなら、& (アンパサンド) を使って以下のように繋げて書けばいいわけです。

PassParameter( "customerName" ;  "Joe Blow" ) &
PassParameter( "street" ; "123 Any St." ) &
PassParameter( "zip" ; 85282 )

How it works: PassParameter() turns the name, value pairs that you pass in into a special format so that they are easy to manage. It basically puts two special characters in front of the name, between the name and value, and after the value. Basically if you were to say PassParameter( “customerName” ; “joe blow” ), this function turns your text into:

実際の動き方:
PassParameter ( ) は、name/value のペアを、処理しやすいように特殊なフォーマットに変換します。
要は、name の前と、name と value の間と、value の後に、2文字の特殊な文字を追加するわけです。
つまり、
PassParameter( “customerName” ; “joe blow” )
と書いたら、返ってくるのは…

<:customerName:=joe blow:>

or in the case of multiple parameters as above it would look like this:

先述の複数のパラメータ例の場合は、以下のような感じになります。

<:customerName:=joe blow:><:street:=123 Any St.:><:zip:=85282:>

This construct of name and value pairs is what we refer to as a dictionary. This becomes important because our next function operates on a dictionary. You’ll notice in the actual definition of the function PassParameter() that I do a couple of substitutions. I use this process to escape the different characters that I use in my delimiters so that my scripts won’t break when you send in those same characters. Don’t worry though, when I get them back out I remove any extra characters that I added.

この name/value のペア構造を dictionary として参照させているわけです。
これは大変大切なことです。
次の関数は、この dictionary を操作する関数です。
PassParameter ( ) の定義式を見れば、二度ほど substitute をしていることがわかりますね。
このプロセスは、デリミタ(区切り記号) として使っているのと同じ文字列をパラメータの内部で使っても、スクリプトが破綻しないように、別の文字列にエスケープするためのものです。
余計な文字列は最終的には除去されますから、ご心配なく。

DictGet( dict, name)

The dict parameter in this custom function is, yup you guessed it, short for dictionary. The second parameter, ‘name’, is just the name of a value that you would like to get out of the dictionary. So if you were to execute the following code:

このカスタム関数内の dict という引数は、(はい!もうわかりましたね!)、dictionary の略ですね。
2番目の引数の name は、dictionary から取り出したい値の名前です。
ですから、もし以下のコードを実行すると…

DictGet( "<:customerName:=joe blow:><:street:=123 Any St.:><:zip:=85282:>" ; "customerName" )

It would return “Joe Blow”. On it’s own this DictGet function doesn’t seem that useful but it is the workhorse of the three functions.

How it Works: DictGet() actually works as a basic text parser. It takes the name that you pass in and turns it into the format you would expect in the dictionary. If the name passed in is “customerName”, then it would be turned into “<:customerName:=”. The we take that weird looking text and search for it in the dictionary. If we find the weird string in the dictionary, then we return the value for it (”joe blow”, otherwise we return an empty string (””). Pretty neat huh?

“Joe Blow” が返ります。
DictGet 関数は、これ自身のみではさほど役に立つとは思えないでしょう。
しかし、DictGet 関数は、くだんの3つの関数の間で馬車馬のように働いてくれるのです。

実際の動き方:
DictGet ( ) は、基本的なテキストパーサとして働きます。
name を受け取ると、dictionary に対して、よき案配のフォーマットに変換します。
渡された name が “customerName” だとすると、
“<:customerName:=”
と変換されます。
そしてこの妙ちくりんなテキストを、dictionary の中で探します。
dictionaryの中に このへんてこテキストを見つけた場合、”joe blow” という値を返すわけです
(見つからなければ、空値 “” が返されます)
なかなかイケてるでしょ?

GetParameter( name )

This is the function you would use whenever you are trying to access data that was passed in using the PassParameter() function. It’s is specifically designed to operate on a script parameter that contains a dictionary. It actually just pulls the value of the name you give it, out of the script parameter using the DictGet() function. Very Simple…. not a whole lot going on here.
Now that you have a pretty good understanding you are pretty much ready to enter into the world of named parameters. Once you get used to using these little gems, I am positive that you will never be able to go back to plain old vanilla script parameters ever again. There are a couple more benefits to using these functions such as using named values in your script results, nesting parameters and accessing multiple occurrences that I will probably get into a later date. For now… I hope these functions help make FileMaker Development a little easier for you.

PassParameter ( ) 関数を使って受け渡されたデータにアクセスしたいときに使います。
dictionary を内包するスクリプト引数を操作するため専用に作成しました。
DictGet ( ) 関数を使って、スクリプト引数から、与えられた name にひもづく値を引き出すわけです。
すごくシンプル。なんちうこたない。
さて、なかなかいい感じで理解できたなら、named parameter の世界に入る準備はいい感じでOK ということです。
いったん、これらのちょっとしたテクを使うのに慣れると、もう、あの古式ゆかしいペラッペラに薄っぺらな標準のスクリプト引数に二度と戻る気はさらさらなくなることでしょう。
これらの関数を使うことで、他にも、二三の恩恵に浴することができます。
スクリプトの結果から 名前で値を引っ張りだしたりとか、入れ子のパラメータからとか、後日言及する複数のオカレンスへのアクセスとか…ね。
とりあえず、これらの関数が、あなたの FileMakerでのデータベース開発を少しでもラクチンにすることを願います。

More About Dictionaries: If you would like to get a little more in-depth into these functions there is a second post that adds functionality to this idea here:FileMaker Dictionary Functions.

NOTE: We had a couple of good comments from some of our early release readers. Genx who blogs on FileMakerMagazine.com added that he thought it would be much more visually appealing and easier to use XML style tags. I can’t remember the exact reason why I didn’t go this route… I am pretty sure it was because I wanted to have two delimiters at each break point in the name/value pair. He did convince us to change the names of the functions from our more nondescript names ( #() #P() ) we started with so that it would be easily understood what each one did. Another useful tip came from Fitch ofpre1.com, who pointed out that another similar name/value pair implementation can be seen in Back Magic from SeedCode.com

dictionary 関連のより詳しい話:
これらの関数についてもっと詳しく知りたい場合、下記の second post で、ここのアイデアの機能追加発展版な記事が読めますぜ。
FileMaker Dictionary Functions

日本語 拙訳

Note:初期版読者からの 良きコメントが、ふたつみっつありました。
FileMakerMagazine.com の blog をやっている Genx からは…
XMLスタイルタグを使えば、もっと見た目で分かりやすくて訴求力のある感じになるんじゃね?…と。
今となってはなんでそのルートに行かなかったのかを思い出せないのですが… おそらくは、たぶん name/value ペアのブレークポイント毎に、2文字のデリミタを差し込みたかったんだと思われます。
また彼がそうしろというのがもっともなので、最初 #() #P() とかいう何なんだかわからない記述にしていたこれらのカスタム関数の名前を、何をするものなのか分かるような名前に変えることにしました。

もうひとつのナイスコメントは、pre1.com の Fitch でもって…
似て非なる name/value ペアの実装方法を指摘してくれました。
Back Magic from SeedCode.comで見られます。


  1. FileMaker – マルチプルスクリプトパラメータの受け渡し
  2. マルチプルパラメータのスクリプトへの受け渡し – 応用編 (このエントリ)
  3. FileMaker Dictionary 関数