天道酬勤,学无止境

为什么三元运算符不能与重定向一起使用(Why won't ternary operator work with redirect)

问题

我喜欢三元运算符。 它确实清理了代码外观,但我有一个案例,它在 Rails 控制器中无法正常运行。

我收到一个语法错误: unexpected tSYMBEG, expecting keyword_do or '{' or '('

我一直遇到这个问题,它点亮了将下面的语句更改为三元运算符的开关。 当我尝试将它与重定向语句结合使用时,它总是会发生。

我不知道有关此的规则吗?

if nexti==0 then
  redirect_to :back
else
  redirect_to edit_playt_path(id: actform['playt_id'], i: nexti)
end

nexti==0 ? redirect_to :back : redirect_to edit_playt_path(id: actform['playt_id'], i: nexti)
回答1

由于散列的隐含性质

Ruby / Rails 将暗示您重定向的参数是一个散列,这在您的示例中具有一些尴尬的含义

当 ruby​​ 暗示要重定向的参数时,它会将其视为以下场景中的散列,它将其解析为

nexti==0 ? redirect_to({:back, : redirect_to edit_playt_path(id: actform['playt_id'], i: nexti})

这是无效的,如果您明确定义哈希/参数,它应该可以工作

nexti==0 ? redirect_to(:back) : redirect_to(edit_playt_path({id: actform['playt_id'], i: nexti}))

大多数 ruby​​ / rails 开发人员会因为这样的原因告诉你避免使用三元组,以及人类对正在发生的事情的一般理解。 Ruby 被认为是一种表达性语言,所以拥抱它。

return redirect_to(:back) if nexti==0
redirect_to(edit_playt_path({id: actform['playt_id'], i: nexti}))
回答2

您需要在对redirect_to的调用中使用括号,以便解析器可以正确理解发生了什么:

nexti==0 ? redirect_to(:back) : redirect_to(edit_playt_path(id: actform['playt_id'], i: nexti))

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 为什么C#三元运算符不能与委托一起使用?(Why doesn't the C# ternary operator work with delegates?)
    问题 分支选择功能时,使用三元运算符选择功能可能很有意义,但这是不可能的。 为什么? public class Demo { protected bool branch; protected void demo1 () {} protected void demo2 () {} public Action DoesntWork() { return branch ? demo1 : demo2; } } 编译器产生以下错误: Cannot implicitly convert type `method group' to `System.Action' 回答1 问题在于demo1不是一个简单的表达式,而是一个方法。 并且方法可以被覆盖,因此它实际上不是一个方法,它是一个方法组。 考虑以下示例: public class Demo { protected bool branch; protected void demo1 (int) {} protected void demo1 () {} protected void demo2 () {} public Action DoesntWork() { return branch ? demo1 : demo2; //Error return demo1; //ok } } 现在, demo1重载了,那么应该使用两个版本中的哪个版本?
  • 在PHP中堆叠多个三元运算符(Stacking Multiple Ternary Operators in PHP)
    问题 这是我写的: $Myprovince = ( ($province == 6) ? "city-1" : ($province == 7) ? "city-2" : ($province == 8) ? "city-3" : ($province == 30) ? "city-4" : "out of borders" ); 但是对于每个领域,我都得到了city-4的价值。 我想使用三元运算符而不是switch/if因为我想尝试一下,看看它会如何做。 这段代码有什么问题? 回答1 其他人已经提出了正确的方法,但是如果您真的想使用三元运算符,则需要使用括号: $province = 7; $Myprovince = ( ($province == 6) ? "city-1" : (($province == 7) ? "city-2" : (($province == 8) ? "city-3" : (($province == 30) ? "city-4" : "out of borders"))) ); 更新的链接 回答2 从左到右评估三元运算符。 因此,如果不正确地对表达式进行分组,将会得到意外的结果。 PHP的建议是[docs]: 建议您避免“堆叠”三元表达式。 在单个语句中使用多个三元运算符时,PHP的行为并不明显。 您的代码实际评估为: ( ( (
  • 为什么我们不能在三元运算符中返回?(Why can't we have return in the ternary operator?)
    问题 说我有一个简单的form ,我想检查form是否已更改。 如果更改了submit则阻止表单提交,因此我使用return,而不是使用if-else语句,而是尝试使用ternary operation但不幸的是,我遇到了错误Uncaught SyntaxError: Unexpected token return但我不明白为什么会出现此错误? 三元运算仅用于分配吗? 在这部分上不确定。 以下只是我正在尝试做的一个示例。 var form_original_data = $("#frmProfile").serialize(); $("#frmProfile").on('submit', function(e) { e.preventDefault(); $("#frmProfile").serialize() != form_original_data ? $("body").append('changed') : return; }) <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <form id="frmProfile"> <input type="text" value="name" /> <input type="submit" value=
  • 为什么我不能在C ++中的三元条件语句中使用“ break”语句?(Why can't I use a “break” statement inside a ternary conditional statement in C++?)
    问题 Node是一个非常简单的类,只有一个构造函数和几个变量:一个“名称”(实际上只是一个字符)和两个子节点指针,分别称为“ left”和“ right”。 我刚刚开始写一些需要放在最左边节点的代码,当我想到这个时,我感到非常高兴: Node *current = this->root; while (true) (current->left != nullptr) ? current = current->left : break; 似乎很简单:在无限循环中,检查current是否有一个左孩子,如果是,则将电流设置为该左孩子,如果没有,则退出循环。 这是一个很酷的单行代码,不是太难读。 (我对此发表了评论!) 好吧,我的编译器不喜欢它: iterator.cpp:20:70: error: expected expression while (true) (current->left != nullptr) ? current = current->left : break; ^ 1 error generated. 同样,仅将一些括号放入while循环中并将三元运算符移至其自己的行也无济于事(毫不奇怪)。 我不得不将其转换为if / else,以便编译器接受它。 有人可以解释它是如何解释单线的,为什么要反对吗? 回答1 三元条件运算符是将多个表达式组合成较大表达式的运算符。
  • 用三元运算符了解C#编译错误(Understanding C# compilation error with ternary operator)
    问题 我从Wrox Professional ASP.NET 4.0 MVC 4本书的第179页(第7章“了解Web应用程序中的安全性向量”)中复制了以下代码,并做了一些小的修改,使其在我的抽象应用程序中protected并作为实用程序方法进行存储,宽Controller protected ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } 上面的代码旨在保护MVC应用程序免受公开重定向攻击,这不是问题的主题。 该代码显然格式正确,可以编译,我相信它可以工作。 当“聪明地”将上面的代码更改为以下单行代码时,就会出现问题 return (Url.IsLocalUrl(returnUrl)) ? Redirect(returnUrl) : RedirectToAction("Index", "Home"); 上面的单行代码应该和扩展代码完全一样(不,ReSharper并不建议我替换它,这是我的倡议)。 编译错误如下: there is no implicit conversion between System
  • 为什么不能重载三元运算符?(Why is it not possible to overload the ternary operator?)
    问题 为什么不能重载三元运算符'?:'? 我经常使用三元运算符来合并if语句,并且很好奇为什么语言设计者选择禁止该运算符重载。 我寻找了一种关于为什么在C ++运算符重载中进行解释的解释,但没有找到描述为什么这不可能的解释。 脚注提供的唯一信息是它不能被重载。 我最初的猜测是,使操作员超负荷几乎总是会违反上面链接中给出的第一或第二个原则。 重载的含义很少是显而易见的,或者会背离其最初的已知语义。 因此,我的问题更多是为什么这是不可能的,而不是如何做到,因为我知道这是不可能完成的。 回答1 我认为当时的主要原因是,似乎不值得为该运算符发明一种新的语法。 没有令牌?: ,因此您必须为此创建许多特殊的语法规则。 (当前的语法规则已operator随后由操作者,这是一种单一令牌。) 正如我们从经验中学到的,可以更合理地使用运算符重载,很明显,我们确实不应该允许&&和||重载。 也可以,因为其他响应指出的原因,也可能不是操作符逗号(因为重载版本不会具有用户期望的顺序点)。 因此,支持它的动机甚至比原来要少。 回答2 如果可以覆盖三元运算符,则必须编写如下代码: xxx operator ?: ( bool condition, xxx trueVal, xxx falseVal ); 要调用覆盖,编译器将必须计算trueVal和falseVal的值。 这不是内置的三元运算符的工作方式
  • 为什么我不能使用三元? 操作员在两个函数调用之间进行选择?(Why can't I use the ternary ? operator to select between two function calls?)
    问题 我最近正在编程,并使用?遇到问题。 :操作数。 这是我的代码。 Random rand = new Random(); for(int x = 0; x < 3; x++) { rand.nextInt(1) == 0 ? vertShip(board) : horizShip(board); } 我的编译器抛出一个错误,指出该行的左侧(rand.nextInt(1)== 0)必须是一个变量。 我尝试了诸如 Random rand = new Random(); int a = rand.nextInt(1); for(int x = 0; x < 3; x++) { a == 0 ? vertShip(board) : horizShip(board); } 或if语句在左侧,但不能解决问题。 有人可以帮助我吗? 回答1 并非每个表达式都是语句。 在此处使用if语句。 请参阅《 Java SE 7 Java语言规范》中的14.8表达语句。 某些类型的表达式可以通过在其后加上分号来用作语句。 ExpressionStatement: StatementExpression ; StatementExpression: Assignment PreIncrementExpression PreDecrementExpression PostIncrementExpression
  • 为什么不能在三元if语句中将可为null的int设置为null? [复制](Why can't I set a nullable int to null in a ternary if statement? [duplicate])
    问题 这个问题已经在这里有了答案: 条件运算符不能隐式转换吗? (3个答案) 7年前关闭。 下面的C#代码: int? i; i = (true ? null : 0); 给我错误: 无法确定条件表达式的类型,因为'<null>'和'int'之间没有隐式转换 这不应该有效吗? 我在这里想念什么? 回答1 编译器尝试评估右手表达式。 null是null , 0是int文字,不是int? 。 编译器试图告诉您它无法确定表达式应评估为哪种类型。 在null和int之间没有隐式转换,因此会出现错误消息。 您需要告诉编译器该表达式应评估为int? 。 int?之间有隐式转换int? 和int ,或介于null和int?之间int? ,因此以下两种方法均应起作用: int? x = true ? (int?)null : 0; int? y = true ? null : (int?)0; 回答2 处理三元运算符时,需要使用default()关键字而不是null。 例子: int? i = (true ? default(int?) : 0); 或者,您可以将null转换为: int? i = (true ? (int?)null : 0); 就我个人而言,我坚持使用default()表示法,实际上,这只是一个首选项。 但是您最终应该只遵循一种特定的表示法,恕我直言。 HTH! 回答3 部分
  • 可空类型和三元运算符:为什么? 10:禁止使用null? [复制](Nullable types and the ternary operator: why is `? 10 : null` forbidden? [duplicate])
    问题 这个问题已经在这里有了答案: 具有Nullable <value>类型的条件运算符分配? (6个答案) 为什么此C#代码无法编译? (4个答案) 7年前关闭。 我刚遇到一个奇怪的错误: private bool GetBoolValue() { //Do some logic and return true or false } 然后,在另一种方法中,如下所示: int? x = GetBoolValue() ? 10 : null; 很简单,如果该方法返回true,则将10分配给Nullable int x。 否则,将null分配给可为null的int。 但是,编译器抱怨: 错误1无法确定条件表达式的类型,因为int和<null>之间没有隐式转换。 我疯了吗? 回答1 编译器首先尝试评估右手表达式: GetBoolValue() ? 10 : null 10是一个int文字(不是int? ),而null则为null 。 这两者之间没有隐式转换,因此会出现错误消息。 如果将右侧表达式更改为以下表达式之一,则它将编译,因为int?之间存在隐式转换int? 和null (#1)以及int和int?之间int? (#2,#3)。 GetBoolValue() ? (int?)10 : null // #1 GetBoolValue() ? 10 : (int?)null // #2
  • 为什么这种方法不起作用? Java三元运算符(Why doesn't this method work? Java ternary operator)
    问题 这段代码有什么问题: void bark(boolean hamlet) { hamlet ? System.out.println("To Bark.") : System.out.println("Not to Bark"); } 回答1 三元运算符不能有不返回值的语句,即void方法。 您需要具有返回值的语句。 您需要重写它。 void bark(boolean hamlet) { System.out.println( hamlet ? "To Bark." : "Not to Bark" ); } 回答2 您可以在Java语言规范15.25中阅读原因。 条件运算符? : 第二个操作数表达式或第三个操作数表达式都是void方法的调用,这是编译时错误。 您需要按照其他一些答案的建议进行操作,并将条件运算符仅应用于参数。 回答3 根据§JLS.15.25: ConditionalExpression: ConditionalOrExpression ConditionalOrExpression ? Expression : ConditionalExpression 条件运算符在语法上是右关联的(它从右到左分组)。 因此,a?b:c?d:e?f:g的含义与a?b:(c?d:(e?f:g))相同。 条件运算符具有三个操作数表达式。 ? :出现在第一和第二个表达式之间,而
  • 三元运算符VB与C#:为什么将Nothing解析为零?(Ternary operator VB vs C#: why resolves Nothing to zero?)
    问题 我只是用脚开枪射击自己,想知道是否有实际原因使这种情况成为可能。 无论如何,这个问题可以留给未来的射手们以方便。 假设我们在vb.net中有一个可为空的值: Dim i as Integer? 我们想根据条件为它分配一个值,并使用三元运算符,因为它是如此的简洁: i = If(condition(), Nothing, 42) 也就是说,如果条件为true ,则采用可为空性,否则采用值。 此时会发生射击。 出于没有明显的原因,VB编译器认为Nothing和Integer的通用基本类型是Integer ,此时它会静默地将语句转换为: i = If(condition(), 0, 42) 现在,如果要在C#中执行此操作: i = (condition()) ? null : 42; 您将立即收到一个编译器错误,指出<null>与int混合不佳。 太好了,因为如果我这次使用C#方式,那么我的脚会更健康。 为了对此进行编译,您必须显式编写: i = (condition()) ? null : (int?)42; 现在,您可以在VB中执行相同的操作,并获得您期望的正确的空值: i = If(condition(), Nothing, CType(42, Integer?)) 但这首先需要把脚拍打。 没有编译器错误,也没有警告。 这是Explicit On , Strict On 。
  • 用三元运算符初始化数组?(Array initialization with a ternary operator?)
    问题 我无权访问C11规范,因此无法调查此错误。 以下声明在编译过程中引发错误: int why[2] = 1 == 1 ? {1,2} : {3,4}; 错误是:{之前的期望表达式和:之前的期望表达式: 回答1 这是无效的C11。 您只能使用初始化列表而不使用表达式来初始化数组。 int why[2] = { ... }; // initializer-list {} 此外, 1 == 1 ? {1,2} : {3,4} 1 == 1 ? {1,2} : {3,4}不是有效的C表达式,因为{1, 2}不是C表达式。 仅出于使用复合文字的信息的考虑,您可以使用指针对象获得与所需内容接近的内容: int *why = (1 == 1) ? (int[2]) {1,2} : (int[2]) {3,4}; 回答2 查尔斯·贝利(Charles Bailey)在这里的回答:条件表达式中的语法 conditional-expression: logical-OR-expression logical-OR-expression ? expression : conditional-expression 和 1 == 1 ? {1,2} : {3,4}; ^ ^ are not expressions 这就是编译器给出如下错误的原因: error: expected expression
  • C语言中的三元(条件)运算符(The ternary (conditional) operator in C)
    问题 条件运算符有什么需要? 从功能上讲,它是多余的,因为它实现了if-else构造。 如果条件运算符比等效的if-else赋值更有效,为什么编译器不能更有效地解释if-else? 回答1 三元运算符是语法和可读性的便利,而不是性能捷径。 由于复杂度各不相同的条件,人们对它的优缺点有所分歧,但是对于较短的条件,使用单行表达式可能会很有用。 而且,由于它是一个表达方式,如查理·马丁(Charlie Martin)所写,这意味着它可以出现在C语言语句的右侧。这对于简洁明了非常有用。 回答2 在C语言中,它的真正用途是它是一个表达式而不是一条语句。 也就是说,您可以将其放在语句的右侧(RHS)。 因此,您可以更简洁地编写某些内容。 回答3 给出的其他一些答案很好。 但是令我惊讶的是,没有人提到它可以用来以紧凑的方式帮助实现const正确性。 像这样的东西: const int n = (x != 0) ? 10 : 20; 所以基本上n是一个const其初始值取决于条件语句。 最简单的办法是使n不是一个const ,这将允许一个普通的if将其初始化。 但是,如果您希望将其设为const ,则无法使用常规if来完成。 您可以做的最好的替代方法是使用如下的辅助函数: int f(int x) { if(x != 0) { return 10; } else { return 20; } }
  • 使用条件?:(三元)运算符的好处(Benefits of using the conditional ?: (ternary) operator)
    问题 与标准的if-else语句相反,?:运算符的优缺点是什么? 显而易见的是: 条件?:运算符 处理直接值比较和赋值时更短,更简洁似乎不如if / else构造灵活 标准If / Else 可以应用于更多情况(例如函数调用) 经常不必要地长 每种陈述的可读性似乎各不相同。 在第一次接触?:运算符之后的一小段时间里,我花了一些时间来准确地理解它的工作方式。 如果我与许多非程序员一起工作,您会建议尽可能使用它,还是坚持使用if / else? 回答1 我基本上建议仅在结果语句非常短并且在不牺牲可读性的情况下,比if / else等效项的简洁性显着提高时,才使用它。 好例子: int result = Check() ? 1 : 0; 不好的例子: int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0; 回答2 其他答案几乎涵盖了这一点,但是“这是一个表达”并不能真正解释为什么它如此有用... 在C ++和C#之类的语言中,您可以使用它们定义本地只读字段(在方法主体内)。 对于常规的if / then语句,这是不可能的,因为必须在该单个语句内分配只读字段的值: readonly int speed = (shiftKeyDown) ? 10 : 1; 与以下内容不同: readonly int
  • 三元运算符和C的归还(Ternary operators and Return in C)
    问题 为什么我们不能在C中的三元运算符中使用return关键字,像这样: sum > 0 ? return 1 : return 0; 回答1 return是一个声明。 不能以这种方式在表达式内部使用语句。 回答2 由于三元运算是一个表达式,因此不能在表达式中使用语句。 您可以轻松地在返回中使用三元运算符。 return sum > 0 ? 1 : 0; 或如DrDipShit所指出的那样: return sum > 0; 回答3 三元运算符处理表达式,但是return是一条语句。 return语句的语法是 return expr ; 三元条件运算符的语法为 expr1 ? expr2 : expr3 因此,您可以在return语句中将三元运算符的调用作为expr插入。 但是您不能以三元运算符的expr2或expr3的形式插入return语句。 三元表达式的行为很像if语句,但是它并不是if语句的精确替代。 如果你想写 if(sum > 0) return 1; else return 0; 您可以将其编写为true if语句,但不能将其转换为using ? : ? :如我们在这里看到的那样,无需稍作重新排列。 回答4 因为return是语句,而不是表达式。 你不能做int a = return 1; 任何一个。 回答5 看到一个三元运算符的语法是 expr1 ? expr2
  • Javascript三元运算符的运算符优先级(Operator precedence with Javascript Ternary operator)
    问题 我似乎无法与三元运算符结合使用此代码的第一部分(+ =)。 h.className += h.className ? ' error' : 'error' 我认为这段代码的工作方式如下: h.className = h.className + h.className ? ' error' : 'error' 但这是不正确的,因为这会在我的控制台中出现错误。 所以我的问题是我应该如何正确插入此代码? 回答1 h.className = h.className + (h.className ? ' error' : 'error') 您希望操作员为h.className工作,最好对此进行具体说明。 当然, h.className += ' error'不会造成任何伤害,但这是另一回事。 另外,请注意, +优先于三元运算符:JavaScript运算符优先级 回答2 这样想: <variable> = <expression> ? <true clause> : <false clause> 语句的执行方式基本上如下: <expression>评估为true还是为false? 如果<expression>计算结果为true,则将<true clause>值分配给<variable> ,将忽略<false clause> ,并执行下<false clause>语句。 如果
  • 为什么我可以在三元运算中将原始类型设置为null(why I can set primitive types to null in ternary operations)
    问题 我一直以为Java中的原始类型不能为null ,因为如果我尝试执行以下操作,这将是编译时错误: int test = null; 但是,在三元运算中,似乎允许这样做: int test = something != 0 ? 5 : null; 这不是三元运算的简称(在这种情况下): int test; if (something != 0){ test = 5; } else { test = null } 当然不应该允许哪个。 如果该条件失败,由于自动装箱,它将自动引发NullPointerException 。 那么,为什么Java编译器不会像这样获取废话呢? 回答1 发生的情况是Java编译器首先尝试使:两侧的表达式类型相等。 在这种情况下,它将5自动装箱为Integer ; 请注意, null是Integer的有效值。 整个三元表达式的结果是Integer 。 您将其分配给int ,然后将Integer自动装箱。 本质上,编译器应用自动装箱和-unboxing,以便该行看起来像这样: int test = (something != 0 ? Integer.valueOf(5) : null).intValue(); 实际上,自动取消装箱null会导致NullPointerException 。 那么,为什么Java编译器不会像这样获取废话呢?
  • 三元运算符-JAVA [重复](Ternary Operator - JAVA [duplicate])
    问题 这个问题已经在这里有了答案: Java三元运算符(6个答案) 6年前关闭。 是否可以更改此: if(String!= null) { callFunction(parameters); } else { // Intentionally left blank } ...对三元运算符? 回答1 好吧,Java中的ternary operator的行为就像这样…… return_value = (true-false condition) ? (if true expression) : (if false expression); ...另一种看待它的方式... return_value = (true-false condition) ? (if true expression) : (if false expression); 您的问题有点含糊,我们必须在这里假设。 如果(且仅当) callFunction(...)声明了一个non-void返回值( Object , String , int , double等等。) -似乎它没有通过您的代码执行此操作-那么您可以执行此操作... return_value = (string != null) ? (callFunction(...)) : (null); 如果callFunction(...)没有返回值
  • 要三元还是不三元? [关闭](To ternary or not to ternary? [closed])
    问题 As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance. Closed 8 years ago. I'm personally an advocate of the ternary operator: () ? : ; I do realize that it has its place, but I have come across many programmers that are completely against ever using it, and some that use it too often. What are your feelings
  • 为什么三元(?:)运算符中的std :: istringstream解析为与std :: ifstream不同?(Why does std::istringstream appear to resolve differently to std::ifstream in the ternary (?:) operator?)
    问题 我习惯于编写使用文件名或从std::cin读取的小命令行工具,因此我已经使用这种模式已有相当长的一段时间了: int main(int argc, char* argv[]) { std::string filename; // args processing ... std::ifstream ifs; if(!filename.empty()) ifs.open(filename); std::istream& is = ifs.is_open() ? ifs : std::cin; std::string line; while(std::getline(is, line)) { // process line... } return 0; } 阅读有关堆栈溢出的问题后,我尝试修改我的惯用模式以适合从文件或从std::istringstream读取的需要。 令我惊讶的是,它无法编译并给出以下错误: temp.cpp:164:47: error: invalid initialization of non-const reference of type 'std::istream& {aka std::basic_istream<char>&}' from an rvalue of type 'void*' std::istream& is = ifs.is_open()