PHP中的模拟Ruby符号

  • 本文关键字:Ruby 符号 模拟 PHP php
  • 更新时间 :
  • 英文 :


Ruby和其他一些语言有一个非常方便的特性:符号。它们看起来像就地常量。现在,我想知道以下在PHP中模拟符号的方法是否有效,该方法在未引用的字符串之前使用at符号。

$array = [@key => "value"];
echo sprintf("%s PHP symbols with a %sn", @testing, $array[@key]);

我知道形式常量等有一些缺点,这与Ruby的符号相同:考虑键入错误。使用这种方法还有其他考虑因素吗?

如果"valid"的意思是"可以运行",那么是的,这是一种有效的方法(但根据该标准,将所有字符串放入HEREDOC也是有效的)。但仅仅因为PHP会接受语法,并不意味着语法没有问题。

我首先想到的是

  1. 您正在主动抑制一个会耗费处理时间的错误
  2. 你的同事需要对正在发生的事情做出解释,这会耗费开发人员的时间
  3. 您正在反对该语言的自然定义(PHP根本不是Ruby)
  4. 由于无论如何都必须为变量使用sigil,因此实际上并没有清理代码

您正在抑制一个错误(确切地说是一个通知)。正如cwallenpoole的回答中所提到的,这不仅会花费处理时间,而且错误也是有原因的。原因是:

Notice: Use of undefined constant hello - assumed 'hello' in ...

您依赖于某个未定义的常量-这正是通知试图告诉您的。如果定义了该名称的常量,您将获取其值。

在Ruby中,:__LINE____LINE__有很大不同。前者是一个符号,无论你在哪里使用它,它都是平等的。后者是一个数字,是一个神奇的变量,每一行都会改变它的值。在PHP中,@__LINE____LINE__相同,因为没有可抑制的错误。哦,还有一个特殊的"符号",调试起来特别有趣:@exit,也就是@die

在Ruby中,您可以使用各种符号,包括运算符和关键字。这些(以及更多)都是有效的::+ :* :< :<< :[] :[]= :while :case :x=。使用一对括号,您甚至可以使用:case=:while=之类的符号在PHP中,这些都不起作用。您最终会出现一个解析错误。它甚至不会被压制。唯一的例外是PHP 5.4中的@[],它生成一个空数组。另一方面,许多PHP表达式都不是有效的Ruby符号:@(1+1) === @2@1 == @'1'

Ruby的符号不等于其他任何符号。这就是他们存在的目的。当然,它们有一些不错的特性,比如to_sto_proc,但它们最初的目的是充当与任何可能的用户输入分离的标识符。例如,如果您使用符号来表示lexer流中的令牌,例如[:lparen, 1, :plus, "rparen", :rparen],那么这在某种程度上是很好的在PHP中,未定义的常量是字符串。在Ruby中,?test != "test"。在PHP @test === "test"中(假设您没有定义一个名为"test"的常量来等于其他值)。

你甚至不能假设非魔术常数不会改变。你甚至不能将糟糕的编码解释为恶意。在Ruby中没有什么值得担心的:

//in library code:
$this->status = @done; // bad
//outside library code:
define('done', "no"); // very bad
define(@done, "yes"); // even worse
echo @no; // prints "yes"
//in library code:
if($this->status == @done){
  //won't execute
}
echo @die;
echo "this won't get printed!";

您不应该依赖于未定义的常量,也不应该使用错误抑制来隐藏告诉您这一点的错误消息。当两样东西相等时,你不应该用特殊的符号来假装它们不相等。此外,您是否可以信任库的用户不会在运行时重新定义常量?

警告:
下面的答案包含了一些类比,纯粹是为了说明一点。在没有的情况下,我是否打算建议你考虑有人(你或其他人)真的坐下来做我提到的事情的可能性。就是这样疯狂


尽管其他答案已经解释了使用@<str>的主要问题,它支持一个通知,但更重要的是要强调这一点
当使用抑制@(死亡)时,通知不会神奇地消失,它仍在发布中。一段时间后,日志将被通知堵塞,从而更难找到可能存在的致命错误。即使没有致命错误,它仍然会减慢代码的速度。

为什么要鼓励人们编写能够发出通知的代码?仅仅因为你喜欢ruby语法?拜托,如果你不喜欢一种语言,就不要使用它。我知道:遗留代码,你必须……那么,就去做吧,不要试图让它看起来像Ruby。它们不是同一种语言。所有提醒你使用不同语言的事情都应该被视为一种工具。不同的语言需要不同的心态和思考问题的不同方式。

想象一下,编写Lisp,但将语法更改为SQL查询。这将生成多少坏代码。语法迫使你进入SQL思维,而你应该在函数中思考
但看在上帝的份上,不要那样疯狂!!这是一件愚蠢的事,甚至比用正则表达式解析HTML还要糟糕。这会让Cthulhu哭得像个小女孩

哦,@在常用时不是用来抑制错误的吗?你真的相信吗?所以,你预计很多人会写糟糕的代码,直到一些IDE插件发布,它不会抱怨@符号的滥用。然后,你希望PHP贡献者注意到这一点,并找到一个新的运算符来抑制错误
真的我不想粗鲁,但这就像期待微软发布windows8的源代码一样,因为有些人已经习惯了linux是开源的。

另一件事:正如我所说,在调试代码时,抑制通知对您没有帮助。众所周知,PHP可以访问其核心/全局命名空间中的许多函数(和保留关键字)。如果你和你的同事养成了滥用@运算符的习惯,你可能会得到这样的代码:

$foo[@die] = [@exit, @constant];

调试那些不清楚的错误,玩得很开心。真的

PHP会将代码中的key视为未知常量。

在大多数语言中,这会使编译器停止,但PHP会将其转换为字符串以保持运行。它发出了警告,但无论如何都会继续。这太糟糕了,你真的不想这么做,更不用说故意这么做了。

PHP中的@用于抑制错误。它什么也不做。

您的@key仍然是一种糟糕的做法,就像key一样,并且将以完全相同的方式工作,但@将隐藏通常会生成的错误消息。

在PHP中使用@错误抑制是一种糟糕的做法,原因有很多(请参阅下面的注释),但将其用作隐藏故意错误代码的方法是很糟糕的。请不要这样做。

这里的基本点是您使用的是PHP,所以您应该编写PHP代码。尝试用PHP编写Ruby代码是行不通的。

你应该使用你正在使用的语言,而不是反对它。

关于为什么错误抑制是一种糟糕的做法的一些想法,你可能想读一读:在PHP中用@operator抑制错误

最后一个想法是:PHP将未知常量转换为字符串的做法纯粹是出于遗留兼容性的原因;这是可以追溯到早期的糟糕语言设计中非常糟糕的一部分。在最近的版本中,许多来自早期PHP的坏东西已经被弃用;这还没有,但没有充分的理由让它仍然存在,所以我有点希望他们也能找到一种方法来贬低这个"功能"。如果他们这样做了,那将立即阻止你的想法发挥作用,无论它有什么优点。

最新更新