2012-05-31 29 views
9

如何规范化函数参数列表到一个字符串,以便两个参数列表转换为相同的字符串iff它们实际上是等效的?该算法应该如何正常化记忆的Perl函数参数?

  1. 比较嵌入散列和列表深,而不是通过引用
  2. 忽略散列键顺序
  3. 忽略3和“3”
  4. 产生相对可读的字符串之间差(不是必需的,但好到有调试)

这是必要的表现良好(XS优于的Perl),即基于其参数缓存函数的结果。

作为一个稻草人例如,Memoize使用此作为默认正规化,从而未能#1和#3:

$argstr = join chr(28),@_; 

有一段时间我去到正规化是

JSON::XS->new->utf8->canonical 

然而,根据最近使用的标量的方式来处理数字3和字符串“3”differently。这可以为基本上等价的参数列表生成不同的字符串,并降低记忆收益。 (绝大多数的功能将不知道或不关心,如果他们得到3或“3”)

为了好玩,我看着一堆串行的,看看哪些区别3,“3”:

Data::Dump : equal - [3] vs [3] 
Data::Dumper : not equal - [3] vs ['3'] 
FreezeThaw : equal - FrT;@1|@1|$1|3 vs FrT;@1|@1|$1|3 
JSON::PP  : not equal - [3] vs ["3"] 
JSON::XS  : not equal - [3] vs ["3"] 
Storable  : not equal - <unprintable> 
YAML   : equal - ---\n- 3\n vs ---\n- 3\n 
YAML::Syck : equal - --- \n- 3\n vs --- \n- 3\n 
YAML::XS  : not equal - ---\n- 3\n vs ---\n- '3'\n 

报告“相等”的人中,不知道如何让他们忽略散列键序。

我可以提前走参数列表和字符串化所有的数字,但这需要作出深拷贝和违反#5。

谢谢!

+0

还有[Test :: More](http://metacpan.org/module/Test::More)的is_deeply,和[Test :: Deep](http://metacpan.org/module/Test :: Deep)的eq_deeply。 – Ether

回答

2

几乎任何串行将把3和“3”不同,因为它不具备知识号和字符串化的数量同样为你和这个假设是一般的数据错误。您必须自己规范输入或输出。

对于输入,深度扫描与它的值+ 0将做更换任何字符串化数。如果您知道输入数字的确切位置,则可以大大缩短此扫描时间。

对于输出,一些简单的状态机,甚至正则表达式(是的,我知道,输出不正规)将最有可能足以仅数字符串值删除为数字。

+0

那么,不,我列出了上面的一些序列化程序(如Data :: Dump和FreezeThaw),但没有。 :)也许你的意思是“任何优秀的序列化程序*都应该*不同地对待3和”3“。我不太确定,因为Perl值在字符串和数字之间可能会变得轻松随意。 –

+0

重新扫描,我提到输入扫描对于性能而言是不理想的。如果必须完成,我希望它在XS中。但是,如果序列化器可以选择关闭这个区别,那么效率会更高。 –

+0

那么我提到的输出扫描呢?这应该足够快。比较依赖于未记录的怪癖的一个重要的优点是,您可以始终确保手动剥离值确实会被剥离。 –

2

YAML,默认情况下它的后代排序哈希键。设置$YAML::SortKeys = 2以获得对深度哈希进行排序。

设置$YAML::Stringify真实值和设定$YAML::XS::QuoteNumericStrings为假值将帮助您恢复正常数值。后者设置将“取消”一个看起来像数字的字符串值。


此外,您还可以使用$Data::Dumper::Sortkeys = 1Data::Dumper正常化的输出顺序。设置$Data::Dumper::Useqq = 1将取消看起来像数字的字符串。

+0

对不起,但不行,YAML :: XS的行为与任何串行器应该一样。试试'perl -MYAML :: XS -e'我的$ v =“0333”;打印YAML :: XS ::转储$ v; $ v + 0;打印YAML :: XS ::转储$ v;打印“$ v \ n”;'' –

+0

@Oleg V. Volkov - 感谢您的评论我了解了更多关于'$ YAML :: XS :: QuoteNumericStrings'是什么和编辑我的答案。但我会认为0333“和333”和0333(即219)应被视为OP的不同输入。 – mob

+0

只需“333”将完全相同。 –