<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Leakon &#187; Perl</title>
	<atom:link href="http://www.leakon.com/archives/category/perl/feed" rel="self" type="application/rss+xml" />
	<link>http://www.leakon.com</link>
	<description>勤奋 - 创新 - 矢志不渝 - 锲而不舍</description>
	<lastBuildDate>Mon, 06 Feb 2012 02:43:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>pure function</title>
		<link>http://www.leakon.com/archives/72?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pure-function</link>
		<comments>http://www.leakon.com/archives/72#comments</comments>
		<pubDate>Thu, 18 Oct 2007 15:56:06 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[转载]]></category>

		<guid isPermaLink="false">http://www.leakon.com/archives/72</guid>
		<description><![CDATA[A pure function:
Has no side effects
Return value depends only on arguments
Example:
sub factorial {
my $n = shift;
$n == 0 ? 1 : $n * factorial($n-1);
}
cache 只对 pure function 有意义。
这可以思考，查询一个档案的修改时间的这种 function，他并非一个 pure function，所以，对非 pure function 做 cache 是没有意义的，这里有一个例子：
 Highly Recursive  [...]]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal"><span lang="EN-US">A pure function:</p>
<p>Has no side effects</p>
<p>Return value depends only on arguments</p>
<p>Example:</p>
<p>sub factorial {<br />
my $n = shift;<br />
$n == 0 ? 1 : $n * factorial($n-1);<br />
}</p>
<p>cache </span><span style="font-family: 宋体">只对 </span><span lang="EN-US">pure function </span><span style="font-family: 宋体">有意义</span><span lang="EN-US">。</span></p>
<p class="MsoNormal"><span lang="EN-US"></span><span style="font-family: 宋体">这可以思考</span><span lang="EN-US">，</span><span style="font-family: 宋体">查询一个档案的修改时间的这种</span><span lang="EN-US"> function，</span><span style="font-family: 宋体">他并非一个</span><span lang="EN-US"> pure function，</span><span style="font-family: 宋体">所以</span><span lang="EN-US">，</span><span style="font-family: 宋体">对非</span><span lang="EN-US"> pure function </span><span style="font-family: 宋体">做</span><span lang="EN-US"> cache </span><span style="font-family: 宋体">是没有意义的</span><span lang="EN-US">，</span><span style="font-family: 宋体">这里有一个例子</span><span lang="EN-US">：</span></p>
<p class="MsoNormal"><span lang="EN-US"> Highly Recursive Functions<br />
sub fib {<br />
my ($n) = @_;<br />
return $n if $n ==0 || $n == 1;<br />
return fib($n-2) + fib($n-1);<br />
}</p>
<p>This function is very very slow!</p>
<p>Caching Fixes Recursion<br />
Solution: Caching</p>
<p>@fib = (0, 1);<br />
sub fib {<br />
my ($n) = @_;<br />
return $fib[$n] if defined $fib[$n];<br />
return $fib[$n] = fib($n-1) + fib($n-2);<br />
}</p>
<p>fib(20) computes fib(18) and fib(19)</p>
<p>fib(19) goes to compute fib(18)</p>
<p>But it is already in $fib[18]</p>
<p>Function is now very fast,Almost as fast as a pure iterative version,<br />
Unlike the iterative version, this version required no ingenuity</p>
<p></span><span style="font-family: 宋体">以上文章节录自</span><span lang="EN-US"> <a href="http://perl.plover.com/yak/hw-dcpm/" target="_blank">http://perl.plover.com/yak/hw-dcpm/</a></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/72/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Perl 变量魔法</title>
		<link>http://www.leakon.com/archives/52?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=perl-%25e5%258f%2598%25e9%2587%258f%25e9%25ad%2594%25e6%25b3%2595</link>
		<comments>http://www.leakon.com/archives/52#comments</comments>
		<pubDate>Tue, 25 Sep 2007 13:01:25 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Perl]]></category>
		<category><![CDATA[原创]]></category>

		<guid isPermaLink="false">http://www.leakon.com/archives/52</guid>
		<description><![CDATA[先来看一段 Perl 脚本：
sub showVars {
	my $name = &#8220;first&#8221;;
	print	$name .  &#8220;\t at &#8221; . \$name . &#8220;\n&#8221;;
	for(my $i = 0; $i  2; $i++) {
		my $name = "loop_" . $i;
		if (1  3) {
			print	$name .  "\t at " . \$name . "\n";
			my $name = "if_A";
			print	$name .  "\t at " . \$name . "\n";
			{
				my $name =  [...]]]></description>
			<content:encoded><![CDATA[<p>先来看一段 Perl 脚本：</p>
<p><coolcode lang="perl" linenum="off">sub showVars {</p>
<p>	my $name = &#8220;first&#8221;;<br />
	print	$name .  &#8220;\t at &#8221; . \$name . &#8220;\n&#8221;;<br />
	for(my $i = 0; $i < 2; $i++) {<br />
		my $name = "loop_" . $i;<br />
		if (1 < 3) {<br />
			print	$name .  "\t at " . \$name . "\n";<br />
			my $name = "if_A";<br />
			print	$name .  "\t at " . \$name . "\n";<br />
			{<br />
				my $name = "blank";<br />
				print	$name .  "\t at " . \$name . "\n";<br />
			}<br />
			print	$name .  "\t at " . \$name . "\n";<br />
		}<br />
		if (1 < 4) {<br />
			print	$name .  "\t at " . \$name . "\n";<br />
			my $name = "if_B";<br />
			print	$name .  "\t at " . \$name . "\n";<br />
		}<br />
		print	$name .  "\t at " . \$name . "\n";<br />
	}<br />
	print	$name .  "\t at " . \$name . "\n";<br />
}</p>
<p>sub showVars_2 {</p>
<p>	my $name = "first";<br />
	print	$name .  "\t at " . \$name . "\n";<br />
	for(my $i = 0; $i < 2; $i++) {<br />
		$name = "loop_" . $i;<br />
		if (1 < 3) {<br />
			print	$name .  "\t at " . \$name . "\n";<br />
			$name = "if_A";<br />
			print	$name .  "\t at " . \$name . "\n";<br />
			{<br />
				$name = "blank";<br />
				print	$name .  "\t at " . \$name . "\n";<br />
			}<br />
			print	$name .  "\t at " . \$name . "\n";<br />
		}<br />
		if (1 < 4) {<br />
			print	$name .  "\t at " . \$name . "\n";<br />
			$name = "if_B";<br />
			print	$name .  "\t at " . \$name . "\n";<br />
		}<br />
		print	$name .  "\t at " . \$name . "\n";<br />
	}<br />
	print	$name .  "\t at " . \$name . "\n";<br />
}</p>
<p>showVars();<br />
print	"--------------\n";<br />
showVars_2();<br />
</coolcode></p>
<p>这里面有 2 个函数，两者之间的区别，就是变量的定义方式不同。</p>
<p>第一个函数，多次使用 my 声明变量。Perl 会在每一个局部区域内，比如说大括号 {} 内，实现一个命名空间。<br />
也就是说，在不同的代码段，相同的变量名，实际上指向了不同的内存地址。<br />
第一个函数体内，首先声明了一个变量 $name，他的作用域是整个函数，但在 for 循环体内，又用 my 声明了 $name 变量，因为 for 是一个封闭的结构，在 {} 里面就可以产生一个新的命名空间，此时 $name 指向了一个新的内存地址。这一点可以在后面的输出结果中看到。</p>
<p>由此，引发一个值得思考的问题：<br />
如果在循环体内部用 my 去声明变量，那么循环执行多少次，就会有多少个变量的副本，这会浪费很多内存空间。<br />
这一点是跟其他类 C 语言是有很大区别的。<br />
所以，如果你要想利用 Perl 的命名空间，那么只要多注意代码段的作用范围，编程的时候能感受到 Perl 十分强大的便利性。<br />
需要注意的，就是避免在循环体中使用 my 声明，浪费内存空间不说，还会影响程序的性能。</p>
<p>说了半天，还是看一看实际的结果吧：</p>
<p><coolcode lang="html" linenum="off">$ perl show_vars.pl<br />
first    at SCALAR(0x182fb10)<br />
loop_0   at SCALAR(0x182fbb8)<br />
if_A     at SCALAR(0x182fc24)<br />
blank    at SCALAR(0x182fc84)<br />
if_A     at SCALAR(0x182fc24)<br />
loop_0   at SCALAR(0x182fbb8)<br />
if_B     at SCALAR(0x182fd5c)<br />
loop_0   at SCALAR(0x182fbb8)<br />
loop_1   at SCALAR(0x182fd5c)<br />
if_A     at SCALAR(0x182fc84)<br />
blank    at SCALAR(0&#215;276164)<br />
if_A     at SCALAR(0x182fc84)<br />
loop_1   at SCALAR(0x182fd5c)<br />
if_B     at SCALAR(0x182fc24)<br />
loop_1   at SCALAR(0x182fd5c)<br />
first    at SCALAR(0x182fb10)<br />
&#8212;&#8212;&#8212;&#8212;&#8211;<br />
first    at SCALAR(0x182fe88)<br />
loop_0   at SCALAR(0x182fe88)<br />
if_A     at SCALAR(0x182fe88)<br />
blank    at SCALAR(0x182fe88)<br />
blank    at SCALAR(0x182fe88)<br />
blank    at SCALAR(0x182fe88)<br />
if_B     at SCALAR(0x182fe88)<br />
if_B     at SCALAR(0x182fe88)<br />
loop_1   at SCALAR(0x182fe88)<br />
if_A     at SCALAR(0x182fe88)<br />
blank    at SCALAR(0x182fe88)<br />
blank    at SCALAR(0x182fe88)<br />
blank    at SCALAR(0x182fe88)<br />
if_B     at SCALAR(0x182fe88)<br />
if_B     at SCALAR(0x182fe88)<br />
if_B     at SCALAR(0x182fe88)</coolcode></p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/52/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Perl 关联数组 哈希表 Hash Table</title>
		<link>http://www.leakon.com/archives/49?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=php-perl-%25e5%2585%25b3%25e8%2581%2594%25e6%2595%25b0%25e7%25bb%2584-%25e5%2593%2588%25e5%25b8%258c%25e8%25a1%25a8-hash-table</link>
		<comments>http://www.leakon.com/archives/49#comments</comments>
		<pubDate>Tue, 18 Sep 2007 13:32:02 +0000</pubDate>
		<dc:creator>leakon</dc:creator>
				<category><![CDATA[Perl]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[原创]]></category>

		<guid isPermaLink="false">http://www.leakon.com/archives/49</guid>
		<description><![CDATA[关联数组，又称为哈希表（hash table），是一种非常好用的数据结构。
在程序中，我们可能会遇到需要消重的问题，举一个最简单的模型：
有一份用户名列表，存储了 10000 个用户名，没有重复项；
还有一份黑名单列表，存储了 2000 个用户名，格式与用户名列表相同；
现在需要从用户名列表中删除处在黑名单里的用户名，要求用尽量快的时间处理。
这个问题是一个小规模的处理量，如果实际一点，2 个表都可能很大，比如有 2 亿条记录。
我最开始想到的方法，就是做一个嵌套的循环，设用户名表有 M 条记录，黑名单列表有 N 条记录，那么，循环的次数是 M * N 次！
PHP  [...]]]></description>
			<content:encoded><![CDATA[<p>关联数组，又称为哈希表（hash table），是一种非常好用的数据结构。</p>
<p>在程序中，我们可能会遇到需要消重的问题，举一个最简单的模型：</p>
<p>有一份用户名列表，存储了 10000 个用户名，没有重复项；<br />
还有一份黑名单列表，存储了 2000 个用户名，格式与用户名列表相同；<br />
现在需要从用户名列表中删除处在黑名单里的用户名，要求用尽量快的时间处理。</p>
<p>这个问题是一个小规模的处理量，如果实际一点，2 个表都可能很大，比如有 2 亿条记录。</p>
<p>我最开始想到的方法，就是做一个嵌套的循环，设用户名表有 M 条记录，黑名单列表有 N 条记录，那么，循环的次数是 M * N 次！<br />
PHP 版代码：</p>
<p><coolcode lang="php" linenum="off"><?php<br />
foreach($arrayM as $keyM => $nameM) {<br />
	foreach($arrayN as $nameN) {<br />
		if ($nameM == $nameN) {<br />
			// 本行执行了 M * N 次！<br />
			unset($arrayM[$keyM]);<br />
		}<br />
	}<br />
}<br />
return $arrayM;<br />
?></coolcode></p>
<p>另一种方式，利用数组索引。</p>
<p>PHP 是一种弱类型的语言，不像 C 语言那样有严格的变量类型限制。C 语言的数组，每一个元素的类型必须一致，而且索引都是从 0 开始。<br />
PHP 的数组，可以用字符串作为索引，也称为关联数组。<br />
数组索引，有一个天然的限制就是不会重复，而且访问的时候不需要查找，可以直接定位。</p>
<p>还是刚才的那个问题，我们采用另一种办法。</p>
<p>把黑名单列表的用户名组织到一个数组里，数组的索引就是用户名。</p>
<p>然后，遍历用户列表的时候，只需直接用 isset 查询那个用户名是否存在即可。</p>
<p>PHP 版代码：</p>
<p><coolcode lang="php" linenum="off"><?php<br />
$arrayHash = array();<br />
foreach($arrayN as $nameN) {<br />
	// 本行执行了 N 次。<br />
	$arrayHash[$nameN] = 1;<br />
}</p>
<p>foreach($arrayM as $keyM => $nameM) {<br />
	if (isset($arrayHash[$nameM])) {<br />
		// 本行执行了 M 次！<br />
		unset($arrayM[$keyM]);<br />
	}<br />
}<br />
return $arrayM;<br />
?></coolcode></p>
<p>可以看到，优化过的代码，循环次数是 M + N 次。</p>
<p>假如 M 和 N 都是 10000，优化前，循环了 1 亿次；优化后，只循环了 20000 次，差了 5000 倍！<br />
如果第二个程序耗时 1 秒，则第一个程序需要将近一个半小时！</p>
<p>最近在做 Perl 的开发，Perl 在处理文本的时候有很高的效率，同样，它也支持关联数组！</p>
<p>只是语法和 PHP 的那种类 C 的方式有很大不同，以第二段代码为例，Perl 版的实现：</p>
<p><coolcode lang="perl" linenum="off"><br />
#!/usr/bin/perl<br />
my %arrayHash;<br />
for(my $i = 0; $i < @arrayN; ++$i) {<br />
	$arrayHash{$arrayN[$i]} = 1;<br />
}</p>
<p>for(my $i = 0; $i < @arrayM; ++$i) {<br />
	if ($arrayHash{$arrayM[$i]}) {<br />
		$arrayM[$i] = undef;<br />
	}<br />
}<br />
</coolcode></p>
<p>Perl 的数组是 @ 开头，哈希是以 % 开头，unset 实际上就是 undef。<br />
Perl 的哈希和数组都是有具体类型的，而且向函数传递变量的时候要传引用，我刚学时间不长，快被搞晕了。</p>
<p>不过，现在刚刚实现了一个以 hash 方式进行 IP 位置查找的算法，平均比较次数大概在 3 次左右，比传统的折半查找方式少了很多次，它大概需要 8 次以上的比较。</p>
<p>刚刚做了一个小的性能测试，对 10 万个 IP 进行查找，在我的台式机上，耗时 15 秒，平均每秒 7500 次，感觉还不错，呵呵。</p>
<p>不过，还是喜欢 PHP 的数组，真的很强大！</p>
<p>God Bless PHP!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.leakon.com/archives/49/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

