Hatena::Groupsubtech

冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

 | 

Jan 08, 2008 (Tue)

PerlYAMLRubyYAML の相互運用 23:02 はてなブックマーク - Perl の YAML と Ruby の YAML の相互運用 - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

Ruby は標準添付の yaml で、PerlYAML::Syck にします。でもって、Syck のオプションを

$YAML::Syck::ImplicitTyping = 1;
$YAML::Syck::SingleQuote    = 1;

にするとたぶん互換になるみたいです。ImplicitTyping は POD にも「こうすると互換になるよ」って書いてあるやつです。SingleQuote は 8 進数みたいな文字列 (/0[0-7]+/) をよみかきするときに必要になります。

use strict;
use warnings;
use Data::Dumper;
sub p { print Dumper shift }

use YAML::Syck;
p YAML::Syck::Load(YAML::Syck::Dump({foo=>"0100"}));
p YAML::Syck::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '--- 
foo: 0100
';

$YAML::Syck::ImplicitTyping = 1;
$YAML::Syck::SingleQuote = 1;
p YAML::Syck::Load(YAML::Syck::Dump({foo=>"0100"}));
p YAML::Syck::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '--- 
"foo": \'0100\'
';

$YAML::Syck::ImplicitTyping = 1;
$YAML::Syck::SingleQuote = 0;
p YAML::Syck::Load(YAML::Syck::Dump({foo=>"0100"}));
p YAML::Syck::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => 64
        };
$VAR1 = '--- 
foo: 0100
';

use YAML;

p YAML::Load(YAML::Dump({foo=>"0100"}));
p YAML::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '---
foo: 0100
';

use YAML::XS;

p YAML::XS::Load(YAML::XS::Dump({foo=>"0100"}));
p YAML::XS::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '---
foo: 0100
';

RubyYAML.load の挙動は YAML::Syck の $YAML::Syck::ImplicitTyping = 1; のときの挙動と一緒です。すなわちクオートしない /0[0-7]+/ は8進数の数値になります。YAML.dump は数値っぽい文字列を自動でクオートします。

require "yaml"

p YAML.load(<<EOS) #=> {"foo"=>64}
---
foo: 0100
EOS

p YAML.load(<<EOS) #=> {"foo"=>"0100"}
---
foo: "0100"
EOS

puts YAML.dump({"foo" => "0100"})
# --- 
# foo: "0100"
#
puts YAML.dump({"foo" => "aaa"})
# --- 
# foo: aaaa

ポイントは結局のところ

  • Dump 時に8進数っぽい文字列がクオートされるか
  • Rubyyaml は特にオプションとかがない (なので、クオートされないものはつかえない)

みたいですね。あと、Perl しか使わない場合でも、$YAML::Syck::ImplicitTyping = 1 で使うときは必ず $YAML::Syck::SingleQuote = 1; も指定しないとデータがこわれてしまうみたいです。

Perl については調べきれてないかもしれないです (Syck 以外でもクオートできるのかな……)。もしかするともっといい方法があったりするのかもしれない……


文字列の繰り返し 07:55 はてなブックマーク - 文字列の繰り返し - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

ref. 文字列繰り返し - Higé au lait

String.prototype.repeat = function (n, sep) {
	if (n < 1) return "";
	return Array(n).join(this + (sep || "")) + this;
};

print("hoge".repeat(-1, '+')); //=> ""
print("hoge".repeat(0, '+'));  //=> ""
print("hoge".repeat(1, '+'));  //=> "hoge"
print("hoge".repeat(3, '+'));  //=> "hoge+hoge+hoge"
print("fuga".repeat(4, '-'));  //=> "fuga-fuga-fuga-fuga"
print("foo".repeat(4));        //=> "foofoofoofoo"

Rake タスクの引数のほげほげ 01:28 はてなブックマーク - Rake タスクの引数のほげほげ - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。

Rakeのタスクに引数が取れるようになったけど…ひどい - (rubikitch loves (Emacs Ruby CUI Books)) をみてて、使えるようになったノカーとか思いつつ、このままだとちょっと使えないなぁと思ったので、Rakefile で対応できる範囲でつかいやすくしてみた

def args(hash)
	name = hash.keys.first
	args = hash[name]
	task name, *args
end

desc "foo task"
args :foo => [:bar, :baz]
task :foo do |t,a|
	p t.arg_names
	p a.bar
	p a.baz
end

desc "bar task"
task :bar do |t|
	puts "this is bar."
end

# ARGV は Rakefile が実行される時には既に rake 自体への引数は全てとりのぞかれている
Rake.application.top_level_tasks.replace(ARGV.map {|a|
	name, vals = *a.split(/@/, 2)
	vals ? "#{name}[#{vals}]" : a
})

これで

$ rake 'foo[aaa,bbb]'
(in /Users/cho45/tmp)
[:bar, :baz]
"aaa"
"bbb"

$ rake foo@aaa,bbb
(in /Users/cho45/tmp)
[:bar, :baz]
"aaa"
"bbb"

になって、どっちでもいけるようになる。


あと引数の宣言の DSL がめちゃくちゃわかりにくいと思うのでオレオレメソッドを定義してみた (あの DSL で、後ろに書いてあるのが引数だと想像できる人はどれほどいるんだろう……)。先に args の宣言がくるのはちょっとキモいけど、task メソッドうわがきせずやるとこんなもんなのかなぁ。


でもそんなに引数めちゃくちゃとりたいケースってないのかもしれない……

いまさらだけど別に ARGV みなくても top_level_tasks.map! でいいのだった。(最初は ARGV をもっといじくるコードを書いてたなごり)

 | 

スポンサード リンク

書いてる人

cho45 (佐藤広央) (www.lowreal.net)

Perl, JavaScript, Ruby, HTML, CSS, Web etc


スポンサード リンク