このブログはURLが変更になりました

新しいブログはこちら→ https://matsuu.hatenablog.com/

utf8プラグマでfat commaを使うと左辺がdecodeされるバグ(perl-5.10.2で修正予定)

id:miyagawa さんからTwitterで教えてもらったネタ。Twitterだけで完結するのはもったいないのでここに書いておく。

元ネタはこちら。

matsuuNet::Twitter/Net::Twitter::Lite最新版のencode/decode周りがおかしい。utf8プラグマとLWPが絡むともうなんつーかバッドノウハウのオンパレードですよ。 ( 2009-08-27 00:14:01 )
miyagawa@matsuu 3.04005 でなおしたはずなんですがね。update() には decode したのを渡さないとだめです。 ( 2009-08-27 00:15:31 )
miyagawa@matsuu 動作がおかしいスクリプトをみせてもらえれば対応できます。ただし Net::Twitter 3.x で直したのは、2.xでたまたま動いていた(utf8 バイトを渡せばなんとなく動いていた)のを正しくしたのですけども ( 2009-08-27 00:20:03 )
matsuu@miyagawa む、utf8バイト列で送るのが流儀ですか?私はNet::Twitter::Liteを使ってutf8フラグ付きを渡してるんですが、encode('utf-8')してる部分がなければ正しく動作してます。 ( 2009-08-27 00:25:59 )
miyagawa@matsuu いえ、フラグつき(という表現はあまりただしくありませんが)で渡すのが正しいです。 ( 2009-08-27 00:28:46 )
matsuu@miyagawa http://gist.github.com/175600 これで、2と4が化けます。アカウント情報は変えてます。 ( 2009-08-27 00:56:56 )
matsuu@miyagawa encodeが必要なのはGETの前のquery_form時のみでしょうか? ( 2009-08-27 01:15:37 )
miyagawa@matsuu ひょっとして update => "テスト" を 'update', "テスト" にすると動いたりしません? utf8 プラグマで fat comma をつかうと左辺がdecodeされる罠なんですが。Net::Twitter側で対応するか微妙っすね。。 ( 2009-08-27 04:24:35 )
miyagawa@matsuu Net::Twitter で対応したのでつぎのリリースでいけますが、当面は 'status' => と quote すればうごくはず。 ( 2009-08-27 06:40:06 )
matsuuうげーーーーーーーー。知らなかった!utf8プラグマ SUCKS! ( 2009-08-27 08:09:34 )
matsuu@miyagawa ありがとうございます。確かに動作しました。まだまだ私は修行が足りないようです。 ( 2009-08-27 08:11:07 )
miyagawa@matsuu fixed in perl5 git :) http://perl5.git.perl.org/perl.git/commit/eaf7a4d2 ( 2009-08-27 09:02:17 )
私が的外れな返答をしてますが、まぁそれはおいといて。

詳しくは#68812を参照。とどのつまり、

use strict;
use utf8;

my %foo = (a => 'b', c => 'd');

と書くのではなく、

use strict;
use utf8;

my %foo = ('a' => 'b', 'c' => 'd');

とfat commaの左辺も文字列で書くのが無難です。

参考

use strict;
use warnings;
use utf8;
use Devel::Peek;

my (%w, %x, %y, %z);

%w = (a => 1);
%x = ('a' => 1);
$y{a} = 1;
$z{'a'} = 1;

Dump(%w);
Dump(%x);
Dump(%y);
Dump(%z);

これはこんな結果になる。

SV = PV(0x71b0f0) at 0x75cd80
  REFCNT = 1
  FLAGS = (TEMP,POK,pPOK,UTF8)
  PV = 0x739cf0 "a"\0 [UTF8 "a"]
  CUR = 1
  LEN = 8
SV = PVIV(0x71c0d0) at 0x75cd80
  REFCNT = 1
  FLAGS = (TEMP,POK,FAKE,READONLY,pPOK)
  IV = 3392050242
  PV = 0x7674a8 "a"
  CUR = 1
  LEN = 0
SV = PVIV(0x71c0d0) at 0x75cd80
  REFCNT = 1
  FLAGS = (TEMP,POK,FAKE,READONLY,pPOK)
  IV = 3392050242
  PV = 0x7674a8 "a"
  CUR = 1
  LEN = 0
SV = PVIV(0x71c0d0) at 0x75cd80
  REFCNT = 1
  FLAGS = (TEMP,POK,FAKE,READONLY,pPOK)
  IV = 3392050242
  PV = 0x7674a8 "a"
  CUR = 1
  LEN = 0

これは直感に反するよね。