2016-11-18 17 views
0

Правильно ли я понял, что в (большинство? Некоторых?) Нескольких языков рассылки каждый метод добавляется к функции в какой-то момент времени выполнения программы.Являются ли функции изменчивыми в нескольких системах отправки?

Могу ли я тогда заключить, что множественная отправка как функция заставляет функции быть изменяемыми?

Есть ли несколько языков отправки, где все методы присоединены к (общей) функции вместе (во время загрузки?), Так что невозможно увидеть функцию в разных состояниях в разные моменты времени?

+1

Возможно, короткий ответ заключается в том, что в Юлии каждая * общая функция * представляет собой набор функций для разных подписей, каждый из которых не является изменяемым. Большинство вызовов функции Julia * * выбирают специальную сигнатуру функции для вызова во время компиляции с использованием системы вывода типов. Если вы будете подробно описывать функции * безстоящего программирования *, которые вас беспокоят, это поможет их решить. –

+1

@DanGetz, я на самом деле не был обеспокоен * о изменчивости - я просто хотел лучше понять мультиметоды. Теперь я отредактировал свой вопрос. – Aivar

ответ

5

в какой-то момент времени выполнения программы.

В Common Lisp методы добавляются/заменяются при выполнении определений методов - для скомпилированной системы это обычно при загрузке скомпилированного кода - необязательно во время выполнения программы.

Помните, что Common Lisp имеет объектную систему (CLOS, Common Lisp Object System), которая определяется его поведением. Он немного отличается от языка или расширения для .

Common Lisp позволяет выполнять временную модификацию объектной системы. Например, добавление/удаление/замена методов.

Common Lisp также может объединить более чем одного применимым методом в эффективный метод, который затем запускается на выполнение. Типичный пример: все применимые методы :before и наиболее специфический применимый первичный метод будут объединены в один эффективный метод .

В некоторых реализациях существуют расширения для CLOS, которые печать общая функция против изменений.

Для более длительной обработки идеи объектной системы см: The Structure of a Programming Language Revolution Richard P. Gabriel.

2

Перефразируя из отличной «Getting started with Julia» книги, которая имеет хороший раздел на этом (курсив):

Мы уже видели, что функции по своей природе определяется как родовое, то есть они могут быть использованы для различных типы их аргументов. Компилятор будет генерировать отдельную версию функции каждый раз, когда она вызывается с аргументами нового типа. Конкретная версия функции для конкретной комбинации типов аргументов называется методом в Julia. Чтобы определить новый метод для функции (также называемой перегрузкой), просто используйте одно и то же имя функции, но другую подпись, то есть с разными типами аргументов.

Список всех методов хранится в таблице виртуального метода (vtable) самой функции; методы не относятся к определенному типу.Когда функция вызывается, Джулия выполнит поиск в этой vtable во время выполнения, чтобы найти, какой конкретный метод он должен вызывать на основе типов всех своих аргументов; это механизм множественной отправки Julia, который не реализует ни Python, ни C++, ни Fortran. Он позволяет открывать расширения, где нормальный объектно-ориентированный код заставил вас изменить класс или подкласс существующего класса и, таким образом, изменить вашу библиотеку. Обратите внимание, что для множественной отправки учитываются только позиционные аргументы, а не аргументы ключевых слов.

Для каждого из этих различных методов создается специализированный низкоуровневый код, предназначенный для набора инструкций процессора. В отличие от объектно-ориентированных (OO) языков, vtable хранится в функции, а не в типе (или классе). В языках OO метод вызывается на одном объекте object.method(), который обычно называется одной отправкой. В Julia можно сказать, что функция принадлежит нескольким типам или что функция специализирована или перегружена для разных типов. Способность Julia скомпилировать код, который читается как высокоуровневый динамический язык в машинный код, который почти полностью работает как C, получена из его способности выполнять множественную отправку.

Итак, как я понимаю (я могу ошибаться), что:

  • Родовая функция должна быть определен в ходе сессии, прежде чем вы можете использовать его
  • Явных определенные методы конкретные аргументы добавляются в таблицу поиска множественной отправки функции в той точке, где они определены.
  • Всякий раз, когда вызывается функция с определенными аргументами, для которой явно установленный метод не существует, конкретная версия для этих аргументов компилируется и добавляется в таблицу vtable. (однако это не отображается как явный метод, если вы запустили methods() на имя этой функции)
  • Первый вызов такой функции приведет к некоторым издержкам компиляции; однако последующие вызовы будут использовать существующую скомпилированную версию *.

Я бы не сказал, что делает функции изменяемые хотя, это совсем другой вопрос. Вы можете подтвердить, что они неизменяемы, используя функцию isimmutable() на функции 'handle'.


* Я знаю, что модули могут быть прекомпилирована, но я не совсем уверен, если они на лету скомпилированные версии сохраняются между сессиями в любой форме - комментарии приветствуются :)

2

Динамичность может быть реальным активом в вашем приложении, хотя бы для отладки. Попытка предотвратить обновление функции, переопределение и т. Д. Может быть немного близорукой. Но если вы уверены, что хотите статическую отправку, вы можете определить свой собственный класс общих функций благодаря MOP, Протоколу метаобъектов, который не является частью стандарта, но в значительной степени поддерживается. Это то, что предоставляет библиотека Inlined-Generic-Function (и это возможно, поскольку CLOS открыт для расширений).

2

В Common Lisp, вы можете прочитать следующие из спецификации:

7.6.1 Introduction to Generic Functions

Когда defgeneric форма оценивается, один из трех действий принимается (из-за ensure-generic-function):

  • Если общая функция данного имени уже существует, изменяется существующий универсальный функциональный объект. Добавляются методы, заданные текущей формой defgeneric, и любые методы в существующей общей функции, которые были определены предыдущей формой defgeneric, удаляются. Методы, добавленные текущей формой defgeneric, могут заменить методы, определенные defmethod, defclass, define-condition или defstruct. Никакие другие методы в общей функции не затрагиваются или не заменяются.
  • Если заданное имя называет обычную функцию, то сигнализируется макрос или специальный оператор.
  • В противном случае создается общая функция с методами, определенными определениями метода в форме defgeneric.

7.6.2 Introduction to Methods

Когда метод-определение формы оцениваются, объект метода создан и одно из четырех действий берутся:

  • Если родовая функция данного имя уже существует, и если объект метода уже существует, что согласуется с новым в параметризаторах и определителях, новый объект метода заменяет старый. Для определения одного метода, согласующегося с другим по параметрическим специалистам и квалификаторам, см. Раздел 7.6.3 (Соглашение о специалистах и ​​квалификаторах параметров).
  • Если общая функция данного имени уже существует и если нет объекта метода, который согласуется с новым в параметризаторах и классификаторах, существующий универсальный функциональный объект модифицируется, чтобы содержать новый объект метода.
  • Если заданное имя называет обычную функцию, то сигнализируется макрос или специальный оператор.
  • В противном случае создается универсальная функция с помощью метода, определяемого формой, определяющей метод.

Определение ensure-generic-function:

Если имя-функции определяет обобщенную функцию, которая имеет другое значение для :lambda-list аргумента, и новое значение сравнимо с лямбда-списки всех существующих методов или нет методов, значение изменяется; в противном случае сигнализируется ошибка.

Если имя функции задает общую функцию, которая имеет другое значение для аргумента :generic-function-class, и если новый универсальный класс функций совместим со старым, то для изменения класса универсальной функции вызывается change-class; в противном случае сигнализируется ошибка.

Если имя функции задает общую функцию, которая имеет другое значение для аргумента :method-class, значение изменяется, но любые существующие методы не изменяются.

У вас также есть add-method и remove-method.

Как вы можете видеть, общие функции сохраняют свою идентификацию между определениями defmethod и даже между определениями defgeneric. Общие функции изменяются в Common Lisp.


В Джулии, вы можете прочитать следующие из документации:

Defining Methods

Чтобы определить функцию с несколькими способами, один просто определяет функцию несколько раз, с разными номерами и типы аргументов. Первое определение метода для функции создает объект функции, а последующие определения метода добавляют новые методы к существующему объекту функции.

Как вы можете видеть, объекты функций изменяются в Юлии.


Это ничего не говорит обо всех других языках рассылки. Вы можете придумать несколько языков отправки прямо сейчас, чтобы показать, что вы можете сделать это с неизменностью, например. методы добавления возвращают новую функцию, аналогичную предыдущей функции, но с добавленным методом. Или язык, на котором функции генерируются статически во время компиляции, так что вы не можете каким-либо образом изменить его во время выполнения, даже не добавлять или удалять методы.