[吐槽] PHP :哪天没有写 bug,算我输。数组哪里都是值拷贝;引用:蛋疼。明明是语言问题,硬说是我太菜
每隔几年都要来学一遍,每次都是入门到放弃。直接上代码,懒得解释。
//常规脑回路,写的代码,抱歉了,bug 成堆
$list=array();
for($i=0;$i<10;$i++){
$obj=array();
$list[]=$obj; //后面会有 break 、return 等复杂逻辑,因此此处进行赋值代码量最少
$obj["val"]=$i;
//...一大堆复杂逻辑
}
//list= [{},{},{},......,{}]
数组对象这么重要的东西,默认进行赋值操作竟然是值拷贝。每赋值一次,就整个数组复制一遍。不能说这种方式不妥吧,就是感觉不那么好,说不上来的那种不好!
数组对象赋值采用引用的方式赋值,场景绝对比值拷贝多的多。需要做为全新的一个数组对象来对待的场景,完全可以显式的进行新数组的创建操作。直接就省去了很多麻烦。( PHP 也是老人家了,发了这么多版,随便出个 Array2 搞点完全不同的特性来糊弄我一下也行啊)
//修改代码,显式的进行引用。依旧是常规脑回路,写的代码,抱歉了,bug 还是成堆
$list=array();
for($i=0;$i<10;$i++){
$obj=array();
$list[]=&$obj; //后面会有 break 、return 等复杂逻辑,因此此处进行赋值代码量最少
$obj["val"]=$i;
//...一大堆复杂逻辑
}
//list= [{val:9},{val:9},......,{val:9}]
然后就有了,看似很屌,其实并没有多大卵用的:引用。有意思的是,它是按名字来引用,这个很关键,也很鸡肋。(在函数参数里面似乎有点儿卵用,就算没有引用传递这种东西,引用参数完全可以用别的带有引用性质的东西来代替)
//好了,这回正常了。不过,我的脑回路已经不正常了,劝退中
$list=array();
for($i=0;$i<10;$i++){
unset($obj); //强加的负担,迟早要翻车,漏了就反复调试来定位吧,一次写出的代码能用就怪了
//这种形式的引用方式,不要也罢:赋值一次,所有变量乱窜
$obj=array(); //如果你不是值拷贝,用得着引用?
$list[]=&$obj; //后面会有 break 、return 等复杂逻辑,因此此处进行赋值代码量最少
$obj["val"]=$i;
//...一大堆复杂逻辑
}
//list= [{val:0},{val:1},......,{val:9}]
php 代码:满屏的毫无意义的 $,满屏的毫无意义的两个字宽度的 -> ,代码看起来很肥 很保暖。
狗屁不是。可以:解决掉有问题的人,就没有问题了。
每门语言的特性不一样,好好的 php 非得按 java 的思路写。
值传递很好,只有数组这一种数据结构很好。千万别按楼主的思路改。也不需要什么 Array2 。
php 没有在不同版本瞎改,向前兼容做的很好,为 php 开发组点个赞。
PHP 的 for 中使用引用一直是潜在 bug 的源头。
为啥要在 for 里面引用?
你这思路有点奇怪。
每种语言有存在的意义 ,有自己的风格,硬要都按照 java 的思路去写不是找麻烦么。
其实楼主用面向对象的方式写就没有问题了:
gist.github.com/zjsxwc/25e7388b777ba56b614fe7f3e9d2b126 显示 Gist 代码
#2 #4 不是 for 的问题,是 Array 的问题。自己定义的对象,默认赋值就是引用,不存在隐式的复制,自然就不需要自己显式的引用赋值。Array 这个玩意败笔就在默认赋值一下就拷贝一遍,这就注定了逃不过用到&,最终结果就是不常用的引用功能,&要被滥用。
所以我提出一个 Array2 ,理想状态下,默认赋值就是引用,我如果要复制,完全可以自己调用一个函数复制出一个新数组。对于解析器底层实现一个这玩意,我猜测应该也不复杂,比如给 Array 加一个标记,遇到这种特殊的 Array 类型的对象,解析器发现有标记,就跳过复制阶段,直接引用这个,就和对象一样对待应该就 OK 了。
#1 #4 针对类似这种说法,所以我结尾直接提前写上了解决办法。
很多相同逻辑,不管什么语言实现,写出的结构都会差不多,不会偏的离谱,我接触的比 php 更丑的还有 python 、vb ,不过他们没有这种不可思议的问题。
“为啥要在 for 里面引用?”,这种问题也会成为问题,程序员忍不住的话要把菜刀放桌上了😂 逻辑实现除了 if for 还有什么是重要的?
#3 上面标错楼层了
第二段起手 数组对象 是什么勾八玩意儿?
数组特么的就不是对象。张口闭口整篇文章就在谈一个不存在的东西我也是服了。
数组就是数组。对象才是对象。搞不清楚数组是什么东西可以学,不知道数组和对象是什么关系可以问(答案是没鸟关系)。你要想搞个 array2 对象欢迎自己写一个。在这里叫破喉咙都没人把你当回事。
还谈跨语言写结构。不同语言结构差远了。给你个 haskell 你不得喷这玩意怎么连循环都没有了。PHP 本来就是一个以值传递为主的语言,就算是对象变量也依然是传值的,只不过这个值是对象指针所以写起来会有传引用的效果。你要是起手就想把别的语言根基给整个掀了,我劝你还是回去写 Jaba 吧。
这段逻辑,放在 Python 里是会用 list comprehension 写,放在 Ruby 里会用 block chain 写,放在 Jaba 里可以用 stream lambda 写,放在 PHP 里也只需要把追加数组项那行放在最后就行了。
后面会有 break 、return 等复杂逻辑,因此此处进行赋值代码量最少
复杂逻辑不放进函数里?不封装进对象里? peer review 不会被同事骂死吗?
#9 同事已经拍桌子了,下一步应该要拿刀了😂
“PHP 中的 array 实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。此类型针对多种不同用途进行了优化; 它可以被视为数组、列表(向量)、哈希表(映射的实现)、字典、集合、堆栈、队列等等。 由于 array 的值可以是其它 array 所以树形结构和多维 array 也是允许的。” 至少在很多地方,它讲的这一套东西叫法,更偏向对象😂
新手:php 没有对象,只有数组(字典也叫数组)😂 ,等学到 class 了才有会发对象😂
楼主你使用冒号的方式好奇特……
哈哈哈 ,本来打了一大堆字,最后还是想了想,就说四个字,尊重祝福~
看了下楼主代码,一致同意、确定、一定是语言的问题
你竟敢说 PHP 语言不行?不想活了?
我是从 PHP4 开始写起来的,那时候 PHP 对对象和类的支持还非常简陋原始,PHP 基本是一个面向过程语言(可以看作和 C 非常类似但大幅简化的语言),对象是一个非常小众,很少有人用到的 feature 。大概一直到 2007 年前后我才看到越来越多的项目开始用类结构来构建项目。你想想,像是 Zend framework 这种项目都是 2005 年才开始搞的。但是那时候主流的开发依然是面向过程。2009 年我在一家公司做架构设计,老大还跟我说不要把面向对象结构设计得太复杂,否则老员工玩不明白,于是只好自己写个 MVC 框架,只用了一点点面向对象设计,controller 依然做成了面向过程结构,满足老员工的复古风需求。
PHP4 里的类结构连可见性控制都没有(即没有 private public 之分),没有接口 interface ,也没有引用传递。一直到后来 PHP5 里才加入这些新功能。只不过像是数组这种超大规模使用的特性,不可能说改就改的,这么多年下来的项目,兼容性不可能说砍就砍,毕竟有太多的地方依赖数组传值。
👍
后面‘$‘, ’->‘ 确实是个槽点,但也没办法,就跟语言定的关键字一样
至少在很多地方,它讲的这一套东西叫法,更偏向对象😂
更像数组和 hashmap 的结合体吧
你强行把数组当对象用,然后还怪别人不支持,哪个语言都不支持吧。。。
PHP 的数组就是一种数据结构,见过一些老代码把数组当对象用的,弄了一个超大的数组,然后直接 return 或者给函数传参,导致内存占用疯涨。。。。
另外学语言得搞清楚变量作用域,PHP 的变量只有全局作用域和函数作用域
感觉写$太难受了 所以直接 ahk 伺候了,三击 4 键输入$
$4::
if pressesCount > 0 ; > 0 说明 SetTimer 已经启动了,按键次数递增
{
pressesCount += 1
return
}
;否则,这是新一系列按键的首次按键。将计数设重置为 1 ,并启动定时器:
pressesCount = 1
SetTimer, WaitKey, 400 ;在 400 毫秒内等待更多的按键。
return
WaitKey:
SetTimer, WaitKey, off
if pressesCount = 1 ;该键已按过一次。
{
Gosub singleClick
}
else if pressesCount = 2 ;该键已按过两次。
{
Gosub doubleClick
}
else if pressesCount = 3
{
Gosub trebleClick
}
;不论上面哪个动作被触发,将计数复位以备下一系列的按键:
pressesCount = 0
return
singleClick:
send 4
return
doubleClick:
send 44
return
trebleClick:
send $
return
你不配用 PHP
你就狗屁不是~~
只看了标题,内容我都没看,我就已经得出结论了,
这世界上没有适合你的语言!!!
我从没碰到过类似的问题,我怎么感觉代码执行没有问题啊,是你自己的问题吧?
$list=array();
for($i=0;$i<10;$i++){
$obj=array();
$list[]=$obj
$obj["val"]=$i;
}
为什么要这么写,又不是对象,能这么写,我头一次看到这样的?
应该是
$obj=array();
$obj["val"]=$i;
$list[]=$obj;
这样的顺序吧
$list=array();
for($i=0;$i<10;$i++){
$obj=array(); // 这里已经重置了
$list[]=&$obj;
$obj["val"]=$i;
}
//list= [{val:9},{val:9},......,{val:9}]
这段代码结果也没错啊,
list[]=obj ,为什么要先赋值到 list 先呢?
obj 确定以后再赋值不就好了吗?也不用 unset ,引用啥的。
也可以 listi=1 来操作 obj 。
可能其他语言会有不同习惯,我一直写 php 都没留意。
php 这么亲民友好的语言,你都玩不明白,的确 狗屁不是
//后面会有 break 、return 等复杂逻辑,因此此处进行赋值代码量最少
因为这个吧,他无法做到在最后一行将 obj 塞入 list ,又不想在每个跳出的地方重复写$list[] = $obj ,更不想优化自己的代码,所以只能吐槽 PHP 了
不应该直接
$list[] = array('val' => $i);
一行就完事了。看了半天才缓过来
那个时候看的教程一般全都是 class component,状态管理必是 redux,后来重心还是切换到 Vue 去了。 现在想重学一遍,但对一些教程比较疑惑,写法可能已经过时…
昨晚本人的手机进水突然变砖头,首先想到的就是在备用机恢复微软验证器的二步验证云备份。 但是!因为当时已经有了一些 2FA,想要启用备份。 官网文档讲的的账户页面我根本找不到,无…
用 astro 做了一个静态网站,内容主要是文字为主。 当时用 tw 的时候是提高生产力为主,比如 light/dark 转换,prose 排版等等。 现在功能基本完成,想做一…