DOM_DOMAIN
Тип данных типов данных
Блокноты MuPAD® будут демонтированы в будущем релизе. Используйте live скрипты MATLAB® вместо этого.
Live скрипты MATLAB поддерживают большую часть функциональности MuPAD, хотя существуют некоторые различия. Для получения дополнительной информации смотрите, Преобразовывают Notebook MuPAD в Live скрипты MATLAB.
DOM_DOMAIN
является типом данных типов данных.
Каждый объект MuPAD® имеет уникальный тип данных. Поскольку тип данных является объектом MuPAD также, он должен самостоятельно иметь тип данных; типом данных, включающим все типы данных (включая себя), является DOM_DOMAIN
.
Существует два вида элементов DOM_DOMAIN
: типы данных ядра и типы данных, заданные в библиотеке или пользователем (области). Объекты, которые имеют тип данных последнего вида, называются доменными элементами.
Тип данных имеет ту же внутреннюю структуру как таблица; его записи называются слотами. Один конкретный слот является ключом; никакие два различных типа данных не могут иметь тот же ключ. Большинство других слотов определяет, как аргументы того типа данных обработаны функциями.
Если пользовательская область была создана, она не может быть уничтожена.
Наш первый пример происходит от этнологии: некоторые языки в Полинезии не имеют слов для чисел больше, чем три; каждое целое число, больше, чем три, обозначается словом “многие”. Следовательно два плюс два не равняется четыре, но “многие”. Мы собираемся реализовать область для этого вида целых чисел; другими словами, мы собираемся реализовать тип данных для конечного множества {1, 2, 3, many}.
S := newDomain("Polynesian integer")
На данном этапе мы задали новый тип данных: объект MuPAD может быть полинезийским целым числом теперь. Никакие операции еще не доступны; область состоит из своего ключа только:
op(S)
Даже при том, что еще нет никаких методов для ввода и вывода доменных элементов, полинезийские целые числа могут быть введены и отображены прямо сейчас. Необходимо использовать функциональный new
для определения доменных элементов:
x := new(S, 5)
Теперь, x
является полинезийским целым числом:
type(x)
Конечно, MuPAD не может знать то, что имеет значение полинезийского целого числа и какова его внутренняя структура должна быть. Аргументы вызова функционального new
только хранятся как нулевое, во-первых, и т.д. операнд доменного элемента, не проверяя их. Можно вызвать new
со столькими аргументами, сколько вы хотите:
new(S, 1, 2, 3, 4); op(%)
new
не может знать, что полинезийские целые числа должны иметь точно один операнд и что мы хотим, чтобы 5
был заменен many
. Чтобы достигнуть этого, мы реализуем наш собственный метод "new"
; это также позволяет нам проверять аргумент. У нас есть еще одна проблема: доменные методы должны относиться к области; но они не должны зависеть от того, что область в настоящее время хранится в S
. С этой целью MuPAD имеет специальную локальную переменную dom
, который всегда относится к области, которой принадлежит процедура:
S::new := proc(i : Type::PosInt) begin if args(0) <> 1 then error("There must be exactly one argument") end_if; if i > 3 then new(dom, hold(many)) else new(dom, i) end_if end_proc:
Вызов функции к области, такой как S(5)
теперь неявно вызывает метод "new"
:
S(5)
S("nonsense")
Error: Invalid object '"nonsense"'. Type of argument number 1 must be 'Type::PosInt'. Evaluating: S::new
На следующем шаге мы задаем наш собственный выходной метод. Полинезийский целочисленный i
, скажем, не должен быть распечатан как new(Polynesian integer, i)
, только его внутреннее значение 1
, 2
, 3
, или many
должен появиться на экране. Обратите внимание на то, что это значение является первым операндом структуры данных:
S::print := proc(x) begin op(x, 1) end_proc: S(1), S(2), S(3), S(4), S(5)
К настоящему времени, ввод и вывод элементов S
были заданы. Остается задавать, как функции и операторы MuPAD должны реагировать на полинезийские целые числа. Это сделано путем перегрузки их. Однако не необходимо перегрузить каждую из тысяч функций MuPAD; для некоторых из них поведение по умолчанию приемлемо. Например, функции манипуляции с выражениями оставляют доменные элементы неизменными:
x := S(5): expand(x), simplify(x), combine(x); delete x:
Арифметические операции обрабатывают доменные элементы как идентификаторы; они автоматически применяют ассоциативный закон и закон коммутативности для сложения и умножения:
(S(3) + S(2)) + S(4)
В нашем случае это не то, что мы хотим. Таким образом, мы должны перегрузить оператор +
. Операторы перегружаются путем перегрузки соответствующих “функций подчеркивания”; следовательно, мы должны записать методу "_plus"
:
S::_plus := proc() local argv; begin argv := map([args()], op, 1); if has(argv, hold(many)) then new(dom, hold(many)) else dom(_plus(op(argv))) end_if end_proc:
Теперь, сумма полинезийских целых чисел вызывает этот слот:
S(1) + S(2), S(2) + S(3) + S(7)
При удалении идентификатора S
не уничтожает нашу область. Это может все еще быть восстановлено с помощью newDomain
.
delete S: op(newDomain("Polynesian integer"))
Мы могли теперь дать подобный пример для более усовершенствованной полинезийской математики с числами до десяти, сказать. Это приводит к вопросу, необходимо ли ввести весь код снова и снова каждый раз, когда мы решаем рассчитать немного дальше. Это не; это - одно из преимуществ доменных конструкторов. Доменный конструктор может рассматриваться как функция, которая возвращает область в зависимости от некоторых входных параметров. Это имеет несколько дополнительных функций. Во-первых, дополнительные ключевые слова category
и axiom
доступны для определения математической структуры области; в нашем случае у нас есть структура коммутативной полугруппы, где различные доменные элементы имеют различные математические значения (мы вызываем это область с каноническим представлением). Во-вторых, часть инициализации может быть задана, который выполняется точно однажды для каждой области, возвращенной конструктором; это должно, по крайней мере, проверять, что параметры передали конструктору. Каждая область, созданная таким способом, может наследовать методы от других областей, и это должно, по крайней мере, наследовать методы Dom::BaseDomain
.
domain CountingUpTo(n : Type::PosInt) inherits Dom::BaseDomain; category Cat::AbelianSemiGroup; axiom Ax::canonicalRep; new := proc(x : Type::PosInt) begin if args(0) <> 1 then error("There must be exactly one argument") end_if; if x > n then new(dom, hold(many)) else new(dom, x) end_if end_proc; print := proc(x) begin op(x, 1) end_proc; _plus := proc() local argv; begin argv:= map([args()], op, 1); if has(argv, hold(many)) then new(dom, hold(many)) else dom(_plus(op(argv))) end_if end_proc; // initialization part begin if args(0) <> 1 then error("Wrong number of arguments") end_if; end:
Теперь, CountingUpTo
является доменным конструктором:
type(CountingUpTo)
Мы задали доменного конструктора CountingUpTo
, но мы еще не создали область. Это сделано путем вызова конструктора:
CountingUpToNine := CountingUpTo(9); CountingUpToTen := CountingUpTo(10)
Мы теперь можем создать, вывести, и управлять доменными элементами как в предыдущем примере:
x := CountingUpToNine(3): y := CountingUpToNine(7): x, x + x, y, x + y, y + y
x := CountingUpToTen(3): y := CountingUpToTen(7): x, x + x, y, x + y, y + y
delete CountingUpToNine, CountingUpToTen, CountingUpTo, x, y:
Никакой доменный конструктор с тем же именем не может использоваться снова во время того же сеанса.
Предположим, что ваша область действительно не зависит от параметра, но что вам нужны некоторые из других функций доменных конструкторов. Затем можно задать доменного конструктора dc
, скажем, который называется без параметров. От такого доменного конструктора можно создать точно один доменный dc()
. Вместо того, чтобы задать конструктора через domain dc() ... end
сначала и затем использовать d := dc()
, чтобы создать доменный d
, скажем, можно непосредственно ввести domain d ... end
, таким образом, сохранение некоторых работает.
При продолжении предыдущих примеров предположите, что мы хотим считать до трех, зная, что мы никогда не хотим рассчитать дальше. Однако мы хотим объявить, что наша область Абелева полугруппа с каноническим представлением элементов. Это не возможно с конструкцией области с помощью newDomain
в качестве в Примере 1: мы должны использовать область ключевого слова. Вы заметите целиком, что следующий исходный код почти идентичен тому в предыдущем примере — мы только удалили зависимость от параметра n
.
domain CountingUpToThree inherits Dom::BaseDomain; category Cat::AbelianSemiGroup; axiom Ax::canonicalRep; new := proc(x : Type::PosInt) begin if args(0) <> 1 then error("There must be exactly one argument") end_if; if x > 3 then new(dom, hold(many)) else new(dom, x) end_if end_proc; print := proc(x) begin op(x, 1) end_proc; _plus := proc() local argv; begin argv:= map([args()], op, 1); if has(argv, hold(many)) then new(dom, hold(many)) else dom(_plus(op(argv))) end_if end_proc; end:
Теперь, CountingUpToThree
является областью и не доменным конструктором:
type(CountingUpToThree)
Можно использовать эту область таким же образом в качестве CountingUpTo(3)
в Примере 2.
Когда названо как функция, тип данных создает новый объект этого типа данных из аргументов вызова. Например, вызов, DOM_LIST(1, 2, x)
генерирует список [1, 2, x]
доменного типа DOM_LIST
(несмотря на то, что в этом случае вы, вероятно, предпочитаете вводить в [1, 2, x]
непосредственно, который приводит к тому же объекту). Это зависит от конкретного типа, какие аргументы допускают здесь.
В случае области называется метод "new"
той области.
Можно получить слоты области с помощью slot
. Функциональный slot
может также использоваться на левой стороне присвоения, чтобы задать новые слоты или переопределить существующие слоты. Используйте delete
, чтобы удалить слоты.
Тип данных состоит из произвольного числа уравнений (объекты типа "equal"
). Если a = b
среди этих уравнений, мы говорим, что slota
типа данных равняется b
. Условно, a
обычно является строкой. Каждая область имеет по крайней мере один слот, индексированный "key"
.
Имена типов данных, обеспеченных ядром MuPAD, имеют форму DOM_XXX
, такой нас DOM_ARRAY
, DOM_HFARRAY
, DOM_IDENT
, DOM_INT
, DOM_LIST
, DOM_TABLE
и т.д.
Можно создать дальнейшие типы данных с помощью функционального newDomain
(cf. Пример 1) или через область ключевого слова (cf. Пример 3.
Можно также создать новые типы данных путем вызова доменного конструктора. Различные предопределенные доменные конструкторы могут быть найдены в библиотеке Dom. Можно также задать собственных доменных конструкторов, использующих область ключевого слова. Cf. Пример 2.
Доменный тип (тип данных) любого объекта MuPAD может быть запрошен функциональным domtype
.
Только одна область с данным ключом может существовать. Если это хранится в двух переменных S
и T
, скажем, присваивающих, или удаляющих слот slot(S, a)
неявно также изменяет slot(T, a)
(ссылочный эффект). Это также содержит если a = "key"
.
Вы не получаете предупреждения, даже если T
защищен.