2007-03-26
2007-01-30
2006-10-04
PHP怪现象[5]
这次要说的是PHP5中的一种叫做type hinting(类型暗示)的东西,从使用上来说,接近于Java这类静态类型的类型检查,比如:
<?
interface A{
function a();
}
class AA implements A{
public function a(){
print "A";
}
}
function b(A $a){
$a->a();
}
?>
如果现在运行b(new AA());则会顺利通过,输出一个A,而使用任何其他类型的,比如b(new stdClass());b(1);b("a");之类的,都会出现这种错误:Fatal error: Argument 1 passed to b() must implement interface A, called in ....
应该说,这东西确实给OOP中的类型检测带来了福音,我们无须写if(xx instanceof xxx)这类繁琐的判断语句了。不过,这功能也有点鸡肋的嫌疑。原因有三:
- PHP是动态类型的,又是弱类型的,这种type hinting只是虚拟机层次上的动态类型判断,即不能做到编译时提前检查出一些类型错误,也不能给予性能上的极大的提升,
- 无法处理基本类型,如string, int——如果将这些东西应用在这个位置上(不过PHP5.1开始array也可以,真是很奇怪),PHP会检查有没有叫做string、int的类或接口;而同样具有type hinting的perl 6,则作的相对更好,比如Perl 6中至少可以将type hinting应用于基本类型上
- 不能进行函数重载,如果实现了的话,PHP可能就变成Generic Programming了,但对于PHP这种动态语言来说,这并不是必要的,但现在又具备了type hinting,为何却不能根据类型来进行一些推断(type inference)呢?
查看Nirvana Studio Groups上的PHP怪现象[5]
标签: 类型, interface, OOP, PHP, type hinting
2006-09-19
Perl复习
我在高中的时候曾经学习过一段时间的Perl,是为了给“宇宙工作室” 制作一个下载站点,为了找一个动态的免费空间可不容易啊,当时是51.net提供了免费的cgi空间,支持Perl,于是乎,特地学习了Perl,并在网上寻找了一个免费的代码改了一遍,
时过6年,又想重新学习Perl——毕竟是一个风靡一时的语言,而且其CPAN中丰富的包,也是相当实用的。
话又说回来,时过六年,Perl6也没有推出,实在是一个遗憾。
从大学开始学习了PHP,PHP从Perl中借鉴了很多东西,比如$式的变量,但实际上和Perl还是有很大区别的,之前我曾经翻译过一篇PHP 对比 PERL,从中可以看出很多不同的地方。
比如,其实Perl是一个函数式编程语言,有词法范围。
关于具体的细节,我会整理一个表格列出来,希望对其他学习两者的朋友有所帮助。
2006-09-18
2006-09-16
PHP之怪现象[3]
这次要说的怪现象在于PHP的性能问题,且不说PHP的性能有多差,因为毕竟是一个脚本语言,不能奢望其速度多快,但PHP的性能的奇怪问题确实很特别:
- 版本的提升并未带来性能的提升——PHP5比PHP4慢
- 通过一些字节码优化器来大幅度提高性能
PHP: version 4.3.10 vs PHP: version 5.0.5 PC: Celeron 2.0Mhz / 512Mb | ||
PHP 4 | PHP 5 | |
Creating int array[100 000] | ||
for vs while | ||
code | [ms] | |
for($i=0;$i<10000;$i++) | 0.063 | 0.087 |
while($i<10000)> | 0.057 | 0.086 |
Reading int array[100 000] | ||
while vs foreach vs or | ||
foreach($arr1 as $vl) {..} | 0.085 | 0.171 |
while(list(,$vl) = each($arr2)) {..} | 0.261 | 0.335 |
for($i=0;$i<10000;$i++) | 0.123 | 0.163 |
Reading apache log (16Mb) | ||
file vs file_get_content vs fread | ||
$a = file("t1.log"); | 0.270 | 0.274 |
$b = file_get_contents("t1.log"); | 0.120 | 0.121 |
.. $c = fread($hdl, $size); .. | 0.133 | 0.141 |
Parse vars names [100 000] | ||
"test$i" vs "test".$i vs ‘test’.$i | ||
for(…) {$c = "test$i";} | 0.316 | 0.354 |
for(…) {$c = "test".$i;} | 0.205 | 0.236 |
for(…) {$c = ‘test’.$i;} | 0.205 | 0.236 |
Parse and find text from apache log (32Mb) | ||
ereg vs preg_match | ||
eregi("2005:03:04",$txt); | 3.504 | 3.521 |
preg_match("/2005:03:04/im",$txt); | 0.108 | 0.735 |
Split text apache log 200Kb (contain 2000 "-") | ||
split vs explode | ||
split("-",$txt); | 1.561 | 1.573 |
explode("-",$txt); | 0.193 | 0.197 |
Count array size. $arr = int[100 000] | ||
count vs sizeof | ||
for($i=0;$i<count($arr);$i++) | 0.198 | 0.276 |
for($i=0;$i<sizeof($arr);$i++) | 0.198 | 0.268 |
Create object by Ref (loop 100 000) | ||
with ref vs without ref | ||
(…) {$j = & new TestClass();} | 0.460 | 1.180 |
(…) {$j = new TestClass(); } | 0.470 | 1.291 |
Random number generator (loop 100 000) | ||
srand vs mt_srand | ||
(…) { srand(); } | 0.185 | 0.193 |
(…) { mt_srand(); } | 0.929 | 0.989 |
Calculate hash (loop 100 000) | ||
srand vs mt_srand | ||
(…) { md5($i."byster.net".$i); } | 1.306 | 1.365 |
(…) { sha1($i."byster.net".$i);} | 1.492 | 1.662 |
2006-09-15
PHP之怪现象(2)
在前面一篇文章PHP之怪现象 中,说到了array()是值复制而非引用的,那么要使用引用的数组,要怎么办呢,PHP5引入的奇特的Standard PHP Library
其中有一个ArrayObject,可以实现引用的数组:
$a = array(1,2,3);
$arrobj = new ArrayObject($a);
这样就可以得到一个行为基本和原始array()一样的一个ArrayObject实例,你也可对其进行foreach操作,不过和基本的array()有一些区别:
- 大多数array相关的函数不能使用,如count(),必须使用ArrayObject的count()方法,象array_push() array_pop()等则无法使用
- 对ArrayObject使用[]取出某个值的时候,如$arrobj['a'],如果要对这个值进行处理如--、++、[]=等操作,不能使用链式表达式,必须先将这个值取到某个变量中才能使用,如下是错误的:
$arrobj[1]++; $arrobj[0]--; $arrobj[2][0] = 1; - ArrayObject的性能比array()的性能差很多,慢一倍多点
说完了ArrayObject,还要说一下和ArrayObject密切相关的另一个东西ArrayIterator,一个数组的迭代器。很难说明SPL的目的到底是什么。下面先看看SPL的一张类图
如此复杂的类图,第一眼看,觉得很象Java,但PHP没有OOP中万物之本的Object类(其实如果用类型转换的object转换,是可以得到一个奇怪的stdClass的实例,但没人知道这是干什么用的),如果说是像C++,又少了GP的支持,而PHP低下的运行效率――不要说和Java比,就是和Lua比,也差太多了,谁敢使用这么庞大复杂的类库呢?
2006-09-14
PHP之怪现象
下面总结一些我发现的PHP的奇怪事情:
1.array()并非引用类型array()并非一个对象的构造函数,它是一个语言结构,它返回的虽然是一个结合数组,但并非一个对象,即时在所谓OO的PHP5中,也是有问题的:
$a = array(...);这时候,确实输出为1,表示两者一致,PHP的手册上是这么说的:
$b = $a;
print $b === $a;
$a == $b | 相等 | 如果 $a 和 $b 具有相同的键/值对则为 TRUE。 |
$a === $b | 全等 | 如果 $a 和 $b 具有相同的键/值对并且顺序和类型都相同则为 TRUE。 |
如果这时修改$b的某个值,那么$b就和$a不等了
$b[0] = 5;这时什么也不输出,表示为false
print $b === $a;
如果要获取$a的引用,必须强制性地使用&操作符
$b =& $a;由此引出了2
2. foreach和each()等数组操作
foreach($arr as $k => $v)表示遍历$arr中的每个元素$e,同样的,这个$v是=出来的,相当于$arr[$k] = $v,而非$arr[$k] =& $v,并非$arr中的实际元素,那就有两种情况:- $arr[$k]这个元素正好是一个对象,这时其中存储的其实是一个引用,那么$v可以正确指向最终的对象
- 之外所有的类型,都是一个副本,如果是一个数组,那么是数组的副本
这种问题同样可出现在其他数组操作,each(),current()等。
2. include和eval
include和eval哪个快?
答案是eval快,这个确实比较奇怪,即使算上文件操作,纯粹执行代码,eval(file_get_contents($file))要比include快那么一点。
问题可能在于include要处理<?php ?>这些东西,而eval仅处理php代码。