Срезы и контроль выхода за границы

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

// PascalABC.NET 3.1, сборка 1239 от 08.05.2016
function Proper(s:string):=s[1].ToUpper+s[2:];

begin
  ReadlnString('>').ToWords.Select(w->Proper(w)).Println
end.

Всего-то нужно было научиться писать слова так, чтобы первая буква была на верхнем регистре. Казалось бы, что может проще и естественнее, чем представить слово состоящим из первого и последующих (возможно, отсутствующих для предлогов) символов? Перекодируем первый символ и приписываем остальные. Использовать слайс [:2] напрашивается само собой. Но из-за неумения слайса возвращать пустую строку вместо исключения, работа с ним превращается в головную боль. Ведь надо предварительно проверять, существуют ли символы в границах, заданных в слайсе, а в этом случае проще вовсе без слайса обойтись, потому что для строк есть Сopy() и проще написать Copy(s,2,s.Length-1), чем делать эти проверки. Но тогда зачем такие слайсы, которые требуют предварительных плясок с бубном?

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

Ну когда мы обращаемся по индексу, мы же тоже проверяем, а не вышли ли мы за границы массива. В других языках со статической типизацией точно так же. Ну а чтобы не танцевать с бубнами, можно было бы ввести в язык оператор ?, который возвращал бы default(T), если вышли за границы массива/строки. s?[2],s?[2:] и т.д

Если Вы используете доступ по несуществующему индексу - это исключение. Слайс-не слайс - это выход за границы. Проверяйте это. Или используйте Copy(s,2,1000) - она гасит исключения.

Как обойти - это понятно. Но неудобно.

Расширим вопрос. Требование предварительной проверки существования объектов в границах слайса (о чем бы ни шла речь: о массивах, последовательностях, строках), фактически делает слайсы малополезной конструкцией, без которой легко обойтись. К примеру, в задаче разбиения последовательности на две по последнему отрицательному элементу вполне вероятны варианты, когда отрицательного элемента нет или он в последовательности последний и одна из подпоследовательностей будет пустой. Если мы предварительно будем определять местоположение точки разбиения в последовательности и рассматривать варианты, когда она есть, когда нет, когда она первая, когда она последняя, … это сведет на “нет” всю красоту и лаконизм функционального программирования. То же и о строке символов, например, о разбивании её на подстроки по последнему пробелу. А если там нет пробела? А если единственный пробел является первым символом строки? Последним символом? Если делать эти проверки, то по их результатам и слайсы не нужны - достаточно Copy. И вся эта мышиная возня из-за запрета пустых слайсов, которые возникают при обращении за пределы указанного в них диапазона. Достаточно ввести такое понятие (и разрешение) - и все сразу становится на места.

1 лайк

А для массивов слайсы с выходом за границу тоже должны работать? Или только для строк?

Если разрешить “пустой слайс”, то он будут работать для всего. То же и для случая выхода за границу: если определить, что “остальное пустое”, то для массива a[0…10] можем получить: из a[-5:1] -> a[0], из а[8:12] -> (a[8],a[9]), а[10:12] вернет пустую последовательность, а указав a[n:m] мы не должны думать о том, что будет, если m и/или n выйдут за отведенные границы. Ведь если написать a[m1:n1]+a[m2:n2]+a[m3:n3] и при этом предварительно требовать проверки каждой границы - извиняюсь, “нафиг нужно”! Почему у нас Copy() умеет давить исключение и ведет себя “разумно”: я возвращу Вам не то, что Вы попросили, а сколько у меня есть", почему в Бейсике есть два варианта подстроки Substr(строка, позиция, сколько) и Substr(строка, позиция) и второй вариант “умно” понимает, что “и до конца строки”, и слайс это умеет в виде [откуда:], но не умеет, если “откуда” вне строки?

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

1 лайк

Хорошо. Давайте зайдём с другой стороны.
Найдите мне пример нескриптового языка, где в слайсах не диагностировался бы выход за границы. Хотя бы один.

Вот например, язык D:

Исключение выхода за границы. И всё тут.

Итак, найдите.

Вот - таблица - есть где поискать: https://en.wikipedia.org/wiki/Comparison_of_programming_languages_(array)#Slicing

Ссылки про то что “мне неудобно” меня не очень убеждают - кому-то неудобно, что a[i] диагностирует выход за границу.

Хорошо, с таким же успехом можно спросить, а кому удобна такая диагностика? Кому удобно вместо красивой и компактной записи получать сообщения об исключениях? Может быть, проще не искать, что в каких языках как реализовано, а задуматься о конечной цели? Если она - обучение, то нужно количество исключений свести к минимуму. Для чего-то же ввели NaN вместо исключения по переполнению? Либо сделать исключение опциональным. Если она - подражание некоей концепции, принятой в каком-то языке (или группе языков) - вопросов нет.

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

Обучать тому, что исключения надо «гасить», точно не стоит. А то скоро будет как в ДжаваСкрипте:

И еще, обратите внимание, как незатейливо и “без головняка” работают срезы в Пайтоне. Да-да, те самые, “с выходом за границу”.

PascalABC.NET - не язык для обучения. Так он не позиционируется. Его можно использовать для обучения - без вопросов.

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

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

На ассоциативном уровне - если квадратные скобки, то выход за границы проверяется ВСЕГДА. Если же это функция, то может проверяться или нет.

По поводу других мнений - мы проводили семинар преподавателей на эту тему - около 10 человек - и все однозначно высказались, что если у слайса - выход за границы - это исключение.

Про NaN Вы сами ответили. Ещё раз - если в каком-то приличном стандарте или языке будут использоваться слайсы без контроля выхода за границы - я готов это обсуждать. Если НИ В ОДНОМ компилируемом языке такого нет - не готов.

Питон. Да - мы знаем Питон, анализировали слайсы в Питоне. Питон - интерпретируемый язык. Питон - динамический скриптовый язык. Это всё другие классы языков. Хотелось бы сравнивать крокодилов с крокодилами, а не с жирафами. Хотелось бы найти такое поведение в компилируемом языке со статическим контролем типов.

Не для обучения? А для чего? Вы всерьез рассчитываете, что он получит “промышленное применение” и все программисты мира бросятся на нем реализовывать свои коммерческие проекты хотя бы средней сложности? Какой процент реальных проектов сейчас создается на Delphi, FPS, PsacalABC.NET, даже вместе взятых? Вы надеетесь этот процент существенно увеличить? А ничего, что версии меняются чуть ли не каждую неделю и в последующей может перестать работать то, что работало до этого лишь потому, что “десять преподавателей единодушно высказались…”? Какой серьезный разработчик в таких условиях согласится брать подобную систему программирования в качестве инструментальной?

А вот для целей обучения - тут да, вы создали прекрасную систему. В разы, на мой взгляд, превосходящую то, что имеется в школах и младших курсах вузов для подобных целей. И эту нишу со временем вы можете занять почти всю. Но для этого язык должен иметь весомые преимущества перед другими. Уже сейчас Python во многом уступает вашей системе по универсальности. Желаете и дальше в чем-то проигрывать ему, в частности в срезах - ну что же, значит, так тому и быть…

И еще. О компилируемых и интерпретируемых языках. Наверно вряд ли кто-то станет опровергать утверждение, что Фортран-IV - компилируемый язык. Но вспомните: в нем есть такая “фишка”, как возможность задавать формат ввода данных во входном потоке, что никак нельзя скомпилировать. На IBM System /360 и /370 был компилируемый язык PL/1 с динамическими данными и все решалось путем наличия в память ЭВМ библиотеки поддержки. Если в языке реализовано позднее связывание, это ведь вовсе не означает, что язык обязан быть интерпретируемым. Если Pyhon и Ruby интерпретируемые языки, означет ли это, что их невозможно сделать компилируемыми. А быть может, это просто никому не нужно?. Хотя… не буду утверждать, потому что не специалист я по ним.

Ну, закритиковать нас легко - проблем нет.

Давайте забудем по 10 преподавателей - вижу, что Вам это не нравится.

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

К тому же язык программирования для обучения - это как правило очень простой язык - типа Кумира или Лого, специально проектировавшийся для обучения программированию. PascalABC.NET специально для этого не проектировался. То, что Вы его используете так - не делает его таким. Поэтому давайте договоримся о терминах. Язык для обучения - это язык, специально создававшийся для обучения, во многих местах существенно упрощённый и проч.

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

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

Еще раз - я считаю, что ваша задача наиболее чисто решается с помощью Copy - и слайсы тут - Вы правы - бесполезны.

По поводу “компилируемых” и “интерпретируемых” - давайте говорить проще - языки примерно одного класса. Всё-таки интуитивно даже Python - язык, относящийся к другому классу языков нежели PascalABC.NET. В нём существенно меньшее количество ошибок находится на этапе компиляции.

Это не критика была, а изложение точки зрения.

У каждого человека есть определенный кругозор. Когда этот кругозор сужается до бесконечности малого, то он обращается в точку. Тогда человек и говорит, что это есть его точка зрения. ―Давид Гильберт

Мне бы не хотелось думать, что язык программирования, предназначенный для обучения - это простой язык типа Лого или КУМир. Это языки не для обучения, они скорее просто некое надуманное введение в мир программирования. Из анекдота, когда прыгали в пустой бассейн: “А тренер сказал, что когда прыгать научимся правильно, тогда нам воды и нальют…”. Сначала учат один язык, потом переучиваются на другой. Кто-то “наверху” решил, видимо, что в школе слишком много часов отведено на программирование.

Когда я говорю о том, что PascalABC.NET прекрасно подходит для целей обучения, я имею в виду, что при всей строгости и академичности Паскаля, его достаточно строгой типизации, преподаватель может на нем иллюстрировать некие базовые подходы, заменяя элементы блок-схем операторами языка “один в один” и держаться в рамках языка, установленных Н.Виртом, но в то же время, там где это уместно, обращаться к элементам функционального программирования и ООП. Реализуется концепция одного единого языка, в котором есть все и каждый может брать оттуда лишь то, что ему необходимо.

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

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

Мне не сильно интересны научные (или околонаучные) мотивировки необходимости проверки границ лишь потому, что “все другие так делают”. Даже если вы называете это “эмоциями”. Я не математик, я по образованию “технарь”, т.е. инженер, который не может по определению довольствоваться фразой типа “А теперь осталось решить эту систему интегральных уравнений и мы получим искомый результат”. От нас всегда требовалось сказать, сколько и какого металла пойдет на изготовление вот этого моста и как именно мы будем эти железяки соединять. Посему мне хочется иметь слайсы, которые не будут меня беспокоить бесконечными проверками своих границ вместо того, чтобы делать то, что им предназначено делать. Независимо от “ассоциаций с []”. Ну не будет такого - значит, не судьба, обойдусь без них.

1 лайк