Почему нет «составного оператора вызова метода», то есть «. =»? - PullRequest
10 голосов
/ 30 сентября 2010

У многих языков программирования уже есть составные операторы +=, -=, /= и т. Д. Относительно новый стиль программирования - это "цепочка" вызовов методов друг с другом, например, в 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 ]

2 голосов
/ 30 сентября 2010

Это поддерживается в Perl 6 .

1 голос
/ 30 сентября 2010

Я не могу ответить на эти вопросы, и я не уверен, что я об этом думаю, потому что я не видел его раньше, но у него есть интересное применение: все операторы на месте становятся устаревшими.

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

Конечно, было бы яснее написать a += 1, но если этот синтаксис появился раньше при разработке языка, а методы __add__ были менее уродливыми (например, просто add),В современном языке может быть на одиннадцать меньше операторов сегодня.

(Конечно, это может иметь и другие последствия - в частности, автоматический откат с __iadd__ до __add__ будетпотеряно. Тем не менее, это интересная концепция.)

1 голос
/ 30 сентября 2010

ИМХО , мне это не нравится.

только представь себе,

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

это больше не синтаксическая ошибка, но это не имеет смысла, не так ли?

Я могу сказать, что это не имеет смысла просто потому, что если вы расширите мой пример, это будет так,

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

items.click(function(){...}); просто вернет объект items, и вы назначите ему items?

в этом примере

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

это имело бы смысл, но не для всех объектов, может быть, поэтому оно не было реализовано.

что касается parent .= children();, что будет с parent позже в кодах?

Я говорю jQuery образом.

0 голосов
/ 02 октября 2010

Ruby имеет эту функцию, но реализует ее по-другому. Это через «разрушительные» методы, которые изменяют переменную, к которой они обращаются. Например, вызов str.split просто возвращает разделение объекта, но не изменяет его. Но, если вы позвоните str.split! это меняет его на месте. Большинство встроенных массивов и строковых методов имеют деструктивную и неразрушающую версию.

0 голосов
/ 30 сентября 2010

Я часто думал об этом при программировании на 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, возможно, не исключено, что он в конечном итоге будет добавлен.

0 голосов
/ 30 сентября 2010

Коллекции 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 s:

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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...