Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP的array、traversable、foreach等的设计失误(一) #37

Open
hax opened this issue Sep 9, 2016 · 2 comments
Open

PHP的array、traversable、foreach等的设计失误(一) #37

hax opened this issue Sep 9, 2016 · 2 comments
Labels

Comments

@hax
Copy link
Owner

hax commented Sep 9, 2016

《PHP恨你》这个系列停笔好久了,主要是一直没空,然后光吐槽也不产生价值。不过这个我新发掘的case,勉强可算语言设计上学到的一课,所以就写一下吧。

第一件小事是,PHP的typehint不支持union type,如果一个参数可以是多个类型,就只好用注释了,或者更常见的情况——就不写了,读代码的人你自己猜吧。

Traversable这个接口表示的是可以用foreach遍历。而array当然也是可以用foreach的。所以一个函数接受Traversable,没有什么道理不接受array。但是因为上面说的限制,导致你无法标注typehint,如果你标注了Traversable,传一个array进去就报错。这真是个悲伤的故事。

实际上Traversable并不是一个可以直接实现的interface,而是一个“internal engine interface”,也就是说它的用途只有typehint和instanceof。而标typehint的用途因为上述原因变得很鸡肋,也就只剩下instanceof。而instanceof代码也基本上就是

if( !is_array( $items ) && !$items instanceof Traversable )
  //Throw exception here

这个罗嗦样子。

其实让这个接口同时覆盖array又有什么问题呢?

注意,有人可能会说普通object其实都能foreach(行为是遍历所有public属性和值),那么Traversable应该可以覆盖所有object,但那样这接口就没意义了。

确实,Traversable接口的真实含义更接近:如果实现了此接口,就代表有定制化的遍历行为。不过遍历一个普通对象是比较少见的(因为PHP中array已经同时具备了关联数组的用途),通常是reflection的用法,而不像Traversable/array是频繁的集合遍历操作。PHP不是一向崇尚“实用主义”嘛,为什么这里不按照实用出发呢?

如果说第一件小事只是稍微带来不便,第二件事就非常蛋疼,且贻害无穷了。

(待续)

@mingyun
Copy link

mingyun commented Nov 16, 2017

没后文了?

@zhujinxuan
Copy link

第二件事情是 hash 和 array 混用,以及默认 deep equal 的 holy shit 么?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants