考虑以下:
if(a == b or c)
在大多数语言中,这需要写成:
if(a == b or a == c)
这有点麻烦并且会重复信息。
我知道我上面的示例语法有点笨拙,但是我确信有更好的方法来传达这个想法。
为什么没有更多的语言提供它?是否存在性能或语法问题?
考虑以下:
if(a == b or c)
在大多数语言中,这需要写成:
if(a == b or a == c)
这有点麻烦并且会重复信息。
我知道我上面的示例语法有点笨拙,但是我确信有更好的方法来传达这个想法。
为什么没有更多的语言提供它?是否存在性能或语法问题?
Answers:
语法问题是–它需要语法。
无论您的语言使用哪种语法,使用该语言的人们都必须学习它。否则,他们冒着看到代码而又不知道代码做什么的风险。因此,如果一种语言具有可以轻松处理很多情况的简单语法,通常被认为是一件好事。
在您的特定示例中,您尝试采用infix运算符(一个带有两个参数但被编写的函数Argument1 Operator Argument2
),并试图将其扩展为多个参数。这并不是很干净,因为在某种程度上,中缀运算符的全部要点是将运算符放在2个参数之间。扩展到(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
似乎并没有增加太多的清晰度Equals(Arg1,Arg2,...)
。Infix通常还用于模拟人们熟悉的数学约定,而对于其他语法则不是这样。
除了您的想法没有任何特定的性能问题外,解析器将不得不处理具有另一条或两条生产规则的语法,这可能会对解析速度产生轻微影响。对于解释型或JIT编译语言,这可能会有所不同,但可能不会有很大的不同。
这个想法的更大问题是,用一种语言编写很多特殊情况往往是个坏主意。
.
。因此它们将被写为arg1 op (arg2, arg3)
。并非完全漂亮,但在某些地方需要使用该语言。
a == b or c
而其他人则需要a == b or c but not d
。IMO是拯救实用程序功能/库的地方。
f().Equals(a,b,c)
; 可以评估(var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
该语法是否完美,但是如果评估该语法int[] arr = {a,b,c}; f().Equals(arr);
效果不好,尤其是在必须为每个调用创建一个新数组的情况下。
因为这是一个非问题,解决它带来的收益基本上为零,但是实施它带来的成本却为非零。
现有的基于范围的功能以及几乎每种语言都可以提供的功能在这种情况下可以很好地工作,前提是它可以缩放到a == b || a == c
不会削减的大小。
in_array($a, [$b, $c, $d, $e, $f])
。:P
某些语言确实具有此类功能。例如,在Perl6中,我们可以使用Junctions,它们是两个值的“叠加”:
if $a == any($b, $c) {
say "yes";
}
# syntactic sugar for the above
if $a == $b | $c {
say "yes";
}
连接使我们能够非常简洁地表达对一组数据的操作,类似于标量操作以某些语言在集合上分布的方式。例如,将Python与numpy结合使用,可以将比较分布在所有值上:
import numpy as np
2 == np.array([1, 2, 3])
#=> np.array([False, True, False], dtype=np.bool)
(2 == np.array([1, 2, 3])).any()
#=> True
但是,这仅适用于选定的原始类型。
为什么路口有问题?因为联结上的操作分布在包含的值上,所以联结对象本身的行为就像方法调用的代理一样,除了鸭子类型之外,很少有类型系统可以处理。
如果只允许这样的连接作为比较运算符周围的特殊语法,则可以避免类型系统问题。但是在这种情况下,它们的局限性太大,以至于它们无法添加足够的价值以添加到任何理智的语言中。可以使用set操作或手动拼出所有比较来表达相同的行为,并且如果已经有一个非常好的解决方案,则大多数语言都不相信添加冗余语法。
2 in [1, 2, 3]
。另一方面,如果numpy具有a .all()
或诸如此类的含义,则等效的纯Python几乎不那么简洁。
==
运算符,但我们也可以使用<
-您in
现在在哪里?结点比集合成员资格测试更笼统,因为结点上的操作分布在所有成员上- (x|y).foo
为x.foo|y.foo
,直到结点最终折叠为单个值为止。假定原始类型,所提供的NumPy代码显示Perl6结的完全等效但更详细的翻译。
在带有宏的语言中,很容易添加不存在的宏。考虑球拍
(define-syntax-rule (equal-any? a b ...)
(or (equal? a b) ...))
(equal-any? "a" "b" "a")
> #t
在其他没有元编程的语言中,也许您可以将其重新设置为集合/列表成员资格检查,也许是:
if a ∈ {b, c}
在某些(流行)语言中,==
运算符不是可传递的。例如在JavaScript 0
等于既''
和'0'
,但后来''
和'0'
彼此不相等。PHP中有更多此类怪癖。
这意味着a == b == c
将增加另一个歧义,因为根据它被解释为(a == b) & (a == c)
还是,可能会产生不同的结果(a == b) & (a == c) & (b == c)
。
在大多数语言中,只要编写一个 In
函数轻松实现这一点,那么为什么要使其成为实际语言的一部分呢?
例如,Linq有 Contains()
。
好了,对于您所有的学徒,这是我在C#中的实现:
public static bool In<T>(this T obj, params T[] values)
{
for(int i=0; i < values.Length; i++)
{
if (object.Equals(obj, values[i]))
return true;
}
return false;
}
a == b || a == c
多次写作,也许是时候了equals_any(a, {b, c})
if (a > (b or c))
和的东西if (a mod (b or c) == 2)
。
i
变量。总的来说,这似乎是在您度过了漫长的一天之后写的:)因为将两者return true
和return false
循环都放在此处意味着没有办法使它超出第一次迭代。您只是在与第一个进行比较value
。顺便说一句,为什么不Any
按照@Bob的建议使用,并将其简化为return values.Any(value => Object.Equals(obj, value));
“ if(a == b或c)”适用于大多数语言:如果a == b或c不为负,为null或为零。
抱怨它太冗长就错了这一点:您不应该将许多东西堆成条件对象。如果需要将一个值与任意数量的其他值进行比较,则构建一个子例程。
c
计算结果为布尔值,那么几乎所有语言都可以处理a == b || c
:)
if(a == b or c)
。我想休息一下...:P
if (a == b or c)
是检查是否a
等于b
或a
等于的伪代码c
。这并不意味着要检查它c
是否为非零。
通常,您希望最小化语法,而是允许在语言本身中定义此类构造。
例如,在Haskell中,您可以使用反引号将具有两个或多个参数的任何函数转换为infix运算符。这使您可以编写:
if a `elem` [b, c] then ... else ...
这里elem
只是一个带有两个参数的普通函数-一个值和一个值列表-并检查第一个是否为第二个元素。
如果要使用and
代替该or
怎么办?在Haskell中,您可以仅使用以下内容,而不必等待编译器供应商实现新功能:
if all (== a) [b, c] then ... else ...
某些语言确实在某种程度上提供了这一点。
也许不作为您的特定示例,但以Python行为例:
def minmax(min, max):
def answer(value):
return max > value > min
return answer
inbounds = minmax(5, 15)
inbounds(7) ##returns True
inbounds(3) ##returns False
inbounds(18) ##returns False
因此,只要您正确表达某些语言,就可以进行多次比较。
不幸的是,它无法像您期望的那样进行比较。
>>> def foo(a, b):
... def answer(value):
... return value == a or b
... return answer
...
>>> tester = foo(2, 4)
>>> tester(3)
4
>>> tester(2)
True
>>> tester(4)
4
>>>
“您是什么意思,它返回True还是4?” -您之后的租用
在这种情况下,至少对于Python,一种解决方案是稍有不同:
>>> def bar(a, b):
... def ans(val):
... return val == a or val == b
... return ans
...
>>> this = bar(4, 10)
>>> this(5)
False
>>> this(4)
True
>>> this(10)
True
>>> this(9)
False
>>>
编辑:以下也将在Python中做类似的事情...
>>> def bar(a, b):
... def answer(val):
... return val in (a, b)
... return answer
...
>>> this = bar(3, 5)
>>> this(3)
True
>>> this(4)
False
>>> this(5)
True
>>>
因此,无论您使用哪种语言,都不一定不是您无法做到,只是您必须首先仔细研究逻辑的实际工作方式。通常,这只是知道您在“实际询问”要告诉您的语言的问题。