Re[4]: C# 8 - фича №1
От: HrorH  
Дата: 03.12.19 14:32
Оценка: 8 (1) +1 :)
Здравствуйте, Kolesiki, Вы писали:

K>Самый тупой из всех возможных.

K>Индекс ПЕРВОГО элемента массива знают даже дети — 0. abc[0] — первый элемент. Сикарашка "^" нам говорит: а теперь мы считаем элементы с конца. И чтобы взять последний элемент... просто напиши abc[^0]! Это же логично!
K>Даже в плане употребления это намного правильнее. Никому не нужна "длина массива" — она неуклюжа как раз тем, что напрямую с массивом её нельзя использовать — её ВСЕГДА приходится вычитать. А понятие "индекс с конца" как раз и удобен тем, что видимый индекс и есть естественный индекс, как если бы мы считали от начала массива.


Why doesn't the new hat-operator index from the C# 8 array-slicing feature start at 0?
Объяснение не сильно понятное...Короче чтобы было удобнее код использующий машинное обучение переписывать с Питона на C#.
Re[4]: C# 8 - фича №1
От: Ночной Смотрящий Россия  
Дата: 03.12.19 14:49
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>Безусловно, все языковые идеи укладываются в две-три старых парадигмы времён мистера Беббиджа


Нет.

MD>Но паттерн-матчинг и деконструкция есть в таком куда более молодом языке как Swift (2014)


Она много где есть. Сифт не обладает ни самой старой, ни самой сложной, ни самой похожей на шарп реализацией.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[5]: C# 8 - фича №1
От: AlexRK  
Дата: 03.12.19 15:54
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>Логично, что последний элемент находится перед концом массива, а после или на конце ничего нет.


Тогда настолько же "логично", что первый элемент находится после начала массива, а перед или в начале ничего нет.
Re[3]: C# 8 - фича №1
От: Sharov Россия  
Дата: 03.12.19 18:57
Оценка:
Здравствуйте, Kolesiki, Вы писали:


K>Осмелюсь предположить, что MS-хипстота таки добралась до D и увидев, насколько мощно и логично выглядит "библиотека на диапазонах",


Скорее до питона.
Кодом людям нужно помогать!
Re[6]: C# 8 - фича №1
От: alexzzzz  
Дата: 03.12.19 22:50
Оценка: -1
Здравствуйте, AlexRK, Вы писали:

A>>Логично, что последний элемент находится перед концом массива, а после или на конце ничего нет.

ARK>Тогда настолько же "логично", что первый элемент находится после начала массива, а перед или в начале ничего нет.

Перед началом массива действительно ничего нет, а как только он начался, идёт первый элемент. А как только кончился, снова ничего не идёт.



Кто-нибудь пишет такие циклы:
for (int i = 0; i <= array.Length - 1; i++)
?
Отредактировано 03.12.2019 23:04 alexzzzz . Предыдущая версия .
Re[4]: C# 8 - фича №1
От: alexzzzz  
Дата: 03.12.19 23:57
Оценка: +1
Здравствуйте, Kolesiki, Вы писали:

A>>Нельзя автоматом — теряется половина смысла.

K>Тут согласен, но строго говоря, у меня вообще ни разу такого случая не было, чтобы "по ошибке" я лез переинициализировать целую структуру! Это довольно тупая ошибка и клянусь, если ЭТО для них проблема — вон из профессии! Это далеко не те вещи, о которых надо заботиться программисту.

Необязательно переинициализировать целую структуру. У структуры может быть десяток полей, достаточно в методе пытаться изменить одно и он не сможет быть readonly-методом.
1) У больших структур больше накладных расходов на защитное копирование.
2) Именно у больших структур больше полей, которые тоже могут быть структурами с несколькими уровнями вложенности. В результате затруднительно держать в голове все поля всех структур и помнить, какой метод что и как делает.
3) Именно большие структуры труднее сделать целиком иммутабельными в соответствии с правилами хорошего тона. Но если нельзя всю её объявить readonly, можно дописать readonly её свойствам/методами по-максимуму и поручить следить за этим машине. Её для этого сделали, автоматизировать тупую работу.
Re[7]: C# 8 - фича №1
От: AlexRK  
Дата: 04.12.19 06:10
Оценка: +1
Здравствуйте, alexzzzz, Вы писали:

A>Image: ranges.png


У меня другая картинка:

---------------------------------------------
индекс от начала массива |   0  1  2  3  4
---------------------------------------------
элементы массива         |   a  b  c  d  e
---------------------------------------------
индекс от конца массива  |   4  3  2  1  0
---------------------------------------------


Разверни массив — и получишь индекс с конца. Как иначе-то?

Если иначе — то это не индекс с конца, а что-то другое. А если что-то другое, но при этом визуально похоже на индекс — то это тупизна и костыль, увеличивающий когнитивную нагрузку на ровном месте.
Re[5]: C# 8 - фича №1
От: Kolesiki  
Дата: 04.12.19 06:38
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>Здравствуйте, Kolesiki, Вы писали:


K>>Индекс ПЕРВОГО элемента массива знают даже дети — 0. abc[0] — первый элемент. Сикарашка "^" нам говорит: а теперь мы считаем элементы с конца. И чтобы взять последний элемент... просто напиши abc[^0]! Это же логично!


A>Смотря, что ты считаешь концом массива. Логично, что последний элемент находится перед концом массива, а после или на конце ничего нет.


Вы рассуждаете о массиве как о некоей линейной вещи, которая лежит в адресном пространстве (чисто сипиписное мышление — на примитивах CPU). Я же смотрю на массив ТОЛЬКО как на некий ряд элементов в пустоте. Что ВНЕ массива — мне не интересно. Соотв. у меня нет "нечто за гранью последнего элемента". Есть последний элемент. Он, как и первый элемент, легко индексируется сосвоего конца логичным индексом 0.
Re[7]: C# 8 - фича №1
От: Kolesiki  
Дата: 04.12.19 06:47
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>Кто-нибудь пишет такие циклы:

A>
for (int i = 0; i <= array.Length - 1; i++)
?


Ваша ошибка кроется в том, что ЛОГИЧЕСКИ вы работаете с "массивом наоборот" (т.е. говоря в коде "я ставлю ^ и значит мы работаем с конца"), а ФИЗИЧЕСКИ эта "крышечка" реализована как array.Length, что в корне неверно! Потому что тогда последний элемент массива должен быть не "^1" (как они нам пытаются всучить), а "^-1"!! Т.е. "взять длину и вычесть один для попадания на последний элемент". ВОТ ГДЕ бестолковое понимание целей послужило кривой реализации.
А всё от того, что они увидели в Ди знак $ (который в ДИАПАЗОНАХ означает именно длину), но попытались превратить его в "логический реверс".
Я ж грю — безалаберное стадо макак может месяцами рассуждать о фичах и всё равно выбрать самый тупой вариант — вот почему так редко пишу им issues — бесполезно, как об стенку горох.
Re[8]: C# 8 - фича №1
От: Kolesiki  
Дата: 04.12.19 06:52
Оценка: +1
Здравствуйте, AlexRK, Вы писали:

ARK>Если иначе — то это не индекс с конца, а что-то другое. А если что-то другое, но при этом визуально похоже на индекс — то это тупизна и костыль, увеличивающий когнитивную нагрузку на ровном месте.


Вот! Специально подчеркнул ключевой момент. Т.е. a[0] — это индекс. А a[^0] — хрен знает что, построенное на индусячей арифметике и длине массива. Лучше б они вообще не брались за "индексы с конца" — не такая это частая задача, чтобы пихать это в язык. Не говоря о том, что квалификация "пихунов" оставляет желать лучшего.
Re[6]: C# 8 - фича №1
От: alexzzzz  
Дата: 04.12.19 07:00
Оценка:
Здравствуйте, Kolesiki, Вы писали:

..1 — один элемент в начале
^1.. — один элемент в конце

..4 — четыре элемента
^4.. — четыре элемента

..n — n первых
^n..- n последних

..^2 — от начала до конца, кроме последних двух

Всё логично и просто.
Re[7]: 0..^0
От: Qbit86 Кипр
Дата: 04.12.19 07:19
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>..^2 — от начала до конца, кроме последних двух


А 0..^0 — просто от начала и до конца.

A>Всё логично и просто.


Да. [inclusiveStart, exclusiveEnd), всё, как Дейкстра завещал.
Глаза у меня добрые, но рубашка — смирительная!
Re[7]: C# 8 - фича №1
От: AlexRK  
Дата: 04.12.19 07:25
Оценка:
Здравствуйте, alexzzzz, Вы писали:

A>Всё логично


a[1] — второй элемент с начала
a[^1] — первый элемент с конца

a[^4] — последний элемент с конца
a[4] — oops, out of bounds exception, надо a[3]

A>и просто.


А причем тут индексы элементов?
Re[8]: C# 8 - фича №1
От: alexzzzz  
Дата: 04.12.19 12:28
Оценка: 1 (1)
Здравствуйте, AlexRK, Вы писали:

ARK>a[^4] — последний элемент с конца

ARK>a[4] — oops, out of bounds exception, надо a[3]

?

ARK>А причем тут индексы элементов?


Диапазон состоит из пары индексов, которые определяют его начало и конец. Он ими задаётся.
Re[9]: C# 8 - фича №1
От: AlexRK  
Дата: 04.12.19 12:40
Оценка:
Здравствуйте, alexzzzz, Вы писали:

ARK>>a[^4] — последний элемент с конца

ARK>>a[4] — oops, out of bounds exception, надо a[3]

A>?


Здесь что-то не так?

ARK>>А причем тут индексы элементов?

A>Диапазон состоит из пары индексов, которые определяют его начало и конец. Он ими задаётся.

Почему-то слово "индекс" меняет смысл при смене точки отсчета с начала массива на конец. Создается впечатление, что словом "индекс" называют две разные вещи.
Re[10]: C# 8 - фича №1
От: alexzzzz  
Дата: 04.12.19 14:23
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>>>a[^4] — последний элемент с конца

ARK>>>a[4] — oops, out of bounds exception, надо a[3]
A>>?
ARK>Здесь что-то не так?

Я не понял, что значит "последний элемент с конца" и как это связано с ^4.

ARK>Почему-то слово "индекс" меняет смысл при смене точки отсчета с начала массива на конец. Создается впечатление, что словом "индекс" называют две разные вещи.


Индекс был равнозначен смещению относительно начала. Когда говорим "смещение", надо уточнить, относительно чего. Когда говорим "индекс", подразумевается, что от начала. Начало массива совпадает с началом его первого элемента, смещение нулевое. У элемента с индексом N смещение N относительно начала массива.

Так было всегда. Сейчас добавилась возможность изменить точку отсчёта, а числовые индексы как были по сути смещениями, так и остались.


Жирные полосочки — это индексы/смещения.

У float с индексом 2 начало смещено на 2 относительно начала массива. Это смещение в "единицах float". Если умножить на 4, будет 8 — смещение в "единицах byte" или индекс первого байта из этого float.

Float с индексом 7 — последний. У него смещение 7 в "единицах float" относительно начала массива или 1 относительно конца. Если эту 1 умножить на 4, будет смещение 4 в "единицах byte" относительно конца. 7*4 -> 28 и ^1*4 -> ^4 указывают на один и тот же байт, начальный байт последнего float.

Kolesiki может по привычке искать начало последнего элемента через length-1, если нравятся отрицательные числа, но оператор ^ позволяет записать это короче: ^1. Крышечка — это не сам конец массива, это унарный оператор такой, возвращающий значение типа Index, привязанное к концу.

Раньше существовала путаница между "индексами" (которые считаются с нуля) и "порядковыми номерами" (первый, второй, ...). Говоришь "пятый элемент" и непонятно, это индекс или порядковый номер. Сейчас к этому добавятся ещё индексы типа ^5, которые индексы в смысле "значения типа Index". Если продолжать всё считать от начала, то ничего не изменится; а считать от конца непривычно никому, надо привыкнуть. Но когда модель мира в голове подтверждается наблюдениями, то это проще, чем когда они противоречат.
Re[11]: C# 8 - фича №1
От: AlexRK  
Дата: 04.12.19 16:07
Оценка:
Здравствуйте, alexzzzz, Вы писали:

ARK>>>>a[^4] — последний элемент с конца

ARK>>>>a[4] — oops, out of bounds exception, надо a[3]
A>>>?
ARK>>Здесь что-то не так?
A>Я не понял, что значит "последний элемент с конца" и как это связано с ^4.

Ну, то и значит. Последний элемент с конца это последний элемент, если вести отсчет с конца. Я не знаю, как иначе объяснить.

A>Индекс был равнозначен смещению относительно начала. Когда говорим "смещение", надо уточнить, относительно чего. Когда говорим "индекс", подразумевается, что от начала. Начало массива совпадает с началом его первого элемента, смещение нулевое. У элемента с индексом N смещение N относительно начала массива.


Что такое "начало" и "конец"? Если "начало" — это "адрес первого элемента", а конец — это "адрес последнего элемента", то конец массива — это "Length — 1", он совпадает с адресом последнего элемента и смещение относительно конца должно быть тоже нулевое.

A>Так было всегда. Сейчас добавилась возможность изменить точку отсчёта, а числовые индексы как были по сути смещениями, так и остались.


Но "смещение относительно конца" сделали неправильное.

A>У float с индексом 2 начало смещено на 2 относительно начала массива. Это смещение в "единицах float". Если умножить на 4, будет 8 — смещение в "единицах byte" или индекс первого байта из этого float.


ОК.

A>Float с индексом 7 — последний. У него смещение 7 в "единицах float" относительно начала массива или 1 относительно конца.


У него смещение в "единицах float" относительно конца должно быть 0, а не 1.

A>Если эту 1 умножить на 4, будет смещение 4 в "единицах byte" относительно конца. 7*4 -> 28 и ^1*4 -> ^4 указывают на один и тот же байт, начальный байт последнего float.


Что за странная арифметика? Чему равно ^1 и ^4? Почему ^4 = 28?

A>Kolesiki может по привычке искать начало последнего элемента через length-1, если нравятся отрицательные числа, но оператор ^ позволяет записать это короче: ^1. Крышечка — это не сам конец массива, это унарный оператор такой, возвращающий значение типа Index, привязанное к концу.


Только оператор ^ — это не индекс, а какая-то странная сущность.
Re[12]: C# 8 - фича №1
От: alexzzzz  
Дата: 04.12.19 18:38
Оценка: 1 (1)
Здравствуйте, AlexRK, Вы писали:

ARK>>>>>a[^4] — последний элемент с конца

ARK>>>>>a[4] — oops, out of bounds exception, надо a[3]
A>>>>?
ARK>>>Здесь что-то не так?
A>>Я не понял, что значит "последний элемент с конца" и как это связано с ^4.

ARK>Ну, то и значит. Последний элемент с конца это последний элемент, если вести отсчет с конца. Я не знаю, как иначе объяснить.


Последний элемент с конца — это первый элемент (если я правильно понимаю в слова). Если ^4 — первый элемент, значит от конца коллекции до её начала надо сделать 4 шага, значит в ней 4 элемента: 0, 1, 2 и 3.

ARK>Что такое "начало" и "конец"?


Если в чистом виде, то абстракция — на картинке выше нарисованы жирными линиями. Если в практическом плане, то да, скорее адрес. Как и «элемент» — абстрактная сущность, а на практике последовательность байт.

ARK>Если "начало" — это "адрес первого элемента", а конец — это "адрес последнего элемента",


В этом месте проблема.

Начало массива ― адрес первого байта массива, совпадает с адресом первого байта первого элемента. Тут трудностей не возникает.

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

Так обычно и принято задавать диапазоны: начало ― адрес/индекс/указатель на первый элемент, конец ― адрес/индекс/указатель на нечто после последнего элемента. Inclusive start, exclusive end.

Ну или второй популярный вариант: адрес/индекс/указатель на начало последовательности и количество элементов. Всю жизнь в NET API использовали второй вариант. Но по сути это одно и то же, переводится друг в друга одной арифметической операцией: start + length = end или end — start = length. Вот даже формулки простые и логичные.

ARK>Только оператор ^ — это не индекс, а какая-то странная сущность.



Обычный унарный оператор, только новый применительно к целым числам.
Отредактировано 04.12.2019 18:44 alexzzzz . Предыдущая версия . Еще …
Отредактировано 04.12.2019 18:42 alexzzzz . Предыдущая версия .
Отредактировано 04.12.2019 18:40 alexzzzz . Предыдущая версия .
Отредактировано 04.12.2019 18:39 alexzzzz . Предыдущая версия .
Отредактировано 04.12.2019 18:38 alexzzzz . Предыдущая версия .
Re[13]: C# 8 - фича №1
От: AlexRK  
Дата: 04.12.19 19:42
Оценка:
Здравствуйте, alexzzzz, Вы писали:

ARK>>Ну, то и значит. Последний элемент с конца это последний элемент, если вести отсчет с конца. Я не знаю, как иначе объяснить.

A>Последний элемент с конца — это первый элемент (если я правильно понимаю в слова). Если ^4 — первый элемент, значит от конца коллекции до её начала надо сделать 4 шага, значит в ней 4 элемента: 0, 1, 2 и 3.

Эту логику я не понимаю.

Почему нельзя сказать "если ^4 — первый элемент, значит, от конца коллекции до её начала надо сделать 5 шагов, значит, в ней 5 элементов: 0, 1, 2, 3 и 4"?
Почему нельзя сказать "если ^4 — первый элемент, значит, от конца коллекции до её начала надо сделать 4 шага, значит, в ней 4 элемента: 1, 2, 3 и 4"?

Вопросы риторические, конечно. Ответ "патамушта так сделали". Но консистентности за этим не видно. И, судя по всему, не только мне.

A>Конец же массива не может указывать на данные внутри массива.


Но ведь начало массива указывает на данные внутри массива, почему же конец не может?

A>Это не адрес последнего элемента, потому что тогда данные элемента могут лежать за концом массива — глупость получается.


Смотря как трактовать термин "конец массива". Массив — это абстракция.

A>Единственный рациональный вариант, который работает для однобайтовых и многобайтовых элементов, считать концом массива адрес первого байта за пределами последнего элемента массива. Как бонус, конец последнего элемента совпадает с концом всего массива.


Не вижу, чем этот вариант рациональнее варианта "считать концом массива адрес последнего элемента". Как бонус, индексы с конца начинаются с 0, а не с 1.

A>Так обычно и принято задавать диапазоны: начало ― адрес/индекс/указатель на первый элемент, конец ― адрес/индекс/указатель на нечто после последнего элемента. Inclusive start, exclusive end.


Вот в этой встроенной асимметричности как раз и корень проблемы.

A>Ну или второй популярный вариант: адрес/индекс/указатель на начало последовательности и количество элементов. Всю жизнь в NET API использовали второй вариант. Но по сути это одно и то же, переводится друг в друга одной арифметической операцией: start + length = end или end — start = length. Вот даже формулки простые и логичные.


Угу, только вот первый элемент a[0], а последний a[^1]. Просто и логично.
Re[14]: C# 8 - фича №1
От: samius Япония http://sams-tricks.blogspot.com
Дата: 04.12.19 21:23
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, alexzzzz, Вы писали:


A>>Единственный рациональный вариант, который работает для однобайтовых и многобайтовых элементов, считать концом массива адрес первого байта за пределами последнего элемента массива. Как бонус, конец последнего элемента совпадает с концом всего массива.


ARK>Не вижу, чем этот вариант рациональнее варианта "считать концом массива адрес последнего элемента". Как бонус, индексы с конца начинаются с 0, а не с 1.


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