Comments 54
Ах perl какой же он древний что про него забыли.
А ведь все то вы написали в нем уже есть.
А ведь все то вы написали в нем уже есть.
+1
А откуда информация, что «кортеж — это структура времени компиляции»?
Сходу источник не смог нагуглить.
Сходу источник не смог нагуглить.
+3
Это следует, скажем так, из практики программирования и понимания того как все устроено изнутри. Не уверен что это гуглится… ну вот теперь будет гуглиться)
В книгах и статьях по тому или иному языку программирования обычно дается практическая сторона: делайте вот так — и вы получите вот такой результат, скорее разместите программу в аппсторе и заработаете $$$. Рассуждения о том, что является структурами времени компиляции или времени выполнения, там излишни. Просто говорится, что в кортеж, также как в структуру (struct) например не добавить новые элементы во время выполнения, а в список (list) — можно.
В книгах и статьях по тому или иному языку программирования обычно дается практическая сторона: делайте вот так — и вы получите вот такой результат, скорее разместите программу в аппсторе и заработаете $$$. Рассуждения о том, что является структурами времени компиляции или времени выполнения, там излишни. Просто говорится, что в кортеж, также как в структуру (struct) например не добавить новые элементы во время выполнения, а в список (list) — можно.
-1
В Haskell ни в список ни в кортеж не добавить элементов во время выполнения, но они от этого не становятся одним и тем же
+5
То, что в кортеж нельзя добавить новые элементы, не делает его структурой времени компиляции, а лишь неизменяемой структурой данных. Есть много языков, в которых ни один экземпляр любого типа нельзя изменить во время выполнения. Но это не повод называть тот же list структурой времени компиляции.
Допустим, у нас есть кортеж {x, y}, если его конкретное значение может быть всегда вычислено на этапе компиляции, то да, это структура времени компиляции. Но если какой-то внешний фактор, например пользовательский ввод, может повлиять на значение x или y, то это уже совсем не структура времени компиляции.
Допустим, у нас есть кортеж {x, y}, если его конкретное значение может быть всегда вычислено на этапе компиляции, то да, это структура времени компиляции. Но если какой-то внешний фактор, например пользовательский ввод, может повлиять на значение x или y, то это уже совсем не структура времени компиляции.
+4
По мне, кортеж — более глубокое понятие, чисто математическое. Например, в реляционной алгебре есть понятие кортежа, и оно по некоторым параметрам сходно — например, строка из БД — это кортеж — совокупность полей. Хотя здесь речь вообще о компиляции не идет, это чисто абстрактное понятие.
+2
Списки гомогенны, кортежи гетерогенны. Отсюда вся пляска с фиксацией размера кортежа и прочие вытекающие.
И да, мы можем добавлять элементы в кортеж, получая новый экземпляр с новым типом (смотреть гетерогенные списки)
И да, мы можем добавлять элементы в кортеж, получая новый экземпляр с новым типом (смотреть гетерогенные списки)
0
Т.е. получая новый кортеж.
Конечно, мне стоило отметить что речь идет в первую очередь о классических компилируемых языках. Чисто функциональные языки я не рассматривал, в них вообще всё по другому, и в первую очередь все данные иммутабельны.
Конечно, мне стоило отметить что речь идет в первую очередь о классических компилируемых языках. Чисто функциональные языки я не рассматривал, в них вообще всё по другому, и в первую очередь все данные иммутабельны.
0
UFO just landed and posted this here
Что наоборот?
0
UFO just landed and posted this here
Он все правильно сказал. Списки гомогенны, т.к. List<Integer> или List<String>. А вот кортежи гетерогенны, т.к. (Integer, String, Double). Вся суть в типах элементов.
+2
Вообще-то автор не Си обсуждает, а вообще…
Берём так любимый нами AppleScript и его списки:
set exampleList to {213.1, 6, «Julia, the actress», 8.5}
Обмен значений двух переменных:
set {a, b} to {b, a}
Это всегда был «списко-ориентированный» язык, и никакими кортежами тут мне голову не дурили.
Берём другой язык, списки значений в 1С:
Список.Добавить(1980, «Год рождения Васи»);
Берём так любимый нами AppleScript и его списки:
set exampleList to {213.1, 6, «Julia, the actress», 8.5}
Обмен значений двух переменных:
set {a, b} to {b, a}
Это всегда был «списко-ориентированный» язык, и никакими кортежами тут мне голову не дурили.
Берём другой язык, списки значений в 1С:
Список.Добавить(1980, «Год рождения Васи»);
0
Кортеж, на самом деле, может быть достаточно неудобен, потому что элементы в нём имеют неосмысленные имена вида «первый», «второй», «тот», «этот» и «ещё один». Чтобы было больше смысла, лучше пользоваться структурами с именованными полями. А если имеется в виду порядковая нумерация элементов — для этого есть массивы.
0
Несколько позабавило то, что рассмотрение кортежей идет в отрыве от тех языков, в которых они действительно используются, скажем так, широко… Haskell, Erlang тот же и т.п.
Ну и да… повеселило даже не про «времени компиляции», а «кортеж — это не тип данных» :-)
Ну и да… повеселило даже не про «времени компиляции», а «кортеж — это не тип данных» :-)
+2
Смотря что понимать под типом данных.
Я бы сказал, что кортежи свободно приводятся к типам данных, но все-же не являются полноценными типами. Например
— это что? Массив из трех целых? Структура из трех целых? Список (list)? Множество (set)? Что-то еще?
Я бы сказал, что кортежи свободно приводятся к типам данных, но все-же не являются полноценными типами. Например
{1, 2, 3}
— это что? Массив из трех целых? Структура из трех целых? Список (list)? Множество (set)? Что-то еще?
-2
— это что? Массив из трех целых? Структура из трех целых? Список (list)? Множество (set)? Что-то еще?
:-) Это, например, _кортеж_ {int, int, int}.
Ну и — на в скидку — к какому _типу данных_ «свободно приводится» какой-нибудь {string, int, boolean}?
0
К соответствующей структуре, разумеется.
0
А точнее — к соответствующим по типам полей структурам. Самих структур может быть бесконечно много, и все они по умолчанию не будут совместимы между собой (номинативная типизация).
0
Вот именно. А _кортеж_ {string, int, boolean} — от такой один единственный.
И тогда, нам остается выяснить, что именно вы подразумевали, говоря что «кортежи свободно приводятся к типам данных»?
Просто, даже ваше утверждение «к соответствующим по типам полей структурам» — оно, мягко говоря, не совсем корректное же. Каким образом вы на уровне _структур_ собираетесь различать {string, int, boolean} и {boolean, int, string}, например?
И тогда, нам остается выяснить, что именно вы подразумевали, говоря что «кортежи свободно приводятся к типам данных»?
Просто, даже ваше утверждение «к соответствующим по типам полей структурам» — оно, мягко говоря, не совсем корректное же. Каким образом вы на уровне _структур_ собираетесь различать {string, int, boolean} и {boolean, int, string}, например?
0
Я имею в виду примерно вот это:
struct Foo {
string str;
int i;
boolean b;
}
struct Bar {
string name;
int k;
boolean c;
}
Foo f;
Bar b;
f = b; // error
b = f; // error
f = {"hello", 10, true}; // ok
b = {"hello", 10, true}; // ok
{string, int, boolean} t1 = {"hello", 10, true}; // ok
{string, int, boolean} t2 = f; // ok
{string, int, boolean} t3 = b; // ok
0
Мне кажется, что пример — надуманный, потому что в первых двух структурах у вас именнованные поля (причём разными именами), а в коде — безымянные.
0
Пример вполне реальный. В структурах именованные поля, и дальше показано что даже если две структуры «структурно идентичны», они все равно несовместимы — то есть объект типа Foo нельзя присвоить объекту типа Bar, и наоборот. То есть первую часть (до кортежей) вы можете проверить практически на любом языке программирования.
Дальше показано, что поведение кортежей отличается от поведения структур — если два кортежа структурно идентичны, то их можно свободно присваивать между собой, и даже между объектами кортежа и структуры. Ближайший аналог подобного синтаксиса — Swift, возможно что-то сделают в C++17.
Дальше показано, что поведение кортежей отличается от поведения структур — если два кортежа структурно идентичны, то их можно свободно присваивать между собой, и даже между объектами кортежа и структуры. Ближайший аналог подобного синтаксиса — Swift, возможно что-то сделают в C++17.
0
Причём здесь структуры? Объявите сначала тип, потом создайте две структуры этого типа и присваивайте наздоровье. Структуры так и останутся «структурно идентичны». То что в языках есть проблемы вывода типов, это не проблемы структур. Даже более того, вы выносите какую-то непонятную сущность и гвоорите — вот она, да ничего подобного, просто компилятор приводит тип справа к типу слева, с таким же успехом можно причмокивая обсасыватть такой пример:
10 это, байт, а он, глядите-ка, присваивается дробным числам. От шайтан, что делается, да это ж кортеж одночленный. Тьфу!..
var
a: real;
begin
a := 10;
end;
10 это, байт, а он, глядите-ка, присваивается дробным числам. От шайтан, что делается, да это ж кортеж одночленный. Тьфу!..
-1
Объявите сначала тип, потом создайте две структуры этого типа и присваивайте наздоровье.
Так задача поставлена уже. Условия иные: у вас есть два типа, они одинаковы структурно, но они — разные сущности. И правил приведения типов для структур — нет. Можно считать, что кортеж — это структура с ограничениями, для которой определена операция приведения, в случае, если все поля — тех же типов и следуют в том же порядке.
+1
А я вижу всего лишь данные, как в комментарии выше, где написано число 10 и не вижу никаких отличий поведения от приведённого мной примера.
0
var
a: real;
b: byte;
begin
a := 10;
b := 10;
end;
Ну давайте теперь поговорим о том, что 10 это магическая сущность, которая может являться и целым и действительным одновременно и она вне типов.
Расширяем пример:
var
a: record
i1: real;
i2: real;
end;
b: record
i1: byte;
i2: byte;
end;
begin
a := (i1:10; i2:10);
b := (i1:10; i2:10);
end;
Можно долго с умным видом рассуждать о вездесущности и приводимости (i1:10; i2:10), но де факто это две совершенно самостоятельные строки без каких-либо взаимосвязей, так же и у вас, то что типы там совпали — это совершенно фиолетово, это не одна сущность «кортеж», это два разных набора данных, по случаю совпавших и приводятся они в каждом конкретном случае именно потмоу, что это данные и их тип определён в левой части, а не в самих данных.
Ещё раз повторяю не стоит плодить непонятные сущности там, где их нет.
0
А кстати, что такое «10»? Какого типа? byte, short, word, int, uint, long, float, double?
Иногда у чисел бывают модификаторы, например можно представить что «10i32» — это int32. А без модификаторов? Брать «тип по умолчанию» («int»), как в Си? А правильно ли это?
В действительности правильный подход к литеральным константам такой — они сами по себе на этапе построения синтаксического дерева не полностью типизированы. Типизация происходит позднее, когда выясняется, в каком выражении с какими типами операндов эта константа используется.
Хотя эти вопросы больше касаются дизайна компиляторов, но это не делает их мене интересными. И это открывает дополнительные возможности — такие как архитектурно правильная интеграция в язык программирования «длинной арифметики».
Иногда у чисел бывают модификаторы, например можно представить что «10i32» — это int32. А без модификаторов? Брать «тип по умолчанию» («int»), как в Си? А правильно ли это?
В действительности правильный подход к литеральным константам такой — они сами по себе на этапе построения синтаксического дерева не полностью типизированы. Типизация происходит позднее, когда выясняется, в каком выражении с какими типами операндов эта константа используется.
Хотя эти вопросы больше касаются дизайна компиляторов, но это не делает их мене интересными. И это открывает дополнительные возможности — такие как архитектурно правильная интеграция в язык программирования «длинной арифметики».
0
Даже не знаю как до вас достучаться. Не имеет никакого значения какого типа число 10, это была иллюстрация вот к этому примеру:
Вы обзываете {«hello», 10, true} кортежем, а раз там и там кортеж, то это по вашему одно и то же.
Я же вам наглядно уже не первый пост пытаюсь показать, что {«hello», 10, true} <> {«hello», 10, true}, это совершенно разные данные, то что они выглядят одинаково с точки зрения компилятора, да и логики языка, ни о чём не говорит. Поэтому не имеет значения насколько равны у вас исходные структуры, им присваиваются разные данные.
На этом предлагаю дисскуссию завершить, если вы и тут меня не поняли, то я не вижу смысла далее разъяснять.
f = {"hello", 10, true}; // ok
b = {"hello", 10, true}; // ok
Вы обзываете {«hello», 10, true} кортежем, а раз там и там кортеж, то это по вашему одно и то же.
Я же вам наглядно уже не первый пост пытаюсь показать, что {«hello», 10, true} <> {«hello», 10, true}, это совершенно разные данные, то что они выглядят одинаково с точки зрения компилятора, да и логики языка, ни о чём не говорит. Поэтому не имеет значения насколько равны у вас исходные структуры, им присваиваются разные данные.
На этом предлагаю дисскуссию завершить, если вы и тут меня не поняли, то я не вижу смысла далее разъяснять.
+1
Даже не знаю как до вас достучаться. Не имеет никакого значения какого типа число 10, это была иллюстрация вот к этому примеру:
Ключевое в примере выше — вот это:
Foo f;
Bar b;
f = b; // error
b = f; // error
Если вы этого не понимате — печально.
Я же вам наглядно уже не первый пост пытаюсь показать, что {«hello», 10, true} <> {«hello», 10, true}, это совершенно разные данные,
А {string. int, boolean} и {string. int, boolean} — один и тот же тип.
В отличие от
struct Foo {
string str;
int i;
boolean b;
}
struct Bar {
string name;
int k;
boolean c;
}
+1
это не одна сущность «кортеж», это два разных набора данных, по случаю совпавших и приводятся они в каждом конкретном случае именно потмоу, что это данные и их тип определён в левой части, а не в самих данных.
Нет, как раз новая сущность «кортеж» определяет то, что это одинаковые наборы данных. Правила приведения применяются в первую очередь для кортежа, а не его элементов. В итоге вы можете скопом передать, привести набор данных.
0
Спасибо… я, кажется, понял ваш ход мыслей.
Проблема, как мне кажется, в том, что следуя вашей логике можно начать утверждать что и «список», например, «не тип». Т.к. каждый конкретный _экземпляр_ списка, можно свести к _экземпляру_ массива, например.
А речь, таки, о _типах_. А вот в терминах типов, как раз можно смело утверждать что _любая_ структура, «свободно сводится» к соответствующему кортежу. Причем, хочешь — с сохранением «плюшек» номинативной типизации, хочешь — без. Но, выше вы упорно пишете что:
В принципе, «можно считать» как угодно. Ктож нам запретит :-) Вопрос только: какой в этом смысл?! С тем же успехом я могу утверждать что это структура — это кортеж специального вида. И я даже знаю язык в котором это действительно так :-)
Проблема, как мне кажется, в том, что следуя вашей логике можно начать утверждать что и «список», например, «не тип». Т.к. каждый конкретный _экземпляр_ списка, можно свести к _экземпляру_ массива, например.
А речь, таки, о _типах_. А вот в терминах типов, как раз можно смело утверждать что _любая_ структура, «свободно сводится» к соответствующему кортежу. Причем, хочешь — с сохранением «плюшек» номинативной типизации, хочешь — без. Но, выше вы упорно пишете что:
Можно считать, что кортеж — это структура с ограничениями, для которой определена операция приведения, в случае, если все поля — тех же типов и следуют в том же порядке.
В принципе, «можно считать» как угодно. Ктож нам запретит :-) Вопрос только: какой в этом смысл?! С тем же успехом я могу утверждать что это структура — это кортеж специального вида. И я даже знаю язык в котором это действительно так :-)
+1
Я вас тоже понял. Конечно, кортеж это тип с определенной точки зрения. И для конечного программиста удобнее рассматривать кортеж именно как тип, обладающий какими-то особенностями — по сравнению например со структурами, которые обладают другими особенностями.
Но я выбрал несколько другую точку зрения, более близкую к внутреннему устройству компилятора, и с этой точки зрения кортеж — скорее "полуфабрикат", заготовка для "полноценного" типа.
Так например, список аргументов функции — это тип? Обычно нет (сама сигнатура функции — тип, но не отдельно список аргументов). Но при этом вполне можно сказать что список аргументов функции — это кортеж. Ну или рассматривать список аргументов функции как самостоятельный тип, что в общем одно и то же.
Но я выбрал несколько другую точку зрения, более близкую к внутреннему устройству компилятора, и с этой точки зрения кортеж — скорее "полуфабрикат", заготовка для "полноценного" типа.
Так например, список аргументов функции — это тип? Обычно нет (сама сигнатура функции — тип, но не отдельно список аргументов). Но при этом вполне можно сказать что список аргументов функции — это кортеж. Ну или рассматривать список аргументов функции как самостоятельный тип, что в общем одно и то же.
-1
Но я выбрал несколько другую точку зрения, более близкую к внутреннему устройству компилятора, и с этой точки зрения кортеж — скорее «полуфабрикат», заготовка для «полноценного» типа.
Ну тогда можно как-то по подробнее про "внутреннее устройство компилятора"? И как быть в случаях когда этого самого "компилятора" вообще нет?! Следует ли это понимать так, что в этом случае типы отсутствую как таковые?
Вообще, ваше настойчевое противопоставление "типов компилятора", "типов определенной т.з" и "типов вообще" веселит меня гораздо больше, чем ваше упорство в попытке убедить общественность сначала в том, что "кортеж — не тип", а теперь, надо понимать, в том, что "кортеж — не настоящий тип". Я наверное таки возьму на себя смелость и поинтересуюсь у вас: "а что такое тип?". :-)
Так например, список аргументов функции — это тип? Обычно нет (сама сигнатура функции — тип, но не отдельно список аргументов). Но при этом вполне можно сказать что список аргументов функции — это кортеж.
Что значит "обычно нет"?! Это сильно зависит от определения функционального типа в данной конкретной системе типов. Если в СТ нет функционального типа, то у вас и "сама сигнатура функции" — не тип. Если есть, то все зависит от его определения. И это вполне может быть и не кортеж вообще. "Ф-ции одного аргумента достаточно для всего" (с) :-)
+1
Думаю лучше будет если я попробую подробнее разъяснить свою точку зрения в следующей части.
Здесь да, признаюсь это моя ошибка — я сделал утверждение, которое является скорее моей оригинальной идеей, а не чем-то общепринятым, да еще и не объяснил что это за идея и почему я так считаю. Обязательно это учту.
Здесь да, признаюсь это моя ошибка — я сделал утверждение, которое является скорее моей оригинальной идеей, а не чем-то общепринятым, да еще и не объяснил что это за идея и почему я так считаю. Обязательно это учту.
0
В принципе, «можно считать» как угодно. Ктож нам запретит :-) Вопрос только: какой в этом смысл?! С тем же успехом я могу утверждать что это структура — это кортеж специального вида. И я даже знаю язык в котором это действительно так :-)
Это было мое утверждение. Смысл очень простой: есть важное свойство — приводимость, которое позволяет считать, что у нас есть отдельный новый тип — кортеж. Под "можно считать" я имел в виду ближайшую аналогичную конструкцию, и указал это отличие, которое позволяет считать к. отдельным типом.
0
UFO just landed and posted this here
Point3D pt{10,20,30}; // новый синтаксис инициализации Point3D foo(Point3D a) { return {1, 2, 3}; // возвращаем "кортеж" } foo( {3,2,1} ); // передаем "кортеж"
Вот за это отдельное спасибо!
0
Вообще кортежи ИЗОМОРФНЫ(равнозначны) структурам.
Полностью.
Отличия следующие
1) Тип структуры вначале декларируется, потом используется. В то время как тип кортежа вычисляется на лету.
2) Кортеж — это структура с безыменным доступом до полей. Или же структура — это кортеж с именным доступом до полей.
3) Технологически построение кортежей и структур в языке может отличаться
Вообще странно, что вы не упомянули примером ни один функциональный язык, ибо кортежи/туплы в основном используются там. И оттуда перекочевали в Go и Rust
Полностью.
Отличия следующие
1) Тип структуры вначале декларируется, потом используется. В то время как тип кортежа вычисляется на лету.
2) Кортеж — это структура с безыменным доступом до полей. Или же структура — это кортеж с именным доступом до полей.
3) Технологически построение кортежей и структур в языке может отличаться
Вообще странно, что вы не упомянули примером ни один функциональный язык, ибо кортежи/туплы в основном используются там. И оттуда перекочевали в Go и Rust
+2
В Swift поля кортежа могут иметь имена.
И кстати, там интересные правила присваивания кортежей с именованными полями, о чем я не рассказал…
Кортеж с безымянными полями можно присвоить любому с именованными, и наоборот.
А если оба кортежа с именованными полями, то присваивание возможно только при совпадении имен полей.
Из того что я еще не рассмортел — Scala, а тоже стоило бы:)
И кстати, там интересные правила присваивания кортежей с именованными полями, о чем я не рассказал…
Кортеж с безымянными полями можно присвоить любому с именованными, и наоборот.
А если оба кортежа с именованными полями, то присваивание возможно только при совпадении имен полей.
Из того что я еще не рассмортел — Scala, а тоже стоило бы:)
0
Ну и «чтобы два раза не вставать» Бьерн Страуструп на днях (буквально вчера) предложил расширения C++ для работы с кортежами isocpp.org/blog/2016/02/a-bit-of-background-for-the-structures-bindings-proposal
+1
Из всей статьи я так и не понял, чем отличаются списки от кортежей.
Более того, автор говорит о языках программирования и его несёт в структуры данных SQL, при этом в процедурных языках данные и код это совершенно разные вещи. Либо давайте конкретно обсуждать языки ориентированные на данные типа HTML (не вижу смысла в контексте кортежей), либо уже плавно съезжайте на объектные которые хоть и имеют парадигмы, но де факто обращаются с данными так же как процедурные языки. К чему компиляция вообще не понятно, я уже приводил пример для расспространённых интерпретаторов языков, таких как AppleScript и 1С . В частности меня интересует объектно ориентированный язык AppleScript, который так же является списко-ориентированным, вот конструкция где на лету создаётся список из двух переменных и обмениваются значения этих переменных:
Ну а вот как создаётся именнованный список:
Я понимаю что такое список, но я так и не понял, что такое кортеж, кроме того, что он везде и — нигде.
Более того, автор говорит о языках программирования и его несёт в структуры данных SQL, при этом в процедурных языках данные и код это совершенно разные вещи. Либо давайте конкретно обсуждать языки ориентированные на данные типа HTML (не вижу смысла в контексте кортежей), либо уже плавно съезжайте на объектные которые хоть и имеют парадигмы, но де факто обращаются с данными так же как процедурные языки. К чему компиляция вообще не понятно, я уже приводил пример для расспространённых интерпретаторов языков, таких как AppleScript и 1С . В частности меня интересует объектно ориентированный язык AppleScript, который так же является списко-ориентированным, вот конструкция где на лету создаётся список из двух переменных и обмениваются значения этих переменных:
set {a, b} to {b, a}
Ну а вот как создаётся именнованный список:
set exampleList to {213.1, 6, «Julia, the actress», 8.5}
Я понимаю что такое список, но я так и не понял, что такое кортеж, кроме того, что он везде и — нигде.
0
Можно сказать, что кортежи это «почти что структуры» (struct).
Чем отличаются списки от структур, я надеюсь что понятно:)
Более интересный вопрос — чем отличаются кортежи от структур, там отличия более тонкие (хотя статья не посвящена именно этим отличиям).
Чем отличаются списки от структур, я надеюсь что понятно:)
Более интересный вопрос — чем отличаются кортежи от структур, там отличия более тонкие (хотя статья не посвящена именно этим отличиям).
0
На сколько я понимаю, единственное принципиальное отличие структуры от кортежа в том, что она умеет рекурсию.
0
Еще структуры как правило номинативно типизированы; то есть объявленная структура создает тип, по умолчанию несовместимый с другими типами, даже если структурно эти типы идентичны.
habrahabr.ru/post/276871/#comment_8769577
habrahabr.ru/post/276871/#comment_8769577
0
Боюсь вас расстроить, но структура, в классическом понимании, не является рекурсивным типом.
0
Sign up to leave a comment.
Кортежи в языках программирования. Часть 1