Одна вещь, которая пришла мне в голову на днях, это конкретные типы, которые все еще необходимы, или наследие, которое сдерживает нас. Я имею в виду следующее: действительно ли нам нужны short, int, long, bigint и т. Д. И т. Д.
Я понимаю причину, переменные / объекты хранятся в памяти, память должна быть выделена, и поэтому мы должны знать, насколько большой может быть переменная. Но на самом деле, не должен ли современный язык программирования обрабатывать «адаптивные типы», т. Е. Если что-то выделяется только в диапазоне сокращений, оно использует меньше байтов, а если что-то внезапно выделяется очень большое число, выделяется память в соответствии с этим конкретным случаем.
Float, real и double немного сложнее, так как тип зависит от того, какая точность вам нужна. Однако строки должны иметь возможность занимать меньше памяти во многих случаях (в .Net), где в основном используется ascii, но строки всегда занимают вдвое больше памяти из-за кодировки в юникоде.
Одним из аргументов для конкретных типов может быть то, что это часть спецификации, то есть, например, переменная не должна быть больше определенного значения, поэтому мы устанавливаем ее в shortint. Но почему бы вместо этого не иметь ограничения типа? Было бы гораздо более гибким и мощным иметь возможность устанавливать допустимые диапазоны и значения для переменных (и свойств).
Я осознаю огромную проблему в обновлении архитектуры типов, поскольку она настолько тесно интегрирована с базовым оборудованием, и такие вещи, как сериализация, могут стать действительно сложными. Но с точки зрения программирования это должно быть здорово, нет?
type hour is range 0 .. 23;
Ответы:
Я полностью верю, что это так. Семантические ограничения стоят больше, чем ограничения реализации. Беспокойство о размерах чего-то напоминает беспокойство о скорости чего-либо, когда появляется объектно-ориентированное программирование.
Он не заменил программирование, критичное к производительности. Это просто сделало не критичное к производительности программирование более продуктивным.
источник
Адаптивные типы означают логику для выполнения адаптации, означают работу во время выполнения для выполнения этой логики (для шаблонов и времени компиляции потребуется определенный тип, а вывод типа является особым случаем, когда вы получаете лучшее из двух миров). Эта дополнительная работа может быть полезна в средах, где производительность не критична, а система сохраняет разумные размеры. В других средах это не так (встроенные системы - одна, где вам иногда приходится использовать 32/64-битные целочисленные типы для производительности процессора и 8/16-битные целочисленные типы для оптимизации статического резервного копирования памяти).
Даже языки общего назначения, которые поддерживают позднюю привязку (разрешение типов во время выполнения, например, VB6), как правило, теперь способствуют строгой типизации (VB.NET) из-за снижения производительности, которое возникало при злоупотреблении поздней привязкой, и потому, что вы часто в конечном итоге получается некрасивый код, когда типы не являются явными ( Справочник / Профессиональный рефакторинг в Visual Basic - Даниэль Арсеновски ).
источник
Простота, память и скорость Когда я объявляю переменную, память для этой переменной выделяется в одном блоке. Чтобы поддерживать динамически растущую переменную, мне нужно добавить в эту переменную концепцию несмежной памяти (либо ту, либо зарезервировать самый большой блок, который может представлять переменная). Несмежная память снизит производительность при назначении / извлечении. Выделение как можно большего было бы расточительным в сценарии, где мне нужен только байт, но система резервирует долго.
Подумайте о компромиссах между массивом и вектором (или связанным списком). Для массива поиск определенной позиции - это простой вопрос получения начальной позиции и смещения указателя памяти на x пробелов, чтобы найти эту новую позицию в памяти. Представьте, что int - это бит [32], чтение которого включает в себя обход этого массива для получения всех значений битов.
Чтобы создать динамический тип числа, вы должны изменить его с массива битов на вектор битов. Чтение вашего динамического числа включает в себя переход к голове, получение этого бита, выяснение, где находится следующий бит в памяти, перемещение в это место, получение этого бита и т. Д. Для каждого бита в динамическом числе вы выполняете три операции чтения ( текущий), читать (адрес следующего), двигаться (следующий). Представьте себе чтение значений миллиона чисел. Это миллион дополнительных операций. Это может показаться незначительным. Но подумайте о системах (например, финансовых), где важна каждая миллисекунда.
Было принято решение, что возложение на разработчика ответственности за проверку размера и проверку является небольшим компромиссом по сравнению с влиянием на производительность системы.
источник
Определенные типы требуются для аппаратно-ориентированных языков и проектов. Одним из примеров являются протоколы сетевых подключений.
Но давайте создадим - для забавы - тип varint на языке, подобном C ++. Создайте его из
new
массива d.Нетрудно реализовать сложение: просто скомпонуйте байты вместе и проверьте старшие биты: если есть операция переноса,
new
в новом старшем байте и перенесите бит. Вычитание следует тривиально в представлении дополнения 2. (Это также известно как сумматор пульсации).Умножение следует аналогично; использовать итеративное добавление / сдвиг. Как всегда, настоящий поворот вашего хвоста - это деление [*].
Что вы потеряли, когда это произойдет?
Детерминированное время. У вас есть системный вызов (
new
), который может срабатывать в точках, которые не обязательно контролируются.Детерминированное пространство.
Полупрограммная математика идет медленно.
Если вам нужно использовать язык аппаратного уровня, а также работать на высоком (медленном) уровне и не хотите встраивать механизм сценариев, это
varint
имеет большой смысл. Это наверное где-то написано.[*] Cf аппаратные математические алгоритмы для более быстрых способов сделать это - обычно дело в параллельных операциях.
источник
Это хороший вопрос. Это объясняет, почему такой язык, как Python, не нуждается в «short, int, long, bigint и т. Д.»: Целые числа, ну, в общем, целые числа (в Python 3 есть единственный целочисленный тип), и не имеют предельного размера (за исключением память компьютера, конечно).
Что касается Unicode, кодировка UTF-8 (которая является частью Unicode) использует только один символ для символов ASCII, так что это не так уж плохо.
В целом, динамические языки, кажется, идут в том направлении, которое вы упоминаете. Однако из соображений эффективности в некоторых случаях полезны более ограниченные типы (например, программы, которые должны работать быстро). Я не вижу особых изменений в обозримом будущем, поскольку процессоры организуют данные в байтах (или в 2, 4, 8 и т. Д. Байтах).
источник
На основании теории языка вы правы. Типы должны основываться на наборе правовых состояний, доступных для этих преобразований преобразованиях и операциях, выполняемых в этих состояниях.
Однако это примерно то, что дает ООП-программирование в его типичной форме. На самом деле, в Java, вы фактически говорите о
BigInteger
иBigDecimal
классах, которые распределяют пространство на основе того , сколько требуется для хранения объекта. (Как отмечает FrustratedWithFormsDesigner, многие языки скриптового типа идут еще дальше по этому пути и даже не требуют объявления типа и будут хранить все, что вы им дадите.)Однако производительность по-прежнему актуальна, и поскольку переключение типов во время выполнения обходится дорого, а компиляторы не могут гарантировать максимальный размер переменной во время компиляции, у нас все еще есть переменные статического размера для простых типов во многих языках.
источник
int
или илиdouble
, и если это не так, они знают об этом, поэтому динамическое определение размера - это функция, за которую им не нужно платить.Это зависит от языка. Для языков более высокого уровня, таких как Python, Ruby, Erlang и т. Д., У вас есть только концепция целых и десятичных чисел.
Однако для определенного класса языков наличие этих типов очень важно. Когда вы пишете код для чтения и записи двоичных форматов, таких как PNG, JPeg и т. Д., Вам необходимо точно знать, сколько информации читается за раз. То же самое с написанием ядер операционной системы и драйверов устройств. Не все делают это, и на языках более высокого уровня они используют библиотеки C, чтобы выполнить детальную тяжелую работу.
В России
short
все еще есть место для более конкретных типов, но многие проблемы разработки не требуют такой точности.источник
Недавно я создал редактор лестничной логики и среду выполнения и решил ограничиться типами:
Я считаю, что это сделало его более интуитивным для пользователя. Это радикальное отклонение от большинства ПЛК, которые имеют весь «нормальный» диапазон типов, который вы видите на таком языке, как C.
источник
Языки программирования движутся в этом направлении. Возьмем строки, например. В старых языках вы должны объявлять размер строки, как
PIC X(42)
в COBOL,DIM A$(42)
в некоторых версиях BASIC или [VAR
]CHAR(42)
в SQL. В современных языках у вас есть только один динамически распределенныйstring
тип, и вам не нужно думать о размере.Целые числа разные, однако:
Посмотрите на Python. Используется для различения целых чисел машинного размера (
int
) и произвольного размера (long
). В 3.х прежний исчез (старыйlong
- новыйint
), и никто не пропустил его.Но есть еще специализированный тип для последовательностей 8-битных целых чисел в форме
bytes
иbytearray
. Почему бы не использоватьtuple
илиlist
целых чисел, соответственно? Правда,bytes
есть дополнительные строковые методы, которыхtuple
нет, но, безусловно, эффективность во многом с этим связана.На самом деле, нет. Подход «все с двойной точностью» очень распространен.
источник
unum64 += ring32a-ring32b
всегда будет давать правильное поведение, независимо от того, является ли целочисленный тип по умолчанию 16 битами или 64 [обратите внимание, что использование+=
является обязательным; выражение вродеunum64a = unum64b + (ring32a-ring32b);
должно быть отклонено как неоднозначное.]Я понимаю причину, переменные / объекты хранятся в памяти, память должна быть выделена, и поэтому мы должны знать, насколько большой может быть переменная. Но на самом деле, не должен ли современный язык программирования обрабатывать «адаптивные типы», т. Е. Если что-то выделяется только в диапазоне сокращений, оно использует меньше байтов, а если что-то внезапно выделяется очень большое число, выделяется память в соответствии с этим конкретным случаем.
Float, real и double немного сложнее, так как тип зависит от того, какая точность вам нужна. Однако строки должны иметь возможность занимать меньше памяти во многих случаях (в .Net), где в основном используется ascii, но строки всегда занимают вдвое больше памяти из-за кодировки в юникоде.
У Фортрана было что-то похожее (я не знаю, действительно ли это то, что вы имеете в виду, поскольку на самом деле я вижу два вопроса). Например, в F90 вверх вам не нужно явно определять размер шрифта , так сказать. Это хорошо, не только потому, что дает вам центральное место для определения типов данных, но и является портативным способом их определения. REAL * 4 не одинаков во всех реализациях на всех процессорах (и под процессором я имею в виду CPU + компилятор), не в общем.
selected_real_kind (p, r) возвращает значение типа реального типа данных с десятичной точностью, превышающей, по меньшей мере, p цифр, и диапазон показателей, превышающий, по меньшей мере, r.
Так вы идете, например;
(Я думаю, что это довольно очевидный пример).
До сих пор не знаю, правильно ли я понял ваш вопрос, и это то, что вы думаете.
источник