开发者

Why is there no "compound method call statement", i.e. ".="?

Lots of programming languages already have the compound statements +=, -=, /=, etc. A relatively new style of programming is to "chain" method calls onto each other, e.g. in Linq, JQuery and Django's ORM.

I sometimes, more often 开发者_如何学JAVAthan I'd like, find the need to do this in 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')

I think it would be easier and actually more readable if there was a compound method call statement such as .= which could work like this:

items = Items.objects.filter(desc__startswith='A')
if something:
    items .= filter(desc__endswith='Z')
  • Are there any programming languages that support this or something like it?
  • If the answer is no, why not?
  • Is this style of programming really that new?
  • Are there any PEPs (Python Enhancement Proposals) that support this idea?


This is supported in Perl 6.


I can't answer those questions, and I'm not sure what I think of this because I havn't seen it before, but it does have an interesting applicatioon: all of the inplace operators become obsolete.

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

Of course, it's clearer to write a += 1, but if this syntax had come earlier in the design of the language, and the __add__ methods were less ugly (eg. just add), the language today might have eleven fewer operators today.

(Of course, there would be other implications of that--in particular, the automatic fallback from __iadd__ to __add__ would be lost. Still, it's an interesting concept.)


IMHO, i don't like it.

just imagine this,

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

it's not a syntax error anymore, but it doesn't make sense, does it?

I can say it does not make sense simply because if you expand my example, it would be like this,

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

items.click(function(){...}); would just return the object items , and you will assign it to items?

in this example,

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

it would make sense, but not true to all objects, maybe that's the reason it was not implemented.

as to parent .= children();, what happens to parent later on the codes?

I'm talking jQuery way.


Scala's collections support in-place operations, provided that the variable is a 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)

(For those unfamiliar with Scala, :: is a method of List)

This is a style of programming that many avoid, and in Scala you can avoid such in-place mutation by using immutable vals:

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"


I have thought about this often when doing Java or C# programming, where you find yourself repeating not just one but often the same two or more object references on both sides of the assignment -- e.g., you have a member of some object that is a string, and you want to call some methods on that string and assign it back to the member variable. Oddly enough, it hasn't bothered me nearly as much in Python.

The .= operator you propose is one idea I thought of at the time I was doing C#. Another option would be to allow a leading dot to as a shorthand for the object being assigned to, like this:

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

Pascal, Modula-2, and Visual Basic have a with statement (different from Python's statement of the same name) that would allow you to write something like this if it existed in Python (I call it "using" here so it is not mistaken for valid Python):

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

This is very convenient when you are going to be doing a lot of manipulation of members of a single object since it allows a block. However, you still have a level of redundancy here, which could be eliminated if you combined the last two ideas like so:

using foo.bar:
    str = .lower()

This seems to me like it would be a nice bit of syntactic sugar, and I find it very readable, but it does not seem like it is high on the priority list of most language designers. However, since Python does have Modula-2 influences, perhaps it's not out of the question that it would eventually be added.


Ruby has this feature in a way, but implements it differently. This is through 'destructive' methods, which alter the variable they are called on. For example, calling str.split just returns the object split, it doesn't alter it. But, if you call str.split! it changes it in place. Most builtin array and string methods have a destructive and non-destructive version.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜