为什么没有“复合方法调用语句”,即“。=”?

时间:2010-09-30 08:47:34

标签: jquery python linq programming-languages syntax

许多编程语言已经具有复合语句+=-=/=等。一种相对较新的编程方式是将方法调用“链接”到彼此,例如在Linq,JQuery和Django的ORM中。

我有时候,经常发现需要在Django中执行此操作:

# Get all items whose description beginning with A
items = Items.objects.filter(desc__startswith='A')
if something:
    # Filter further to items whose description also ends with Z
    items = items.filter(desc__endswith='Z')

我认为如果有一个复合方法调用语句(例如.=可以这样工作,那么它会更容易,实际上更具可读性:

items = Items.objects.filter(desc__startswith='A')
if something:
    items .= filter(desc__endswith='Z')
  • 是否有支持此类或类似内容的编程语言?
  • 如果答案是否定的,为什么不呢?
  • 这种编程方式真的很新吗?
  • 是否有支持这一想法的PEP(Python增强建议)?

6 个答案:

答案 0 :(得分:2)

Perl 6支持此功能。

答案 1 :(得分:1)

恕我直言,我不喜欢它。

想象一下,

items .= click(function(){...});

它不再是语法错误,但它没有意义,是吗?

我可以说它没有意义,因为如果你扩展我的例子,它会是这样的,

items = items.click(function(){...});

items.click(function(){...});只会返回对象items,您会将其分配给items

在这个例子中,

items .= filter(desc__endswith='Z');

它会有意义,但并不适用于所有对象,也许这就是它没有实现的原因。

至于parent .= children();parent稍后代码会发生什么?

我说的是jQuery方式。

答案 2 :(得分:1)

我无法回答这些问题,而且我不确定我对此的看法,因为我以前从未见过它,但确实有一个有趣的应用:所有的现场操作员都已经过时了。

a = 1
a .= __add__(1)
a .= __mul__(2)

当然,编写a += 1更清楚,但如果语法设计中的语法较早,__add__方法不那么难看(例如add ),今天的语言今天可能只有 11个更少的运营商。

(当然,还会有其他含义 - 尤其是从__iadd____add__的自动回退将会丢失。但这仍然是一个有趣的概念。)

答案 3 :(得分:0)

Scala的集合支持就地操作,前提是该变量为var

scala> var L = List("b", "c")
L: List[java.lang.String] = List(b, c)

scala> L ::= "a"

scala> L
res8: List[java.lang.String] = List(a, b, c)

(对于那些不熟悉Scala的人,::是一种List的方法

这是许多人避免的编程风格,在Scala中,您可以通过使用不可变val来避免这种就地突变:

scala> val L = List("b", "c")
L: List[java.lang.String] = List(b, c)

scala> L ::= "a"
<console>:7: error: reassignment to val
       L ::= "a"

答案 4 :(得分:0)

在进行Java或C#编程时,我经常考虑过这种情况,在这种情况下,你发现自己不仅重复了一个,而且在赋值的两边经常使用相同的两个或更多个对象引用 - 例如,你有一个对象的成员这是一个字符串,您希望在该字符串上调用一些方法并将其分配回成员变量。奇怪的是,它在Python中几乎没有让我感到困扰。

你提出的.=运算符是我在做C#时想到的一个想法。另一种选择是允许前导点作为被分配对象的简写,如下所示:

foo.bar.str = .lower()  # same as foo.bar.str = foo.bar.str.lower()

Pascal,Modula-2和Visual Basic有一个with语句(不同于Python的同名语句),如果它存在于Python中,你可以编写类似这样的语句(我称之为“使用“这里没有错误的有效Python):

using foo.bar:
    str = str.lower()  # same as foo.bar.str = foo.bar.str.lower()

当你要对一个对象的成员进行大量操作时,这非常方便,因为它允许一个块。但是,您仍然具有一定程度的冗余,如果您将最后两个想法合并在一起,则可以将其消除:

using foo.bar:
    str = .lower()

在我看来,这似乎是一个很好的语法糖,我发现它非常易读,但它似乎并不像大多数语言设计师的优先级列表。但是,由于Python确实具有Modula-2影响,因此最终可能会添加它并不是不可能的。

答案 5 :(得分:0)

Ruby在某种程度上具有此功能,但以不同方式实现它。这是通过'破坏性'方法,改变它们被调用的变量。例如,调用str.split只返回对象split,它不会改变它。但是,如果你打电话给str.split!它改变了它。大多数内置数组和字符串方法都具有破坏性和非破坏性版本。