在某些动态语言中,我看到过这种语法:
myValue = if (this.IsValidObject)
{
UpdateGraph();
UpdateCount();
this.Name;
}
else
{
Debug.Log (Exceptions.UninitializedObject);
3;
}
基本上能够返回分支中的最后一个语句作为变量的返回值,不一定只返回方法返回,但也可以实现它们。
此功能的名称是什么?
这也可以用静态类型语言如C#实现吗?我知道C#有三元运算符,但我的意思是使用if语句,如上所示切换语句。
答案 0 :(得分:7)
它被称为“条件分支是表达式”或“声明/表达式分裂的死亡”。
请参阅Conditional If Expressions:
许多语言支持if表达式,它类似于if语句,但返回值作为结果。因此,它们是真正的表达式(评估为值),而不是语句(仅执行操作)。
也就是说,if (expr) { ... }
是表达式(可能是表达式或语句,具体取决于上下文)语法语法就像?:
是C,C#或Java等语言中的表达式一样。
这种形式在函数式编程语言中很常见(避免副作用) - 然而,它不是“函数式编程”本身并且存在于接受/允许“功能”的其他语言中喜欢语法“虽然仍然使用沉重的副作用和其他范例(例如Ruby)。
某些语言(如Perl)允许模拟此行为。也就是说,$x = eval { if (true) { "hello world!" } else { "goodbye" } }; print $x
将显示“你好世界!”因为eval 表达式评估 中评估的最后一个值,即使if
语法生成本身不是表达式。 ($x = if ...
是Perl中的语法错误。)
快乐的编码。
答案 1 :(得分:2)
这是一个三元条件。
在C中你可以使用,例如:
printf("Debug? %s\n", debug?"yes":"no");
编辑:
复合语句列表可以用C表示。最后一个语句应该是一个表达式,整个复合语句用大括号括起来。
例如:
#include <stdio.h>
int main(void)
{
int a=0, b=1;
a=({
printf("testing compound statement\n");
if(b==a)
printf("equals\n");
b+1;
});
printf("a=%d\n", a);
return 0;
}
因此,您正在执行的特性的名称是将(本地)变量分配给复合语句。现在我认为这会对你有所帮助。有关更多信息,请访问此来源: http://www.chemie.fu-berlin.de/chemnet/use/info/gcc/gcc_8.html
保重, BECO。
PS。这个例子在你的问题的上下文中更有意义:
a=({
int c;
if(b==a)
c=b+1;
else
c=a-1;
c;
});
答案 2 :(得分:2)
回答你的另一个问题:
这是否也可以用静态类型语言实现,例如C#?
语言是否支持?不可以实现?那种。
C# - 比如C ++,Java和所有类似的东西 - 都有表达式和语句。语句,如if-then和switch-case,不返回值,因此不能用作表达式。另外,稍微说一下,您的示例将myValue
分配给字符串或整数,C#无法执行,因为它是强类型的。您要么必须使用object myValue
,然后接受投射和装箱费用,请使用var myValue
(仍然是静态类型,只是推断)或其他一些奇怪的聪明。
无论如何,如果if-then
是一个声明,你如何在C#中做到这一点?你必须构建一个方法来实现if-then-else的目标。您可以使用静态方法作为bools的扩展,以模拟Smalltalk的方式:
public static T IfTrue(此bool值,Action doThen,Action doElse) { 如果(值) return doThen(); 其他 return doElse(); }
要使用此功能,您需要执行类似
的操作var myVal = (6 < 7).IfTrue(() => return "Less than", () => return "Greater than");
新的IfTrue()函数检查它附加的布尔值,并执行传递给它的两个委托之一。它们必须具有相同的返回类型,并且都不接受参数(使用闭包,因此无关紧要)。
现在,你应该这样做吗?不,几乎可以肯定不是。它不是正确的C#做事方式,因此令人困惑,而且它的效率远低于使用if-then。你正在处理像IL指令这样的复杂的类和方法调用,.NET将在幕后构建以支持它。
答案 3 :(得分:1)
除了返回分支中最后一个表达式的值之外,可能(取决于语言)myValue
被分配给匿名函数 - 或者在Smalltalk / Ruby中,{{3} }:
代码块(匿名函数)可以表示为文字值(它是一个对象,因为所有值都是对象。)
在这种情况下,由于myValue
实际指向仅在使用myValue
时调用的函数,因此该语言可能将它们实现为code blocks,这最初是功能语言。
因为闭包是带有自由变量的第一类函数,closures。但是,不会发生隐式返回;在C#中,他们只是匿名代表!考虑:
Func<Object> myValue = delegate()
{
if (this.IsValidObject)
{
UpdateGraph();
UpdateCount();
return this.Name;
}
else
{
Debug.Log (Exceptions.UninitializedObject);
return 3;
}
};
这也可以使用lambda表达式在C#中完成:
Func<Object> myValue = () =>
{
if (this.IsValidObject) { ... }
else { ... }
};
我意识到你的问题是询问隐含的返回值,但我试图说明这里不仅仅有“条件分支是表达式”。
答案 4 :(得分:0)
这也可以静态实现 打字语言?
当然,可以静态和严格地检查所涉及的表达式的类型。似乎没有什么依赖于“if-as-expression”方法中的动态类型。
例如,Haskell - 一种严格的静态类型语言,具有丰富的类型系统:
$ ghci
Prelude> let x = if True then "a" else "b" in x
"a"
(示例表达式可能更简单,我只想反映您的问题中的赋值,但演示该功能的表达式可能是simlpler:
Prelude> if True then "a" else "b"
"a"
)