Должны ли структуры данных быть интегрированы в язык (как в Python) или предоставлены в стандартной библиотеке (как в Java)?

21

В Python и, скорее всего, во многих других языках программирования общие структуры данных можно найти как интегрированную часть основного языка со своим собственным выделенным синтаксисом. Если мы оставим в стороне синтаксис интегрированного списка LISP, я не смогу думать о других известных мне языках, которые предоставляют какую-то структуру данных над массивом как интегрированную часть их синтаксиса, хотя все они (но, я думаю, C) кажется, чтобы предоставить их в стандартной библиотеке.

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

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

Анто
источник
1
Мы исключаем объект и хэш-карту?
Orbling
3
@ Анто: У многих языков есть хеш-карты в виде ассоциативных массивов, Perl, PHP, JS (технически объект здесь) и т. Д.
Orbling
1
Возможно, вы могли бы более конкретно указать, о каких структурах данных вы думаете, кроме массивов, списков, хэш-карт / ассоциативных массивов?
FrustratedWithFormsDesigner
1
Включите хеш-карты, списки и все, что более продвинуто как «сложные структуры данных», и выбросьте массивы как слишком простые.
Anto
1
Я думаю, что более разумным заголовком было бы что-то вроде: «Какие структуры данных должны быть включены в язык и что в библиотеке?» Однако значимый ответ в значительной степени зависит от языка: чем чище библиотека интегрирована в язык, тем разумнее перемещать структуры в библиотеку.
Джерри Гроб

Ответы:

13

Это зависит от того, для чего предназначен язык.

Некоторые примеры (несколько украденные из других ответов):

  • Perl имеет специальный синтаксис для хеш-таблиц, массивов, строк. Perl часто используется для сценариев, они полезны для сценариев.
  • Matlab имеет специальный синтаксис для списков, матриц, структур. Matlab предназначен для матричной и векторной математики для инженерии.
  • Java / .NET поддерживает строки и массивы. Это языки общего назначения, где часто используются массивы и строки (все реже с использованием новых классов коллекций)
  • C / C ++ поддерживают массивы. Это языки, которые не скрывают от вас аппаратные средства. Строки поддерживаются частично (без конкатенации, используйте strcpy и т. Д.)

Я думаю, что это зависит от цели / духа / аудитории вашего языка; насколько абстрактно и как далеко от оборудования вы хотите, чтобы оно было. Обычно языки, которые поддерживают списки в качестве примитивов, позволяют создавать бесконечно длинные списки. Хотя на низком уровне, таком как C / C ++, их никогда не будет, потому что это не цель, дух этих языков.

Для меня сборщик мусора следует той же логике: заботится ли аудитория вашего языка о том, когда точно знать, когда и если память выделяется или освобождается? Если да, malloc / free; если нет, то сборка мусора.

earlNameless
источник
6
Это плохое место для использования термина «C / C ++», потому что наличие высокоуровневых типов шаблонов в C ++ является основным отличием между этими двумя языками.
2004 г.
Сбор мусора может быть сделан детерминированным способом, вам просто нужны линейные типы (или замена их беднякам: RAII).
Пион
@ EduardoLeón, хотя вы можете вызывать сборщик мусора в детерминированной точке, я не думаю, что как долго он будет работать, является детерминированным (по той же причине, что mallocи newв C / C ++ недетерминированы).
EarlNameless
@earlNameless: он детерминирован по отношению к использованию ресурса: линейные типы (или типы уникальности, которые похожи) делают ошибку типа (и, следовательно, ошибку компиляции) не освобождают ресурсы (по возможности, не фиксируются типом) системы, любого ненормального завершения программы), или использовать их после их удаления.
Пион
5

В Perl есть хеш-карты, а PL / SQL поддерживает записи, и у меня очень туманные воспоминания о том, что у matlab есть синтаксис для поддержки векторов и матриц всех разных измерений (хотя я могу ошибаться в этом, и могут быть аргументы, что это типы данных, а не данные структуры ) ... Я бы сказал, что иметь некоторую встроенную поддержку очень распространенных структур - это хорошо. Обычно кажется, что массивы и хэш-карты / ассоциативные массивы являются наиболее распространенными структурами с естественной поддержкой, и, вероятно, они также наиболее часто используются.

Не забывайте, что если вы добавите поддержку собственного синтаксиса для других структур, таких как бинарные деревья, эти структуры также будут реализованы средствами поддержки языка (компилятор / среда выполнения / и т. Д.). Сколько структур вы хотите создать поддержку?

Вам придется придумывать новые обозначения для менее часто поддерживаемых структур ... Keep It Simple !.

FrustratedWithFormsDesigner
источник
Нет необходимости изобретать буквальный синтаксис, например, для деревьев - они более редки, их даже нет в stdlib многих языков! По тому же аргументу можно было бы возразить против включения операторов, потому что «вам придётся придумывать новые обозначения для менее часто используемых операций».
@delnan: Я понял это с точки зрения разработки нового языка и интересуется, должна ли структура данных, кроме массивов, изначально поддерживаться (возможно) новым синтаксисом, или они должны поддерживаться включением библиотеки.
FrustratedWithFormsDesigner
В первом предложении явно говорится о «общих структурах данных», поэтому я предполагаю, что OP не настолько безумен, чтобы пытаться добавить специальный синтаксис для каждой непонятной структуры данных, когда-либо придуманной.
@delnan: ... а затем OP продолжает исключать списки и массивы LISP (в общем случае) "... оставив в стороне синтаксис интегрированного списка LISP, я не могу думать о каких-либо других известных мне языках, предоставляющих какие-то структура данных над массивом как неотъемлемая часть их синтаксиса "... поэтому я подумал, что они размышляли о структурах данных более экзотично, чем массивы / списки ...
FrustratedWithFormsDesigner
Да (я интерпретировал «над массивами» как «другие общие структуры данных»), но ничто в этом вопросе не намекает на «давайте сделаем литералы для каждой отдельной структуры данных, которую мы имеем». Хорошо заявить, что это должно быть ограничено разумным, но я не думаю, что мы можем сказать «плохая идея» только из-за этого предположения .
5

Мой любимый пример здесь - Lua . У Lua есть только один встроенный тип данных, « таблица », но его гибкость и скорость означают, что вы фактически используете их вместо обычных массивов, связанных списков, очередей, карт, и они даже являются основой для объектно-ориентированных возможностей Lua. (т.е. классы).

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

Дин Хардинг
источник
2
JavaScript-объекты действительно одинаковы - например, массивы - это просто объекты с числовыми свойствами и длиной.
Тихон Джелвис
1
Lua таблицы отличаются от объектов JavaScript: в JavaScript {}нет [], в Lua у вас есть {}для обоих. Lua таблицы лучше сравнивать со списками в Лиспе.
Якоб
Я предполагаю, что в JavaScript «все является объектом», включая массивы, но не все является массивом. В Lua все это стол.
Дин Хардинг
3

Вам не нужно иметь выделенный синтаксис для каждого типа данных высокого уровня. Например, допустимо иметь set([1, 2, 3])(как Python 2.x) вместо {1, 2, 3}.

Важно, чтобы иметь некоторый удобный способ построения структуры данных высокого уровня. Чего вы хотите избежать, так это код:

s = set()
s.add(1)
s.add(2)
s.add(3)

которая раздражает меня сильно , когда я использую std::vector, std::setи std::mapв C ++. К счастью, новый стандарт будет иметь std::initializer_list.

dan04
источник
3

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

  • Это дешево, чтобы добавить к языку. Это не будет стоить вам много из этого драгоценного бюджета сложности:
    • Грамматика в основном someBracket {expr ','} someBracketили someBracket {expr ':' expr ','} someBracket, с некоторыми мертвыми простыми дополнениями, если вам нужны такие вещи, как дополнительные запятые. В поплавок литералы могут легко быть больше в грамматике.
    • Во многих языках ни один из популярных литералов не конфликтует с существующим синтаксисом (исключение, которое я могу придумать, это язык с фигурными скобками в виде выражений, оператор запятой и отсутствие точки с запятой, как в {1, 2})
    • Семантика может быть определена менее чем в пяти предложениях, неофициальная версия такова: «Создайте новую коллекцию $, затем вызовите .add/ .append/ .setItemодин раз для заданных выражений с этим (этими) выражениями (ями) в качестве аргументов».
  • Из-за предыдущего третьего пункта это также очень легко реализовать.
  • Это очень удобно, когда вам это нужно, и не влияет (не нужно) на синтаксис других элементов, то есть вы не «платите» за него, когда не используете его.
комар
источник
3

Clojure - это шутка, но поддерживает

Lists: (x1 x2)
Vectors: [x1 x2]
Maps: {k1 v1 k2 v2}
Sets: #{x1 x2}
WuHoUnited
источник
2

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

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

ergodicsum
источник
2

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

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

Kamaal
источник
2

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

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

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

Единственная базовая структура, которая действительно нуждается в поддержке самой среды выполнения, по крайней мере на управляемом языке, - это массив: если вы не управляете памятью, вам будет трудно получить кучу смежных байтов. Любая другая структура может быть построена из массивов и указателей (или ссылок).

Andrea
источник
1

APL (и связанные с ним современные варианты, A +, J и K) имеют скаляр, вектор и матрицу в качестве первоклассных структур данных.

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

С. Лотт
источник
APL также имеет вложенные массивы, и массивы не обязательно должны иметь однородный тип данных, что делает их очень мощными структурами данных.
RFlack
1

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

Литералы списков и карт, а также удобный синтаксис замыкания являются важными характеристиками языков высокого уровня.

Разница между этим кодом Java:

Thing t = new Thing();
t.setFoo(3);
t.setBar(6.3);
t.setBaz(true);

и этот Groovy код:

t = new Thing(foo: 3, bar: 6.3, baz: true)

огромен Это разница между программой на 40000 строк и программой на 10000 строк. Синтаксис имеет значение.

Кевин Клайн
источник
В C # можно сделать: var t = new Thing(foo: 3, bar: 6.3, baz: true);- только 4 символа.
Работа
это на самом деле тот же номер; код Groovy должен читаться как 'def t = ...'
Кевин Клайн
1

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

  • упорядоченные последовательности (1-мерные): массив, очередь, стек, списки ...
  • упорядоченные многомерные структуры : таблица, вектор, матрица ..
  • карты : hashmap, словарь, множество, multimap ... (1-мерный)
  • многомерные карты : функции, карты карт ...
  • типы графов : деревья, ориентированные графы ...

Вы можете эмулировать любую структуру с любой другой структурой - это зависит только от того, насколько простой и понятный язык программирования позволяет это делать. Например:

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

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

Jakob
источник
1

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

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

  • Массивы фиксированной длины
  • наборы
  • HashMaps
  • Последовательности / списки
  • Записи / структуры / классы

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

В частности, такие вещи, как «красные / черные деревья», «приоритетные очереди» и т. Д., Имеют достаточно много возможных вариантов реализации, поэтому нецелесообразно запекать конкретную реализацию в основной язык. Лучше позволить людям выбрать наиболее подходящую реализацию для их ситуации. Примеры вариантов реализации, на которых я не хочу, чтобы разработчик языка ограничивал мой выбор:

  • Изменчивый или неизменный?
  • Позволяет нули или нет?
  • Синхронизировано или нет?
  • Поддерживается постоянное хранение или нет?
mikera
источник