Чем определяется тип данных информатика

Типы данных

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

Любая константа, переменная, выражение или функция относятся к некоторому типу. Тип данных определяет диапазон допустимых значений и операций, которые могут быть применены к этим значениям. Кроме того, тип данных задает формат представления объектов в памяти компьютера, ведь в конце концов любые данные будут представлены в виде последовательности двоичных цифр (нулей и единиц). Тип данных указывает, каким образом следует интерпретировать эту информацию. Тип любой величины может быть установлен при ее описании, а в некоторых языках может выводиться компилятором по ее виду (Fortran, Basic).

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

Классификация типов данных

Любые данные могут быть отнесены к одному из двух типов: простому (основному), форма представления которого определяется архитектурой ЭВМ, или сложному, конструируемому пользователем для решения конкретных задач. Данные простого типа — это символы, числа и т.п. элементы, дальнейшее дробление которых не имеет смысла. Из таких элементарных данных формируются структуры (сложные типы) данных.

Принято различать следующие типы данных:

Рассмотрим перечисленные типы данных подробнее.

Простые типы

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

Целочисленные типы данных делятся, в свою очередь, на знаковые и беззнаковые. Целочисленные со знаком могут принимать как положительные, так и отрицательные значения, а беззнаковые — только неотрицательные значения. Диапазон значений при этом определяется количеством разрядов, отводимых на представление конкретного типа в памяти компьютера (см. “Представление чисел”).

Символьный тип. Элемент этого типа хранит один символ. При этом могут использоваться различные кодировки, которые определяют, какому коду (двоичному числу) какой символ (знак) соответствует. К значениям этого типа могут применяться операции сравнения (в результате получается логическое значение). Символы считаются упорядоченными согласно своим кодам (номерам в кодовой таблице).

Логический тип. Данные этого типа имеют два значения: истина (true) и ложь (false). К ним могут применяться логические операции. Используется в условных выражениях, операторах ветвления и циклах. В некоторых языках, например С, является подтипом числового типа, при этом ложь = 0, истина = 1 (или истинным считается любое значение, отличное от нуля).

Перечислимый тип. Отражает самый прямолинейный способ описания простого типа — перечисление всех значений, относящихся к этому типу. Каждая константа такого типа получает свой порядковый номер, что позволяет реализовать ряд простых операций над этим типом, таких, как получить следующее по порядку значение данного типа.

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

Указатель (тип данных). Если описанные выше типы данных представляли какие-либо объекты реального мира, то указатели представляют объекты компьютерного мира, то есть являются исключительно компьютерными терминами. Переменная-указатель хранит адрес в памяти компьютера, указывающий на какую-либо информацию, как правило — на другую переменную.

Составные типы

Составные типы формируются на основе комбинаций простых типов.

Массив является индексированным набором элементов одного типа, простого или составного (см. “Операции с массивами”). Одномерный массив предназначен для компьютерной реализации такой структуры, как вектор, двухмерный массив — таблицы.

Строковый тип. Хранит строку символов. Вообще говоря, может рассматриваться как массив символов, но иногда рассматривается в качестве простого типа. Часто используется для хранения фамилий людей, названий предметов и т.п. К элементам этого типа может применяться операция конкатенации (сложения) строк. Обычно реализованы также операции сравнения над строками, в том числе операции “ ”, которые интерпретируются как сравнение строк согласно алфавитному порядку (алфавитом здесь является набор символов соответствующей кодовой таблицы). Во многих языках реализованы и специальные операции над строками: поиск заданного символа (подстроки), вставка символа, удаление символа, замена символа.

Запись. Наиболее общий метод получения составных типов из простых заключается в объединении элементов произвольных типов. Причем сами эти элементы могут быть, в свою очередь, составными. Так, человек описывается с помощью нескольких различных характеристик, таких, как имя, фамилия, дата рождения, пол, и т.д. Записью (в языке С — структурой) называется набор различных элементов (полей записи), хранимый как единое целое. При этом возможен доступ к отдельным полям записи. К полю записи применимы те же операции, что и к базовому типу, к которому это поле относится (тип каждого поля указывается при описании записи).

Последовательность. Данный тип можно рассматривать как массив бесконечного размера (память для него может выделяться в процессе выполнения программы по мере роста последовательности). Зачастую такой тип данных обладает лишь последовательным доступом к элементам. Под этим подразумевается, что последовательность просматривается от одного элемента строго к следующему, формируется же она путем добавления элементов в ее конец. В языке Pascal подобному типу соответствуют файловые типы данных.

Преимущества от использования типов данных

Типы данных защищают программы по крайней мере от следующих ошибок:

1. Некорректное присваивание. Пусть переменная объявлена как имеющая числовой тип. Тогда попытка присвоить ей символьное или какое-либо другое значение приведет к ошибке еще на этапе компиляции. Такого рода ошибки трудно отследить обычными средствами.

2. Некорректная операция. Типизация позволяет избежать попыток применения выражений вида “Hello world” + 1. Поскольку, как уже говорилось, все переменные в памяти хранятся как наборы битов, то при отсутствии типов подобная операция была выполнима (и могла дать результат вроде “Hello worle”!). С использованием типов такие ошибки отсекаются опять же на этапе компиляции.

3. Некорректная передача параметров в процедуры и функции (см. “Подпрограммы”). Если функция “синус” ожидает, что ей будет передан числовой аргумент, то передача ей в качестве параметра строки “Hello world” может иметь непредсказуемые последствия. При помощи контроля типов такие ошибки также отсекаются на этапе компиляции или приводят к ошибкам выполнения программы, если значения параметра вводятся с клавиатуры или файла.

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

Методические программы

При изучении данной темы самое главное — разделить следующие понятия:

данные — тип данных — абстрактная структура данных — структура данных

Типом данныхпеременной называют множество значений, которые может принимать эта переменная, и множество операций, которые применимы к этим значениям.

Абстрактная структура данных (см. “Структуры данных”) — это некоторая математическая модель данных (см. выше), включающая различные операции, определенные в рамках этой модели. Для реализации абстрактной структуры в том или ином языке программирования используются структуры, которые представляют собой набор переменных, возможно различных типов данных, объединенных определенным образом. При этом одна и та же абстрактная структура данных может быть реализована через различные структуры языка программирования. Например, такая абстрактная структура данных, как список, может быть реализована с использованием массива, файла или списка динамических переменных. Примеры различных структур данных, реализующих абстрактную структуру граф, приведены в статье “Табличные модели” 2.

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

Изучение особенностей представления целых чисел (а именно этот тип данных встречается в учебных задачах по программированию чаще всего) полезно проиллюстрировать следующим примером.

Пример. С помощью программы на языке Borland Pascal вычислим значение n! (факториал числа n). Версия языка в данном случае указана потому, что ею определяется количество разрядов, отводимых на переменные определенного типа. В данном случае на переменные типа integer отводится 16 бит, что определяет диапазон значений этого знакового типа от –32 768 до 32 767.

При запуске этой программы для n = 7, 8 и 10 мы получим 5040, –25 216 и 24 320 соответственно. Первое полученное значение является верным, второе (отрицательное) может натолкнуть программиста на мысль, что в результате арифметических действий произошел выход за границу диапазона значений типа, а вот третье число само по себе может показаться верным, хотя, конечно, это не так.

На этом примере можно показать, что правильный алгоритм решения задачи при неправильном выборе типов данных может привести к абсурдному результату. И при разработке программы одним из важных этапов является оценка возможных значений (в том числе промежуточных) используемых переменных и выбор подходящих типов данных.

Следует подчеркнуть, что для целого типа выход за диапазон значений не приводит к прерыванию работы процессора (компьютер выдает неверные результаты), а для вещественных чисел (переполнение порядка) — это аварийная ситуация (floating point error), которая не пройдет незамеченной.

Источник

Тип данных

Тип данных

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

Содержание

История

Ещё в 1960-х г.г. Р. Хиндли (Roger Hindley) исследовал типизацию в комбинаторной логике. Его проблемной областью была типизация в языках, основаных на теории лямбда-исчисления. Позднее, в конце 1960-х годов, тот же учёный исследовал полиморфные системы типов. Позже, в 1970-х годах, Робин Милнер предложил практическую реализацию расширенной системы полиморфной типизации для языка функционального программирования ML.

Определение

Тип (сорт) — относительно устойчивая и независимая совокупность элементов, которую можно выделить во всём рассматриваемом множестве (предметной области). [1]

Полиморфный тип — представление набора типов как единственного типа.

Математически тип может быть определён двумя способами:

Необходимость использования типов данных

Типы данных различаются начиная с нижних уровней системы. Так, например, даже в Ассемблере х86 различаются типы «целое число» и «вещественное число». Это объясняется тем, что для чисел рассматриваемых типов отводятся различные объёмы памяти, используются различные регистры микропроцессора, а для операций с ними применяются различные команды Ассемблера и различные ядра микропроцессора.

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

Практическое применение

Как правило, типы языков программирования не всегда строго соответствуют подобным математическим типам. Например, тип «целое число» большинства языков программирования не соответствует принятому в математике типу «целое число», так как в математике указанный тип не имеет ограничений ни сверху, ни снизу, а в языках программирования эти ограничения есть. Как правило, в языках и системах имеется множество целых типов, отличающихся допустимым диапазоном значений (определяемым объёмом занимаемой памяти). Стоит отметить, что в большинстве реализаций языков и систем выход за границу целого типа (переполнение) не приводит к исключительной ситуации.

Современные языки программирования (включая Ассемблер) поддерживают оба способа задания типа (см. Определение). Так, в С++ тип enum является примером задания типа через набор значений. Определение класса (если рассматривать класс как тип данных) фактически является определением предиката типа, причём возможна проверка предиката как на этапе компиляции (проверка соответствия типов), так и на этапе выполнения (полиморфизм очень тесно связано с полиморфными типами). Для базовых типов подобные предикаты заданы создателями языка изначально.

Языки без типов

Теоретически не может существовать языков, в которых отсутствуют типы (включая полиморфные). Это следует из того, что все языки основаны на машине Тьюринга или на лямбда-исчислении. И в том, и в другом случае необходимо оперировать как минимум одним типом данных — хранящимся на ленте (машина Тьюринга) или передаваемым и возвращаемым из функции (лямбда-исчисление). Ниже перечислены языки программирования по способу определения типов данных:

3) Языки с типом, определяемым пользователем. Также хорошо известны языки, в которых типы данных определяются автоматически, а не задаются пользователем. Каждой переменной, параметру, функции приписывается определённый тип данных. В этом случае для любого выражения возможность его выполнения и тип полученного значения могут быть определены без исполнения программы. Такой подход называют «статической типизацией». При этом правила обращения с переменными, выражениями и параметрами разных типов могут быть как очень строгими (С++), так и весьма либеральными (Си). Например, в классическом языке Си практически все типы данных совместимы — их можно применять совместно в любых выражениях, присваивать значение переменной одного типа переменной другого почти без ограничений. При таких операциях компилятор генерирует код, обеспечивающий преобразование типов, а логическая корректность такого преобразования остаётся на совести программиста. Подобные языки называют «языками со слабой типизацией». Противоположнось им — «языки с сильной типизацией», такие как Ада. В них каждая операция требует операндов строго заданных типов. Никакие автоматические преобразования типов не поддерживаются — их можно выполнить только явно, с помощью соответствующих функций и операций. Сильная типизация делает процесс программирования более сложным, но даёт в результате программы, содержащие заметно меньше труднообнаруживаемых ошибок.

На практике языки программирования поддерживают несколько моделей определения типов одновременно.

Базовые типы

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

Преимущества от использования типов данных

Классификация типов данных [2] [3]

Типы данных бывают следующие:

Процесс проверки и накладывания ограничений типов — контроля типов, может выполняться во время компилирования (статическая проверка) или во время выполнения (динамическая проверка).

Контроль типов также может быть строгим и слабым.

Источник

Элементарные типы и операции над ними. Часть I: типы данных, размер, ограничение.

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

Материал в первую очередь адресую тем кто только начал или хочет начать писать на Erlang-e. Но я постарался максимально полно охватить данный аспект языка и поэтому надеюсь, что написанное будет полезно и более продвинутой аудитории.

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

Вступление

Для начала хочу выразить огромную признательность участникам русскоязычной рассылке по Erlang-у в Google-е за поднятие кармы и возможности выложить на хабр данную статью.

В процессе изложения будут приводиться примеры из командной оболочки (шелла) Эрланга. Поэтому нужно усвоить простые принципы работы. Каждая команда в шелле разделяется запятыми. При это совершенно не важно, производится набор в одну строку или в несколько.

1> X=1, Y = 2,
1> Z = 3,
1> S=4.
4

Указателем завершения ввода и запуск на выполнение является точка. При этом шелл выведет на экран значение возвращаемое последней из команд. В примере выше возвращается значение переменной S. Значения всех инициированных переменных запоминается, а так как в Эрланге нельзя переопределить значение инициированной переменной, то попытка переопределения приведет к ошибке:

2> Z=2.
** exception error: no match of right hand side value 2

Поэтому если требуется в текущей сессии работы заставить шелл «забыть» значения переменных, то можно воспользоваться функцией f(). Вызванная без аргументов она удаляет все инициализированные переменные. Если в качестве аргумента указать имя переменной, то удалена будут только она (передать список переменных нельзя):

3> f(Z).
ok
4> X = 4.
** exception error: no match of right hand side value 4
5> f().
ok
6> X = 4. %все, что идет после знака процента является комментарием
4

Для выхода достаточно ввести halt(), или вызвать интерфейс пользовательских команд Crtl+G и ввести q (команда h выведет справку). При выводе цифровых данных в шелле они приводятся к десятичному виду.

Изложенный материал относится к последней, актуальной на данный момент, версии 5.6.5. Для кодирования строк используется ISO-8859-1 (Latin-1) кодировка. Соответственно и все численные коды символов берутся из этой кодировки. Первая половина (коды 0-127) кодировки соответствует кодам US-ASCII, поэтому проблем с латинским алфавитом не возникает.

Несмотря на заявление разработчиков о том, что во внутреннем представлении используется Latin-1 «снаружи» виртуальной машины это зачастую совершенно неочевидно. Это возникает оттого, что Эрланг передает и принимает символы в виде кодов. Если для терминала установлена локаль, то коды интерпретируются исходя из установленной кодовой страницы и если это возможно выводятся в виде печатных символов. Вот пример SSH сессии:
# setenv | grep LANG
LANG=
# erl
Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.6.5 (abort with ^G)
1> [255].
«\377»
2> halt().
# setenv LANG ru_RU.CP1251
# erl
Erlang (BEAM) emulator version 5.6.5 [source] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.6.5 (abort with ^G)
1> [255].
«я»

Причем совершенно не важно, что указано в переменной окружения LANG, главное что бы она была установлена.

1. Элементарные типы

В языке не очень много базовых типов. Это число (целое или с плавающей запятой), атом, двоичные данные, битовые строки, функции-объекты (аналогично JavaScript-у), идентификатор порта, идентификатор процесса (Erlang процесса, а не системного), кортеж, список. Существует ряд псевдотипов: запись, булев, строки. Любой тип данных (не обязательно элементарный) называется терм.

1.1 Число

Потребление памяти и ограничения. Целое занимает одно машинное слово, что для 32-ух и 64-х разрядных процессорах составляет 4 байта и 8 байт соответственно. Для больших целых 1…N машинных слов. Числа с плавающей точкой в зависимости от архитектуры занимают 4 и 3 машинных слова соответственно.

1.2 Список

Список (List) позволяют группировать данные в одну структуру. Список создается при помощи квадратных скобок, элементы списка разделяются запятыми. Элемент списка может быть любого типа. Первый элемент списка называется голова (head), а оставшаяся часть — хвост (tail).

Потребление памяти и ограничения. Каждый элемент списка занимает одно машинное слово (4 или 8 байт в зависимости от архитектуры) + размер хранимых в элементе данных. Таким образом на 32-ух разрядной архитектуре значение переменной List будет занимать (1 + 1) + (1 + 4) + (1 + 1) = 9 слов или 36 байт.

1.3 Строка

На самом деле в Эрланге нет строк (String). Это просто синтаксический сахар который позволяет в более удобной форме записывать список целых чисел. Каждый элемент этого списка представляет собой ASCII код соответствующего символа.

Потребление памяти и ограничения. Т.к. строка это список целых чисел, а каждый символ это один элемент списка, то на символ уходит 8 или 16 байт (2 машинных слова).

1.4 Атом

Атом (Atom) это просто литерал. Он не может быть связан с каким либо цифровым значением подобно константе в других языках. Значение возвращаемое атомом является самим атомом. Атом должен начинаться со строчной буквы и состоят из цифр, латинских букв, знака подчеркивания _ или собачки @. В этом случае его можно не заключать в одиночные кавычки. Если имеется другие символы, то нужно использовать одиночные кавычки для обрамления. Двойные кавычки для этого не подходят, т.к. в них заключают строки.

Например:
hello
phone_number
‘Monday’
‘phone number’

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

SequenceDescription
\bвозврат (backspace)
\dудалить (delete)
\eэскейп (escape)
\fпрогон страницы (form feed)
\новая строка (newline)
\rвозврат каретки (carriage return)
\sпробел (space)
\tгоризонтальная табуляция (tab)
\vвертикальная табуляция (vertical tab)
\XYZ, \YZ, \Zвосьмеричный код символа
\^a. \^z
\^A. \^Z
Ctrl + A … Ctrl + Z
\’одиночная кавычка
двойная кавычка
\\обратная косая черта

Имя незаковыченного атома не может быть зарезервированным словом. К таким словам относятся:
after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse query receive rem try when xor.

Потребление памяти и ограничения. Каждый объявленный атом является уникальным и его символьное представление хранится во внутренней структуре виртуальной машины которая называется таблица атомов. Атом занимает 4 или 8 байт (одно машинное слово) и является просто ссылкой на элемент таблицы атомов в котором содержится его символьное представление. Сборщик мусора (garbage-collection) не выполняет очистку таблицы атомов. Сама таблица так же занимает место в памяти. Допускается использовать атомы в 255 символов, в общей сложности допустимо использовать 1 048 576 атомов. Таким образом атом в 255 символов будет занимать 255 * 2 + 1 * N машинных слов, где N – количество упоминаний атома в программе.

1.5 Кортеж

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

Кортежи удобны тем, что позволяют не только включать в структуру конкретные данные, но и описывать их. Это, а так же фиксированность кортежа позволяют очень эффективно применять их в шаблонах. Будет хорошей практикой при создании кортежа в первый элемент записывать атом описывающий сущность кортежа. Если проводить аналогии с РСУБД, то список является таблицей, каждая строка таблицы это элемент списка, а кортеж находящийся в этом элемент – конкретная запись в соответствующем столбце.

Потребление памяти и ограничения. Кортеж занимает 2 машинных слова + размер необходимый для хранения непосредственно самих данных. К примеру, кортеж в строке 5 будет занимать (2 + 1) + (2 + 1) = 6 машинных слов или 24 байта на 32-ой архитектуре. Максимальное количество элементов в кортеже 67 108 863.

1.6 Запись

Запись (Record) на самом деле является еще одним примером синтаксического сахара и во внутреннем представлении хранится как кортеж. Запись на этапе компиляции преобразуется в кортеж, поэтому использовать записи напрямую в шелле невозможно. Но можно воспользоваться rd() функцией для объявления структуры записи (строка 1). Объявление записи всегда состоит из двух элементов. Первый элемент обязательно должен быть атом называемый имя записи. Второй всегда кортежем, возможно даже пустым, элементы которого являются парой имя_полязначение_поля, при этом имя поля должно быть атомом, а значение любым допустимым типом (в том числе и записью, строка 11).

Оператором создания кортежа на основании записи (строка 2) является решетка # после которой следует имя записи и кортеж со значениями полей, возможно даже и пустым, но ни когда с именами полей которые не объявлены в описание записи.

1> rd(person, ).
person
2> #person<>.
#person
3> #person.
#person

Преимущество записи перед кортежем в том, что работа с элементами осуществляется по имени поля (имя должно быть атомом и быть объявленным в описании записи, строка 1), а не по номеру позиции. Соответственно порядок присвоения не имеет значения, не нужно помнить, что у нас содержится в первом элементе имя, телефон или адрес. Можно изменить порядок следования полей, добавить новые поля. Кроме того возможно присвоение значения по умолчанию когда соответствующее поле не задано.

4> rd(person, ).
person
5> P = #person<>.
#person
6> J = #person.
#person
7> P#person.name.
«Smit»
8> J#person.name.
«Joi
9> W = J#person.
#person

Если же при создании записи (строка 4) значение по умолчанию не определено (поле phone), то его значение равно атому undefined. Получить доступ к значению переменной созданной с помощью записи можно используя синтаксис описанный в строках 7 и 8. Можно скопировать значение переменной в новую переменную (строка 9). При этом если значение ни каких полей не определено, то получается полная копия, если же определены, то в новой переменной соответствующие поля переопределяются. Все эти манипуляции ни как не затрагивают ни определение записи, ни значения полей в старой переменной.
Лично мне это очень напоминает описание и создание экземпляров класса, хотя еще раз подчеркну, что это всего лишь способ хранения в переменной кортежа.

10> rd(name, ).
name
11> rd(person, , phone>).
person
12> P = #person, phone=123>.
#person,
phone = 123>
13> First = (P#person.name)#name.first.
«Robert»

Пример выше иллюстрирует вложенные записи и синтаксис доступа к внутренним элементам.

1.7 Бинарные данные и битовые строки

И бинарный тип (Binaries) и битовые строки (Bit strings) позволяют работать с двоичным кодом напрямую. Отличие бинарного типа от битовой строки в том, что бинарные данные должны состоять только из целого количества байт, т.е. количество бит в них кратно восьми. Битовые же строки позволяют работать с данными на уровне бит, т.е. по сути бинарный тип это частный случай битовой строки количество разрядов в которой кратно восьми. Можно как создавать данные описав их структуру, так и использовать данный тип в шаблонах. Двоичные данные описываются такой структурой:

>

Отдельной элемент такой структуры называется сегмент. Сегменты описывают логическую структуру двоичных данных и могут состоят из произвольного числа битов/байтов. Это дает очень мощный и удобный инструмент при использовании в шаблонах (пример такого применения будет рассмотрен в третьей части).

1> >.
>
2> >.
>
3> >.
>
4> Var = 30.
30
5> >.
>

Что бы понять, почему в результате создания двоичных данных в строке 2 мы получили 144 (т.е. 10010000, ведь мы, надеюсь, еще не забыли, что шелл при выводе приводит все цифровые данные к десятичному виду), а не ожидаемые 400 нужно рассмотреть битовый синтаксис описания сегмента.

Полная форма описания сегмента состоит из значения (Value), размера (Size) и спецификатора ( TypeSpecifierList ). Причем размер и спецификатор являются необязательными и если не заданы принимают значения по умолчанию.

Значение (Value) в конструкторе может быть числом (целым или с плавающей точкой), битовой строкой или строкой, которая, как мы помним, является на самом деле списком целых чисел. Однако вместе с тем значение сегмента не может быть списком даже целых чисел, т.к. внутри конструктора строка является синтаксическим сахаром для посимвольного преобразования в целые числа, а не в список. Т.е. запись > является синтаксическим сахаром для >, а не >.
Внутри шаблонов значение может быть литералом или неопределенной переменной. Вложенные шаблоны недопускаются. В Value так же можно использовать выражения, но в этом случае сегмент должен быть заключен в круглые скобки (строка 5).

Размер (Size) определяет размер сегмента в юнитах (Unit, о них чуть ниже) и должен быть числом. Значение по умолчанию Size зависит от типа (Type, см. ниже) Value, но может быть и явно задано. Для целых это 8, чисел с плавающей точкой 64, бинарный соответствует количеству байт, битовые строки количеству разрядов. Полный размер сегмента в битах можно вычислить как Size * Unit.
При использовании в шаблонах величина Size должна быть явно заданной (строка 7) и может не задаваться только для последнего сегмента поскольку в него попадает остаток данных (сродни чтению строки со start символа и до конца строки без указания нужного length количества символов).

6> Bin = >.
>
7> > = Bin,
8> Z. %переменная размером в 3 разряда, её значение 110
>

9> >.
>
10> >.
>
11> >.
>

Использую битовый синтаксис одни и те же данные могут быть описаны по разному (строки 9 и 11 описывают одну и туже двухбайтовую структуру).

1.8 Ссылка

Ссылка (Reference) представляет собой терм создаваемый функцией make_ref/0 и может считать уникальным. Она может быть использовать для такой структуры данных как первичный ключ.

Потребление памяти и ограничения. На 32-ух разрядной архитектуре требуется 5 машинных слов на одну ссылку для текущей локальной ноды и 7 слов для удаленной. На 64-ой 4 и 6 слов соответственно. Кроме того ссылка связана с таблицей нод которая также потребляет оперативную память.

1.9 Булев

Булев тип (Boolean) является псевдо типом т.к. на самом деле это всего лишь два атома true и false.

1.10 Объект-функция

Поэтому входные аргументы должны быть того же типа, что объявленные в функции. После ключевого слова when и до -> можно включать выражение результатом которого является true либо false. Тело функции выполняется в случае если выражение возвращает true. Если в ходе всех проверок тело функции так и не было выполнено (т.е. функция ни чего не вернула), то генерируется ошибка (строка 12). Переменные внутри функции являются локальными.

Функции могут быть вложенными, при этом результатом возвращаемым внешней функцией будет внутренняя:

1.11 Идентификатор процесса

Идентификатор процесса (Pid) возвращают функции spawn/1,2,3,4, spawn_link/1,2,3,4 and spawn_opt/4 при создании Эрланг процесса. Удобным механизмом взаимодействия с процессом может быть обращение к нему по имени, а не через цифровой идентификатор. Поэтому в Эрланге есть возможность связывать с Pid-ом символическое имя и в дальнейшем посылать сообщения процессу используя его имя.

Потребление памяти и ограничения. На данный тип уходит 1 машинное слово для локальных и 5 для удаленных нод. Кроме того функция связана с таблицей нод которая так же занимает память.

1.12 Идентификатор порта

Идентификатор порта ( Port Identifier) возвращает функция open_port/2 при создании порта. Порт представляет собой базовый механизм взаимодействия между Эрланг процессами и внешним миром. Он предоставляет байт ориентированный интерфейс связи с внешним программами. Процесс создавший порт называется владелец порта или процессом присоединенным к порту. Все данные проходящие через порт так же проходят и через владельца порта. После завершения процесса сам порт и внешняя программа должны так же завершиться. Внешняя программа должна представлять собой другой процесс операционной системы который принимает и отправляет данные со стандартного входа и выхода. Любой Эрланг процесс может послать данные через порт, но только владелец порта может получить данные через него. Для идентификатора порта, как и для идентификатора процесса, может быть зарегистрировано символьное имя.

Потребление памяти и ограничения. На данный тип уходит 1 машинное слово для локальных и 5 для удаленных нод. Кроме того функция связана с таблицей нод и таблицей портов которые так же занимает память.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *