2

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

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

我知道形式常量等存在某些缺点,这与 Ruby 的符号相同:考虑输入错误。是否有任何其他考虑反对使用这种方法?

4

4 回答 4

3

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

我能想到的第一个是

  1. 您正在积极抑制错误,这会花费处理时间
  2. 您的同事需要解释发生了什么,这会花费开发人员的时间
  3. 您正在反对该语言的自然定义(PHP 根本不是 Ruby)
  4. 由于无论如何您都必须对变量使用符号,因此您实际上并没有清理代码。
于 2013-08-08T02:39:09.603 回答
2

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

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

你依赖于一些未定义的常量——这正是通知试图告诉你的。如果定义了该名称的常量,您将获取它的值。

在 Ruby 中,:__LINE____LINE__. 前者是一个符号——无论你在哪里使用它,它都等同于它自己。后者是一个数字,是一个在每一行都改变其值的神奇变量。在 PHP 中,@__LINE__与 相同__LINE__,因为没有要抑制的错误。哦,还有一个特殊的“符号”,调试起来非常有趣:@exit,AKA @die

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

Ruby 的符号不等于其他任何东西。这就是他们存在的目的。当然,它们有一些不错的属性,比如to_sand to_proc,但它们最初的目的是作为标识符,与任何可能的用户输入分开。例如,如果您使用符号来表示词法分析器流中的标记,这有点好,例如[:lparen, 1, :plus, "rparen", :rparen]. 在 PHP 中,未定义的常量是字符串。在红宝石中,?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!";

您不应该依赖未定义的常量,也不应该使用错误抑制来隐藏告诉您的错误消息。您不应该使用特殊符号来假装两个事物不相等。另外,你能相信你的库的用户不会在运行时重新定义常量吗?

于 2013-08-13T10:16:15.560 回答
2

警告:
以下答案包含类比,纯粹是为了说明一点。在任何情况下,我都不建议您考虑某人(您或其他任何人)实际坐下来做我提到的事情的可能性。如此疯狂的谎言


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

为什么要鼓励人们编写引发通知的代码?仅仅因为你喜欢 ruby​​ 语法?来吧,如果你不喜欢一种语言,就不要使用它。我知道:遗留代码,你必须......那么,去做吧,不要试图让它感觉和看起来像 Ruby。它们不是同一种语言。所有让您想起您正在使用不同语言的事实的东西都应该被视为一种工具。不同的语言需要不同的思维方式和不同的思考问题的方式。

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

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

另一件事:正如我所说,在调试代码时,禁止通知对您没有帮助。众所周知,PHP 在其核心/全局命名空间中有许多函数(和保留关键字)。如果您和您的同事养成滥用@操作员的习惯,您最终可能会得到如下代码:

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

愉快地调试那些不清楚的错误。诚实地...

于 2013-08-13T14:45:13.407 回答
0

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

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

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

@key仍然是不好的做法,key并且将以完全相同的方式运行,但是@会隐藏通常会生成的错误消息。

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

这里的基本点是您使用的是 PHP,因此您应该编写 PHP 代码。尝试用 PHP 编写 Ruby 代码永远不会奏效。

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

关于为什么错误抑制是不好的做法的一些想法,您可能想阅读以下内容:在 PHP 中使用 @ 运算符抑制错误

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

于 2013-08-15T10:20:58.137 回答