Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Page 23/248: « 19 20 21 22 23 24 25 26 27 »

Unityのランチャーに沢山Firefoxの項目を追加する代わりにサブコマンド?にした - Jul 29, 2012

複数のプロファイル、複数のバージョンを検証用に用意しないといけなくて、簡単に使い分けられるような環境を作る必要があるのです。

  1. Unityのランチャー上にある「Firefox ウェブ・ブラウザ」を右クリックして、「ランチャーに常に表示」のチェックを外す。
  2. /usr/share/applications/firefox-custom.desktopとして以下の内容でファイルを作成する。

    [Desktop Entry]
    Version=1.0
    Name=Firefox Web Browser (custom)
    Name[ja]=Firefox ウェブ・ブラウザ (custom)
    Comment[ja]=ウェブを閲覧します
    GenericName=Web Browser
    GenericName[ja]=ウェブ・ブラウザ
    Exec=firefox %u
    Terminal=false
    X-MultipleArgs=false
    Type=Application
    Icon=firefox
    Categories=GNOME;GTK;Network;WebBrowser;
    MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall;
    StartupWMClass=Firefox
    StartupNotify=true
    X-Ayatana-Desktop-Shortcuts=NewWindow;Sub;ESR;Stable;Beta;Nightly;
    
    [NewWindow Shortcut Group]
    Name=Open a New Window
    Name[ja]=新しいウィンドウを開く
    Exec=firefox -new-window
    TargetEnvironment=Unity
    
    [Sub Shortcut Group]
    Name=Sub
    Exec=firefox -no-remote -p sub
    TargetEnvironment=Unity
    
    [ESR Shortcut Group]
    Name=ESR
    Exec=/home/piro/opt/firefox-esr/firefox -no-remote -p esr
    TargetEnvironment=Unity
    
    [Stable Shortcut Group]
    Name=Stable
    Exec=/home/piro/opt/firefox-stable/firefox -no-remote -p stable
    TargetEnvironment=Unity
    
    [Beta Shortcut Group]
    Name=Beta
    Exec=/home/piro/opt/firefox-beta/firefox -no-remote -p beta
    TargetEnvironment=Unity
    
    [Nightly Shortcut Group]
    Name=Nightly
    Exec=/home/piro/opt/firefox-trunk/firefox -no-remote -p trunk
    TargetEnvironment=Unity
    
  3. ファイルに実行権限を設定する。
  4. Dashホームから「Firefox ウェブ・ブラウザ(custom)」を探して、実行する。
  5. ランチャーに表示されたアイコンを右クリックして「ランチャーに常に表示」にチェックを入れる。

これで、アイコンを右クリックして各プロファイルで起動できるようになった。

ユーザのホーム以下にファイルを作成して複数のアイコンを登録してみたりとか色々試みてたんだけど、自分で付けた名前と表示名が一致しないとか色々動作が怪しくて、結局このような所(グローバルな設定ファイルとして作成)に落ち着いた。

2014年8月21日追記。Ubuntu 14.04LTSで、Thunderbird用の物も作った。

[Desktop Entry]
Encoding=UTF-8
Name=Thunderbird Mail (custom)
Name[ja]=Thunderbird電子メールクライアント (custom)
Comment=Send and receive mail with Thunderbird
Comment[ja]=メールの読み書き
GenericName=Mail Client
GenericName[ja]=電子メールクライアント
Keywords=Email;E-mail;Newsgroup;Feed;RSS
Keywords[ja]=Eメール;イーメール;mail;e-mail;email;メール;電子メール;ニュースグループ;ネットニュース;RSS;フ>ィードリーダー;書く;読む;Mozilla
Exec=thunderbird %u
Terminal=false
X-MultipleArgs=false
Type=Application
Icon=thunderbird
Categories=Application;Network;Email;
MimeType=x-scheme-handler/mailto;application/x-xpinstall;
StartupNotify=true
Actions=Compose;Contacts;AnotherProfile

[Desktop Action Compose]
Name=Compose New Message
Name[ja]=新しいメッセージの作成
Exec=thunderbird -compose
OnlyShowIn=Messaging Menu;Unity;

[Desktop Action Contacts]
Name=Contacts
Name[ja]=連絡先
Exec=thunderbird -addressbook
OnlyShowIn=Messaging Menu;Unity;

[Desktop Action AnotherProfile]
Name=Start with Another Profile
Exec=thunderbird -no-remote -p sub
OnlyShowIn=Messaging Menu;Unity;

Firefoxの物を作った時と微妙に様式が変わっているようだ。

Ubuntuでのgeditとvimの初期設定 - Jul 23, 2012

自分がGNOME3ベースの環境でgeditを使う時に最低限これだけはやっとくという設定。

  • タブ幅4、自動バックアップなし。
  • フォントはシステムフォントではなくIPAゴシックあたりをダイレクトに指定(これは必要ないか?)
  • シンタックスハイライトで太字にならないようにする。 /usr/share/gtksourceview-3.0/styles/classic.xmlをclassic-nobold.xmlとかなんとかいう名前でコピーして、vimで開いて:%s/ bold="true"//して、スタイルの名前を書き換えて上書き保存して、geditの設定で色のスキームの欄からファイルを選択して一覧に追加して選択する。 ( Gedit の色設定。 - 研究日誌。のやり方に従った)
  • エンコーディング自動判別用の設定を日本語環境向けに変更する。 gsettings set org.gnome.gedit.preferences.encodings auto-detected "['UTF-8','CURRENT','SHIFT_JIS','EUC-JP','ISO-2022-JP','UTF-16']"で、自動判別がまともに動くようになる。 (geditの文字化けを解消する (GNOME3) - 憩いの場のやり方に従った)
  • プラグインを入れる。設置場所は ~/.local/share/gedit/plugins/ 以下(GNOME2の頃に書かれたような古いドキュメントでは ~/.gnome2/gedit/plugins/ 以下に置くように書いてあるけど、GNOME3では .local 以下に置くようになってる)。
    • Regex Search and Replace(正規表現での検索と置換を可能にする): Gedit/Plugins - GNOME Live!の「Regular Expression Plugin」の所からダウンロードできる。

あと、vimの設定も。というか、Ubuntuの方の設定なんだけど。

  • sudo apt-get install vimでインストール。
  • sudo update-alternatives --config editorで設定のリストが出るので「vim.basic」を選択する。

vimを使っているのは、nanoはGNOME標準のキーバインドとも何とも異なるワケ分からない操作体系のようなので、それよりはまだlessとかと操作が共通している部分が多いvimの方がマシ……という判断による。

ページ内の見出し一覧をMarkdownのリスト形式で出力するbookmarklet - Jul 05, 2012

前に似たような事をやった気がするけど。

javascript:

var tab  = '   ',
    min = prompt('Input minimum level of the headings (default=1)');

function tabs(n) {
  var ret = [];
  for (var i = 0; i < n; i++) ret.push(tab);
  return ret.join('');
};

function collectHeadings(minLevel) {
  var rawHeadings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');
  var headings = [];
  var heading, node;
  for (var i = 0, maxi = rawHeadings.length; i < maxi; i++)
  {
    node = rawHeadings[i];
    heading = {
      node: node,
      id: node.id,
      label: node.textContent,
      level: parseInt(node.localName.charAt(1))
    };
    if (heading.level >= min)
      headings.push(heading);
  }
  return headings;
}

function generateList(headings) {
  var list = [],
      h,
      id,
      item,
      nest = 0;
  for (var i = 0; i < headings.length; i++)
  {
    h = headings[i];
    id = h.id || h.node.parentNode.id || h.node.parentNode.parentNode.id;
    item = (id) ? '['+h.label+'](#'+id+')' : h.label ;
    if (i > 0) {
      if (h.level > headings[i-1].level) {
        nest += 1;
      } else if (h.level < headings[i-1].level) {
        nest -= 1;
      }
    }
    if (nest == 0) {
      list.push(' * '+item+'\n');
    } else {
      list.push(tabs(nest)+'* ' + item + '\n');
    }
  }
  return list.join('');
}

var headings = collectHeadings(Math.max(1, min));
var list = generateList(headings);
if (list) window.open('data:text/plain,'+encodeURIComponent(list));

見出しレベルの関係がちゃんとしてないとうまく動かない。あとsection/headingのネストには対応してない。

結婚しました - Jul 03, 2012

一部の方や会社では報告済みですが、結婚しました。お相手は一般人の女性です……というと芸能人っぽくてウケるかなと思いましたが寒いだけでした。ともかく、誰と結婚したのかという情報は諸事情により今の所完全公開にはしたくないというのが両名の意向ですので、両名をご存じの皆様方におかれましては、ブコメやらTweetやらで二人の名前を併記して「おめでとう」とウッカリ発言してしまわれることのないように、何卒ヨロシクお願い致します。


時間外受け付けに書類を提出して、ちゃんと受理されるかどうかドキドキハラハラだった(指輪に「婚姻届の提出日」ということで日付を入れてしまった以上、手続きやり直しなんて事になったら、後で指輪を見返した時に「この日付なんなの」ってなってしまう……)のですが、昼間に住民票を取りに行ったらちゃんと受理されてました。よかったです。

で、結婚にあたって姓を妻側にしたのですが、特に社会人になって以降は「下田」と呼ばれる機会よりも「ぴろたん」と呼ばれる機会の方が圧倒的に多かったため、いまいち実感が湧きません。早速免許の訂正の手続きに行ってみたら、窓口で新しい苗字で呼ばれて一瞬「あー誰か呼ばれてるな」って思ってしまいました。慣れるまで時間がかかりそうです。

ところで、姓を妻側にするというと婿入りなのかとかなんとか色々思われるようなのですが、単に姓が妻側になっただけで、それ以上のことは何も無いです。といっても知らない人にはよくわからないと思うので、姓を妻側に変更するとはどういう事なのか?を簡単に解説してみたいと思います。ポイントは以下の3点です。

  • 姓を妻側にする、とはどういう事なのか?
  • 姓を妻側にする事と、婿養子と、婿入りとはどう違うのか?
  • 本籍地はどこになるのか? どこにするべきなのか?

まず戸籍というのは、代表者にあたる筆頭者および他のメンバーからなる家族を1つのユニットとした単位で存在しています。大抵の場合は、両親+その子供というセットになっています。

(図:両家の戸籍)

さて、ここで下田家の長男と上田家の長女が結婚するとします。この時、新しいユニットが誕生することになって、それ用の戸籍が新たに作られます。新しく作成された戸籍には、各人のメタ情報として元の戸籍への参照が付与されます。また、古い戸籍にあるその人の情報には「除籍(この人の情報はこの戸籍ではもう管理されていない)」というタグが付き、新しい戸籍への参照が付与されます。

(図:新しい戸籍)

このようにして戸籍と戸籍が相互リンクされるため、例えば下田カズユキさんやヒロシ君が死んだ時には、遺産を相続できる人がどれだけいるんだ?という事を辿っていって調べられるわけです。

この時決めないといけないのが、新戸籍の「筆頭者」と「本籍地」の2点です。

筆頭者とは、文字通り、その戸籍の最初に名前が書かれてる人の事です。新戸籍に記載される人達の姓は、筆頭者の姓になります。つまり、夫の姓を名乗りたければ夫が筆頭者になるし、妻の姓を名乗りたければ妻が筆頭者になります。はい、僕の場合はそういうわけなので、戸籍上は妻が筆頭者になっています。

(図:新しい戸籍(妻が筆頭者))

新しく作る戸籍で誰の名前を最初に書くのかを決めなくてはならなくて、その時選んだ方の人の姓が、新戸籍に属してる人全員の姓になる。制度上は、ただそれだけ。「夫の姓になったんだから妻は夫の一族の一員になったのだ」とか、「妻の姓になったんだから夫は実家を捨てて妻の家に尽くさねばならないのだ」とか、言うのは勝手ですが、それは制度とは何も関係のない話だということです。

他方、婿養子の場合は、戸籍同士の関係がちょっと違います。

まずヒロシ君と上田アキオさんの養子縁組手続きをして、ヒロシ君が上田家の養子になります。この時、元の下田家の戸籍からはヒロシ君は除籍されます。

(図:ヒロシ君の養子縁組)

次に、ヒロシ君とヒロコさんで結婚して(※養子と実子は結婚できます)新しい戸籍を作ります。

(図:新しい戸籍)

この時、ヒロシ君は既に上田姓になっていますし、ヒロコさんも当然上田姓なので、どっちが筆頭者になっても新戸籍の姓は上田になります。よって、ヒロシ君はどっちみち、もう下田姓を名乗ることはできません。

ヒロシ君とアキオさんの間には養子・養父としての法的な親子関係もあります。なので、ヒロシ君にとってアキオさんは「義理の父」ではなく「養父」ということになります。「実子の配偶者」ではなく「養子」として、遺産の相続等、実子と同等の権利があるわけです。

これがいわゆる婿養子です。なお、実際には養子縁組と婚姻の手続きはどっちを先にやってもいいそうです。ここでは説明が簡単な方ということで、養子縁組後に婚姻する場合を説明しました。

婿入りというのは、これら制度上のやり取りとは関係のない慣習的な言葉です。かつての制度やしきたりを現在の制度に照らし合わせると、上記の「婿養子」に近いものを指していたっぽいです。ということで、僕が婿入りという言葉を使う時は、婿養子と同じ物を指していると思って下さい。(もっと言うと、「婿養子」も慣習的な言葉で、制度上はただの「妻の実家の養子になっている」という状態です)

ちなみに、法律の用語における入籍とは、上記の養子縁組手続きにおいて夫が妻の実家の戸籍に入る、あるいは妻が夫の実家の戸籍に入る事を言うそうです。なので、僕のケースは入籍にはあたらないわけです。「結婚」のもってまわった言い回しとして「入籍」を使うという風潮があります(この用法は俗語として一般的なので、最近は辞書にも載ってるみたいです……)が、そういうわけなので、僕は入籍という表現は意地でも使わないでおきます。

最後に、ここまであえて触れずにいましたが、本籍地についても説明します。

昔は戸籍と住民票が一体だったとかで、戸籍は住所ベースの管理になっていますが、戸籍と住民票が別々になっている現在では、本籍地とは単に「戸籍を管理する自治体がどこなのかを示す」という事以上の意味は無いそうです。居住地と無関係に決められるので、夫側実家と同じ本籍地にしてもいいし、妻側実家と同じにしてもいいし、千代田区1の1で皇居を本籍地にしてもいい(戸籍を取り寄せる時は千代田区の区役所に行く)し、スカイツリーでも屋久島でもなんでもオッケーです。

よく「本籍地はどっちかの実家と同じにしておいた方がいい」という話がありますが、これは、単に「管理する自治体が1箇所にまとまっていれば、手続きや戸籍の取り寄せがちょっとだけ楽になる」「本籍地が変わらない方の人は、本籍地が関係している登録を更新しなくて良い」というだけのことです。

仮に東京都E区の住所で新戸籍を作ったとすると、ヒロシ君が死んだ時は、東京都E区と鳥取県A市のそれぞれから戸籍を取り寄せることになりますし、ヒロコさんが死んだ場合、東京都E区と埼玉県C市の2箇所の自治体から戸籍を取り寄せることになります。これがニュートラルな状態です。

(図:2箇所に問い合わせないといけない)

埼玉県の上田家の本籍地と同じ本籍地で新戸籍を作った場合、ヒロコさんが現在属している戸籍と、過去に属していた戸籍は、2つとも埼玉県C市の役所が管理しています。なので、ヒロコさんが死んだ時であれば埼玉県C市の役所からだけ戸籍を取り寄せればOKです。でも、ヒロシ君が死んだ時は、埼玉県C市と鳥取県A市の両方から戸籍を取り寄せないといけません。二人のうち片方だけは楽になりますが、もう片方はニュートラルな状態と何ら変わりません。

(図:どちらか一方は、2箇所に問い合わせないといけないのは変わらない)

また、運転免許のように本籍地の情報がある登録情報は、本籍地が変わったら更新する必要があります。上記のように「上田家の本籍地と同じ本籍地に新戸籍を作った」場合、ヒロコさんは名前も本籍地も変わらないので免許は更新しないでオッケーです。それに対して、ヒロシ君の方は名前も本籍地も変わるので(どっちか一方だけ変わった場合もですが)免許を更新しないといけません。

僕の場合、夫側実家の本籍地で妻側の姓ってなんか違和感あるなーと思ったのと、妻側実家の本籍地で妻側の姓だとちょっと婿入りっぽ過ぎるかなーと思ったのと、いろんな意味でちゃんと独立したいなあ一人前になりたいなあという思いとで、心機一転するつもりで本籍地は敢えて既存のどちらでもない場所にしました。


どちらの実家も苗字については特に拘りは無い(家を継ぐとかそういうのは無い)ということだったので、姓については当人同士の意志でわりとすんなり決まりました。

というか、僕の元の苗字「下田」がぶっちゃけダサイというかショボいというか、敢えてこの苗字になろうという気が湧くようなものでもなく、僕自身苗字を変えられる物ならもっと格好いい苗字だったらよかったのに!と思っていたくらいだったし、妻さんにも「『下田』になるのはちょっと……」と言われてしまったしで、満場一致で妻側の姓という感じでした。

姓が変わることで色々大変なのかなーと思っていたのですが、実際なってみると、引っ越しとそれに伴う住所変更の時と気分はそんなに変わらないなあ……という感じです。事前にしなきゃいけない事なんて、元の戸籍を取り寄せて婚姻届の枠の中を埋めておくという事だけだったし。むしろ引っ越しより楽なくらいじゃないの?

元々、住所変更すら完璧にはこなしてなかった(郵便物の転送期限が過ぎて実家に連絡が行ってそれでやっと情報を更新したとかそんなのもあった)人間なので、結婚だからって気張って完璧に手続きを済ませられるわけがないのであります。なので、気がついた物からボチボチ名前を変えていこうと思っています。


……という風に思えるのは、戸籍上の名前イコール自分のアイデンティティ、という考え方をしていないからなのかもしれませんね。

僕は16で漫研に入った時にペンネームを決めて(先輩に決めてもらって)以降、13年間ずっと「Piro」の名義で色々な活動をしてきました。物心ついてから、という考え方をすれば「Piro」であった期間の方が長いくらいです。どっちかがシンボリックリンクでどっちかが本当の名前だ、というのではなく、どっちも等しくハードリンクという感覚だと思います。

よく「インターネットは仮想現実。ハンドルという仮名で、嘘の人格を装って交流する場所。そんなものにハマってないで、もっと現実を見ろ。」みたいな言い方をされるけれども、僕にとってはネットも現実の一部です。「現実」と、そこから切り離れた「非現実」があるのではなくて、ネットというインフラの上に「現実」が延長されている、そういう感じなので、僕はオフラインでもPiroという名前を使いますし、オンラインでも下田洋志という名前を使ってきました。名前毎に異なるペルソナを使い分ける、という事をしていない(つもり)のですよね。むしろ、ペルソナは名前よりも場(家だとか客先だとか)の方に結び付いている気がします。

名前が一つしか無かったら、名前が変わる事への抵抗はもっと強かったかもしれません。姓が変わった後でも変わらない、自分を自分でアイデンティファイする永続的な名前を持っていたから、それほど強い抵抗を感じずに済んだ、というのはやっぱりあるんじゃないかなと思います。それが良い事(制度に縛られない自由な感覚が養われたということ)なのか悪い事(伝統を蔑ろにすること、制度に順応「できていない」ということ、在る物に合わせるのを怠っているということ)なのかは分かりませんが。


以上、結婚のご報告でした。

漫画、連載 - Jul 02, 2012

「描かないマンガ家」の3巻で、マンガ家デビューを目指す若手が3話連載のチャンスをもらって、好評なら長期連載ということだったんだけど不評で予定通り3話でおしまいになって、長期連載になるチャンスを逃して涙する、という話があって、見てていたたまれなくなった……

日経Linuxで連載中のシス管系女子も、実は当初はとりあえず3回くらいでっていうことで話をもらってて、3話目の最後に「つづく」って入れていいのか良くないのか(っていうか話的にちゃんときりのいい所で終わらせなきゃなんじゃないのかとか)悩んでたりしたんだけど、なんか特にそこを突っ込まれることもなく4話5話と続いて、今に至ってる。それでもうすぐ1周年ですよ。感慨深い。

でもそれはあくまで技術系の雑誌(専門誌?)の連載「記事」としての評価なのであって、「雑誌の連載漫画作品」というのとはまたちょっと違うのかな-、と思う所もある。画力も話作り(技術解説の部分ではない、エンタテインメントとしての部分)も取り立てて優れているわけではない……というか、むしろ下手な方だと思うし。そこら辺、純粋に画力や話作りで勝負する「漫画業界」に比べるとずいぶんユルく甘やかされてるんだと思う。「描かないマンガ家」「バクマン」等のマンガ家漫画を見てると、こんなんで連載やらせてもらってるのが忍びないです。

という事に引け目を感じるくらいなら、上達することに一生懸命になれよって話ですよね……

シス管系女子 第11話「システムの負荷を把握しよう」 - Jun 18, 2012

発売から少し経ってしまってますが、日経Linuxにて連載中のコマンドライン系豆知識漫画「シス管系女子」の第11話が掲載されている日経Linux 2012年7月号が発売されています。 (本編中の1コマ) 今回はtopの紹介のつもりで始めたのですが、成り行きでload averageとkillについても説明してしまいました。

ところで、日経BP記事検索サービスを今見てみたら、10話だけでなく11話も単品でご覧頂けるようになってました。シス管系女子だけ見てみたい!という方はこういう手もありますよということで……(PDFのダウンロード購入ではなく、オンラインビューワで見る形式だそうですが)

今回が11話という事は、次回は連載12回目で、ついに1周年ですね。まぁ、何か特別な事をやるわけでもなく、普通に11話の続きでtopとload averageの話の補足をやるつもりなのですけれども。

そういえば、ネタのチョイスについては特に指示があるわけでなく、ある程度普遍的な話題であればOKという枠だけ示していただいていて、毎回僕の方でとりあげたいネタを好き勝手に考えています。もし「こういうのもやってくれ!」というご要望がございましたら、コメント等で是非ともお寄せいただけましたら幸いです(本誌のアンケート葉書ならなお良し)!

JSDeferred - Why this code doesn't work? - Jun 12, 2012

I got a mail.

I've started to use jsdeferred 2 days ago and I'm really really happy with it because I consider it's really easy to use, light and it looks very powerfull. Anyway, I have one little doubt I hope you can help me about.

Here's the thing, I would like to deferredize some functions to use in some chains, but I haven't figured out what's the best way to get it, I put you a little example

If I try something basic like this:

function my_deferred(data) {
  var deferred = new Deferred();
  deferred.call(data);
  return deferred;
}

function main() {
  Deferred.define();

  my_deferred("foo").
    next(function(data) {
      console.log(data);
    });
}

The chain is not executed (I don't know why). But if I change to something like this, using setTimeout, it works:

function my_deferred(data) {
  var deferred = new Deferred();
  setTimeout(function() {
    deferred.call(data);
  },1);
  return deferred;
}

function main() {
  Deferred.define();

  my_deferred("foo").
    next(function(data) {
      console.log(data);
    });
}

The question is, wouldn't it be possible to get the right behaviour of the chain without using setTimeout? I would like to deferredize some functions without the penalty of using setTimeout.

You should use Deferred.next() ( it is available as a global function next() if you use Deferred.define() ) instead of setTimeout(), like:

function  my_deferred(data) {
  var deferred = new Deferred();
  Deferred.next(function() {
    deferred.call(data);
  });
  return deferred;
}

Deferred.next() works just like setTimeout(), but in most cases it works faster than setTimeout().

deferred.call() just calls the next job which is registered as a callback function given to its .next() method. So, you have to call deferred.call() after you register the next job.

However, In your case, any "next job" has not been registered yet when you call deferred.call(). As the result, the "next job" registered after deferred.call() was called won't be called by anyone.

function my_deferred(data) {
  // (3) Now, we are in this function.
  var deferred=new Deferred();
  deferred.call(data); // (4) deferred.call() is called, then
                       //     the next job ( registered via
                       //     deferred.next() ) is also called.
                       //     However, it has not been registered yet.
                       //     As the result, nothing happens.
  return deferred; // (5) We return the deferred object and
                   //     exit from this function.
}

function main() {
  // (1) Starting position of this event loop.
  Deferred.define();

  // (2) The function is called.
  my_deferred("foo").
    next(function(data) {
      // We never come here!!
      console.log(data);
    }); // (6) You register the next job to the returned deferred
        //     object, via its next() method. However, because
        //     deferred.call() was already called, the job will
        //     never be called by anyone.
  // (7) End of this event loop.
}

Instead,

function my_deferred(data) {
  // (3) Now, we are in this function.
  var deferred=new Deferred();
  Deferred.next() {
    // (8) Now, the next event loop is started.
    deferred.call(data); // (9) deferred.call() is called, then
                         //     the registered next job is also called.
  }); // (4) We just reserve the task for the next event loop.
  return deferred; // (5) We return the deferred object and
                   //     exit from this function.
}

function main() {
  // (1) Starting position of this event loop.
  Deferred.define();

  // (2) The function is called.
  my_deferred("foo").
    next(function(data) {
      // (10) We are here!
      console.log(data);
    }); // (6) You register the next job to the returned object.
  // (7) End of this event loop.
}

As above, you must register the next job to the deferred object before its call() is called.


ちょよんごさんによると、このメールの送り主の人(ここでは省いたけど、WebGL用のスクリプトを書いてるそうです)は、JSDeferredを使ってるとおぼしき開発者に手当たり次第質問を投げてるらしい。そんなこととはつゆ知らず「僕作者じゃないんだけどなあ」と呑気にちょよんごさんに転送してしまって、余計なストレスをかけてしまったようなので罪滅ぼしと思って真面目に返信してみた。伝わってるかどうかは分かんないけど。

これはJSDeferredの結構典型的なハマリ所だと思う。XMLHttpRequestとかNode.jsの非同期なメソッドみたいに、コールバック関数が必ず次以降のイベントループで呼ばれる物に対してであれば、このメールの送り主の人が書いてるような

var Deferred = require('jsdeferred').Deferred;
var fs = require('fs');

function statDeferred(filePath) {
  var deferred = new Deferred();
  fs.stat(filePath, function(error, stats) {
    if (error)
      deferred.fail(error);
    else
      deferred.call(stats);
  });
  return deferred;
}

statDeferred('/tmp/foobar')
  .next(function(stats) {
    if (stats.isDirectory()) {
      ...
    }
  });

こういう流れの書き方で何も問題ない。

問題は、やらせたい処理が同期的であった場合で、

function statDeferred(filePath) {
  var deferred = new Deferred();
  try {
    var stats = fs.statSync(filePath);
    deferred.call(stats);
  } catch(error) {
    deferred.fail(error);
  }
  return deferred;
}

これでは動かないのですよね。 何故かというと、 deferred.call() は「その deferrednext() に渡された関数、という形で あらかじめ 登録されていた『次のジョブ』を実行する」物だから。 この例だと statDeferred()deferredreturn する前に deferred.call() を呼んでしまっているから、その後で次のジョブを登録しても、登録した「次のジョブ」を呼ぶ人が誰もいないわけです。

function statDeferred(filePath) {
  // (2) 関数の中に入った。
  var deferred = new Deferred();
  try {
    var stats = fs.statSync(filePath); // (3) 処理を実行した。
    deferred.call(stats); // (4) 登録済みの「次のジョブ」を実行しよう……
                          //     とするんだけど、まだ何も登録されてないので、
                          //     当然何も起こらない。
  } catch(error) {
    deferred.fail(error);
  }
  return deferred; // (5) 関数を抜けた。
}

// (1) 今のイベントループでのスタート地点。
statDeferred('/tmp/foobar')
  .next(function(stats) {
    // 「次のジョブ」の登録後に deferred.call() が呼ばれないので、ここには到達しない。
    if (stats.isDirectory()) {
      ...
    }
  }); // (6) 戻り値の next() を呼んで、「次のジョブ」を登録した(今更)。
// (7) 今のイベントループの終わり。

だから、 setTimeout() なり Deferred.next() なりを使って、 deferred.call() を呼ぶ処理を「次のジョブを登録する処理」よりも後(=次のイベントループ)に実行する必要がある。そうすれば、

function statDeferred(filePath) {
  // (2) 関数の中に入った。
  var deferred = new Deferred();
  Deferred.next(function() {
    // (7) 次のイベントループで、予約されたこの処理が始まる。
    try {
      var stats = fs.statSync(filePath);
      deferred.call(stats); // (8) 登録済みの「次のジョブ」を連鎖的に呼ぶ。
    } catch(error) {
      deferred.fail(error);
    }
  }); // (3) 次のイベントループで実行するように予約。
  return deferred; // (4) 関数を抜けた。
}

// (1) 今のイベントループでのスタート地点。
statDeferred('/tmp/foobar')
  .next(function(stats) {
    // (9) 「次のジョブ」として、この処理が始まる。
    if (stats.isDirectory()) {
      ...
    }
  }); // (5) 戻り値の next() を呼んで、次のジョブを登録した。
// (6) 今のイベントループの終わり。

……という順番で処理が進むから、期待通りに動くようになる。

どの処理が一体何をしているのか、どの関数が何を返しているのか、自分が呼んでいるメソッドは誰のメソッドなのか、といった事をちゃんと理解しておくと、この話がすっと頭に入ってくると思うんだけど、ただの構文として覚えてしまっていると、メールの送り主の人みたいに「何で動かないの……」って詰まってしまうんだと思う。

という風に偉そうな事を言ってるけど、僕自身も最初は多分ただの構文として覚えてた方で、ただ、「同期処理の時は setTimeout() なり Deferred.next() なりを使って deferred.call() を呼ぶ」という所までを「構文」として暗記していたから、結果的にはちゃんと動いてくれてたという状態だったんだと思う。その後若手IT勉強会の中でコードリーディングをやってだんだん仕組みが分かってきて、「ああなるほど、こういうことだったんだ」と理解できるようになった。

Firefox Hacks Rebootedでもいっぱい書いたけど、JSDeferredの本質は、「あらゆる処理について、その次にやらせたい仕事を next() のコールバック関数という形で後から登録できるようにする」ものだ、と僕は認識してる。「後から登録する」という都合上、この性質は非同期処理(関数を抜けた時点でまだ処理が始まっていないという種類の処理)と非常に相性がいい。けれども、非同期処理じゃないと使えないわけではない。ただ、「後から登録する」というのは、普通に順番通りに進む同期的な処理の中では行えないイレギュラーな事だから、 setTimeout()Deferred.next() を使わざるを得なくて、それで初見の人に分かりにくくなってしまう。そこがもどかしい所だ。

The priority policy of my addon projects - May 10, 2012

In recent days, I discussed on the issue about scrolling of the vertical tab bar. It made the priority policy about my addon projects clear, again. So, let's sum up them.

  • I assign the highest priority to issues I actually annoyed. Most projects were started because I wanted to use such addons. This is the main motivation to continue developing for me. In other words, when I suffer from a bug in my daily use, I'll fix it prior to other bugs, even if the mine is just trivial and the yours is very serious. After that, if I have time good enough, I'll research and fix your issues. If I've never used the feature (and I never use it in the future), then there is extremely low feasibility rating.
  • I'm negative about adding new features (especially digressive features) to existing addons. Because I currently have no plan to switch to other browsers (Google Chrome, etc.), I want to keep codes easy to follow up to future releases of Firefox. Even if the new feature looks simple, it can cost much time for maintenance in the future chronically. Long term sustainability is prior to short term convenience, for my projects. I'll reject requests which can lose maintainability or independency of the project, even if it is very useful feature, fixing serious bug, and so on.
  • I think that any addon shouldn't break features of Firefox itself without any apparent reason. For example, because the tab bar is automatically hidden in the full-screen mode (F11 key) by default, the vertical tab bar also should be done. If my addon breaks Firefox's default behavior unexpectedly, then I'll make effort on fixing it. However, if the issue is not introduced by my addon, then I often step back from it.

Because currently I have less time to develop addons, I have to apply these policies strictly. Actually, in recent days, I spend just a few days of my time per a month for my private development. Sadly I have to keep many requests pending.

However, codes of my addons are licensed under open source licenses. For example, Tree Style Tab is licensed under GPL/LGPL/MPL. You can fork, develop, or re-distribute any project based on my codes, by your hand. Your version can be better alternative for people who suffered from the issue ignored by me. (And, if it is enough reasonable, I possibly merge your changes to my repository.)

シス管系女子 第10話「ネットワーク越しにファイルをコピーしよう」 - May 09, 2012

もう1ヶ月経ってしまった……

ということで日経Linuxにてゆるゆる連載中のコマンドライン系豆知識漫画、「シス管系女子」の第10話が掲載されている日経Linux 2012年6月号が発売されています。 (本編中の1コマ) 今回はscpの紹介です。これのために改めて調べるまで、scpをナメてました自分。

日経Linuxの公式サイトからAmazonの詳細ページにリンクされてます。特集記事も面白いので、デスクトップ環境は使った事あるけど……とか、仕事でサーバを管理しなきゃなんだけど……とか、なんかWaylandとかXとか色々話題になってるけどよくわかんね……とか、そういう人はぜひ一度ご覧になってみてください。紙媒体という都合上、カッティングエッジの最新情報にはさすがに追いつきにくいのは否めないですが、その分教養が深まる読み物が色々ありますので。

あと、日経BP記事検索サービスで「まんが シス管系女子」と検索すると、過去の号に掲載された分をネットで購読(※PDFのダウンロードみたいな形式ではなく、オンラインビューワーで見る形だそうです)できる模様です。以下、現時点で出てくるバックナンバーです。

マンガだけ見てみたいけど近くの本屋に置いてないなーという方は、電車賃使って立ち読みしに行く代わりにこちらもご検討されてはいかがでしょうか。いや、マンガだけと言わず他の記事も。今号で終了してしまいましたがまつもとゆきひろ氏の記事とか、僕も楽しく読ませて頂いておりました。

ところで、単行本出ないの?って声をたまに頂きますが、全然ページ数足りてないんで……この調子だとあと2年くらいやらないと出ない気がします。(そんなに連載続くんか?)

自宅のPCから異音がするようになったのが直った - May 09, 2012

なんか先週末くらいから急に、カラカラカラというかシャッシャッシャッシャッというか、回転する物が何か別の物と当たったり擦れたりしてるような音がしだした。

寿命を迎えたPC用の冷却ファンによくある音だよな……と思って蓋開けて見てみて、CPUでもなければ筐体のでもないしということで、グラフィックカードのファンから音がしてるっぽいという事は分かった。

でもなんで急にそんな音がするようになったのか皆目見当も付かなくて、ホントに寿命なのかなーだったら困るなーと思いながら騙し騙し使ってたんだけど、一昨日あたりからカリカリいう音が絶えず出るようになっていかにもこれはヤバイという感じだったので、とりあえず電源落としてた。

今日になって、もしかして油さしたらよくなるかな?と思って潤滑油のスプレー(ノズルの先に細いストローみたいなのをさす奴)をプシュッとやってみたんだけど、部屋が油臭くなっただけで音は全然変わらなかった(擦れてる音がちょっとだけ、潤滑油のおかげか小さくなりはしたけど)。

こうなったらとことんやってやろうじゃないか、ということでまた蓋開けてグラフィックカード外してファンのとこを指でくるくる回してみたら、どうも出っ張ってる部品とかファンの周りのヒートシンク?とかに当たってるみたいで、なんで急にそんな風に当たるようになったんだろ……コンデンサが膨張してぶつかるようになったとかそういう事でもないみたいなんだけどなあ、とかなんとか思いながらヤスリで当たってたとこをゴリゴリ削り始めたところで、回転するファン自体の方に、なんか指で押すとぐにっと隙間ができてそれが広がる感じになってるとこがあるという事に気がついた。

そういう作りのものなのかなーと思ってたんだけど、ふとファンの真ん中の所にカバーみたいに貼ってあったシールをはがしてみたら、そういう作りなんじゃなくて、ヒビが入ってファンの半分が浮いてる状態になってるだけだったという事にやっと気がついた。半分は軸にくっついてて半分は軸からはがれてるという状態だったから、回転数が上がると遠心力で広がって周囲にぶつかったり、重力やら空力やらで歪んで電子部品にぶつかったりしてたみたいだった。ここに辿り着くまで1週間くらいかかってしまった……

割れたところを、軸にまで染み込まないように注意しながら瞬間接着剤を流し込んで補修したら、電源入れても擦れる音はしなくなった。やっぱりこれが原因で間違いなかった。

もうかれこれ5年くらい使ってる気がするけど、環境移行するのがめんどいのでまだまだ頑張ってもらいます。1回電源が逝ったのをわざわざ有償修理で直してもらったくらいだし……(DELLの通販で買ったマシンだから、明らかに新品買った方がコストパフォーマンス的にはいいはずだけど、それよりも同じ環境使える事の方が僕にとっては大事なのです。)

Page 23/248: « 19 20 21 22 23 24 25 26 27 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき