Поиск пустых значений в несуществующем массиве:
*NL arrpos('probe659', 0) *NL arrpos('$probe659', '')
вернёт позицию 0, т. е. первую позицию массива, хотя, по-хорошему, хотелось бы получать -1, то есть "не найдено".
Неактивен
Неинициализированные переменные и ячейки массивов, числовые и текстовые, имеют значения по умолчанию '' и 0 соответственно.
Если 0 не найден в массиве, то он будет найден сразу за последним элементом массива(в нулевой позиции, если массив пуст), то бишь в первой же неинициализированной ячейке.
При этом стоит учесть то обстоятельство, что массивы неразрывны и "пробелов" между элементами нет: массив располагает свои элементы в ячейках от 0 до N - 1, где N - количество всех существующих элементов массива.
по-хорошему, хотелось бы получать -1, то есть "не найдено"
Оба поведения корректны в своем контексте. Вопрос же заключается в том, какое предпочтительнее для авторов.
Существующий вариант выгоднее тем авторам(A), для которых нет различий между "присвоенным"(инициализированным) значением 0 и "пустым"(неинициализированным), использующим массивы в заранее определенном диапазоне индексов.
Вариант с поиском исключительно инициализированных значений удобнее тем авторам(B), у которых "полезными" считаются значения инициализированные, а "бесполезными" - неинициализированные, при этом длина массива варьируется.
Минус первого варианта для авторов A и B - им придется делать проверку на выход за границы массива при поиске нулевых значений.
Минус второго варианта для авторов A - для работы с массивами им придется инициализировать их нулями. Это противоречит правилу QSP, перенятому из Бэйсика: неинициализированный массив считается заполненным нулями. Придется вводить явное различие между инициализированным значением и неинициализированным(сейчас оно тоже есть, но неявное). С другой стороны, в Бэйсике массивы заранее объявленной длины, поэтому там контекст немного другой.
Отредактировано Nex (06.09.2011 22:56)
Неактивен
Проблем с тем, что содержимое массива внутри интервала автоматически заполняется (или считается заполненным) нулями, нет. Однако ситуация, когда результат поиска возвращает результат, лежащий по сути вне пределов массива (который задал автор), довольно необычна.
Вдогонку к первому примеру код
probe[0]=10 probe[1]=20 probe[2]=30 *NL ARRSIZE('probe') *NL ARRPOS('probe', 0)
вернёт размер массива, равный трём элементам, а позицию нуля — в четвёртом элементе.
Неактивен
Как раз в QSP-то, в отличие Бэйсика, размер массива и не задается!
Я писал об этом в предыдущем сообщении.
Массив считается теоретически бесконечным. Автор при использовании просто пользуется любыми ячейками массива на свое усмотрение.
Кстати, я был неправ насчет "пробелов" - они-таки инициализируются нулевыми значениями, начиная с нулевого индекса. Т.е. такой эксперимент:
probe[1]=20 probe[3]=30 ARRSIZE('probe')
выведет "4"!
Таким образом, весь интервал индексов, между последним инициализированным и нулевым(включительно), будет всегда заполнен как минимум "настоящими" нулями. Эта техника оказалась хитрее, чем я предполагал.
Но нулями он заполняется при присваивании. А как же удаление отдельных элементов через KILLVAR? Но KILLVAR тоже не оставляет пробелов! Как только из массива 1, 2, 3 мы удаляем 2, то получаем массив 1, 3 - два элемента на позициях 0 и 1 соответственно. "Хвост" массива сдвигается влево на 1, сохраняя массив неразрывным.
Раз целостность массивов сохраняется, то, пожалуй, стоит пересмотреть свои выводы.
Неактивен
Nex написал:
Как раз в QSP-то, в отличие Бэйсика, размер массива и не задается!
Я писал об этом в предыдущем сообщении.
Массив считается теоретически бесконечным. Автор при использовании просто пользуется любыми ячейками массива на свое усмотрение.
Ну так я говорю не про указание максимальной размерности массива, а про то, каким этот массив представляет себе автор.
Даже если он учитывает нюансы автоматического заполнения интервалов в массиве, то после выполнения такой конструкции:
probe[3]=30
то есть ручного заполнения четвёртого элемента массива (и первых трёх — в автоматическом режиме), он ожидает, что размер массива будет равен 4. Если же он потом заполнит первые три элемента ненулевыми значениями, размер будет всё также равен 4. Но если он после этого поищет в массиве (ВСЕ элементы которого он же заполнил ненулевыми значениями) значение "0" — QSP вернёт ему позицию несуществующего с точки зрения автора пятого элемента.
Неактивен
Пересмотрел выводы, отредактировал первое сообщение. Оба варианта имеют свои недостатки.
Хорошим решением, теоретически, был бы ввод необязательного параметра, определяющего предполагаемый размер массива. Если указан - ищем значение в указанных пределах по первому способу, если не указан - в существующих элементах массива по второму. Беда в том, что авторам такие тонкости будет очень трудно объяснить.
Неактивен
Nex написал:
Хорошим решением, теоретически, был бы ввод необязательного параметра, определяющего предполагаемый размер массива. Если указан - ищем значение в указанных пределах по первому способу, если не указан - в существующих элементах массива по второму. Беда в том, что авторам такие тонкости будет очень трудно объяснить.
Зачем так усложнять для автора? Не проще всё же в реализации самой функции (на уровне платформы) ввести проверку на размер массива? Например, если найденная позиция больше размера массива — значит, ничего не нашли.
Ведь если автор укажет, что
probe[4]=0 *NL ARRPOS('probe', 0)
то функция отрабатывает вполне корректно и возвращает "4".
Неактивен
Затем, что благодаря отсутствию явного задания длины массива, есть два способа их использования, я об этом писал выше.
Если автор использует массив самым простым способом - задав некую переменную(L), определяющую размер массива, то при заполнении произвольных ячеек внутри выбранного автором диапазона, размер полученного массива запросто может не совпасть с L. И вот тут-то, при поиске нулевых значений, в предложенном тобою варианте мы будем искать не по всей длине L, а лишь по отрезку заполненных элементов. Из-за этого придется явно инициализировать массив, о том, чем это плохо, я тоже писал. Перечитай.
Неактивен
Nex написал:
Затем, что благодаря отсутствию явного задания длины массива, есть два способа их использования, я об этом писал выше.
Если автор использует массив самым простым способом - задав некую переменную(L), определяющую размер массива, то при заполнении произвольных ячеек внутри выбранного автором диапазона, размер полученного массива запросто может не совпасть с L. И вот тут-то, при поиске нулевых значений, в предложенном тобою варианте мы будем искать не по всей длине L, а лишь по отрезку заполненных элементов. Из-за этого придется явно инициализировать массив, о том, чем это плохо, я тоже писал. Перечитай.
Перечитал. В своём описании порядка работы с массивами в QSP ты как-то всё усложнил, смешав как есть и как могло бы быть.
С точки зрения автора всё организовано просто (я не буду говорить про строковые индексы — они не влияют на суть):
Однако, несмотря на "свободную расширяемость" массива, в каждый конкретный момент времени он (массив) имеет вполне определённый фактический размер (который можно получить функцией ARRSIZE), и этот размер автору либо уже известен, либо он его может получить. Так вот, возвращать функцией поиска значение индекса массива, который лежит вне этого диапазона, — на мой взгляд некорректно.
Отсюда и предложение — на уровне платформы ограничить верхний предел обработки массива функцией ARRPOS его фактическим размером, то есть тем значением, которое можно получить функцией ARRSIZE.
Неактивен
Но нулями он заполняется при присваивании. А как же удаление отдельных элементов через KILLVAR? Но KILLVAR тоже не оставляет пробелов! Как только из массива 1, 2, 3 мы удаляем 2, то получаем массив 1, 3 - два элемента на позициях 0 и 1 соответственно. "Хвост" массива сдвигается влево на 1, сохраняя массив неразрывным.
Вот этот нюанс на самом деле напрягает. Грубо говоря, задавая конкретное значение элементу массива, я рассчитываю что оно таким и останется.
Например, я пишу:
probe[4]=10
а потом, поигравшись с killvar пытаюсь поработать с этим элементом, но там неожиданно оказывается другое значение. Пока у меня таких глюков не было, и теперь, зная как это работает, наверное не допущу такой ошибки, но мог бы.
PS Кстати, а если используется строковая индексация? Происходит смещение по индексам, или индекс сохраняется за элементом массива вне зависимости от того, где он находится?
Отредактировано WladySpb (08.09.2011 12:30)
Неактивен
WladySpb написал:
задавая конкретное значение элементу массива, я рассчитываю что оно таким и останется.
Например, я пишу:Код:
probe[4]=10а потом, поигравшись с killvar пытаюсь поработать с этим элементом, но там неожиданно оказывается другое значение. Пока у меня таких глюков не было, и теперь, зная как это работает, наверное не допущу такой ошибки, но мог бы.
Если ты рассчитываешь на неизменность порядка элементов массива, то не нужно удалять элементы — достаточно их просто очищать, вот и всё…
Неактивен
Строковая индексация:
A["a"]="aaa" A["b"]="bbb" A["c"]="ccc"
Имеем:
A[0]="aaa", A["a"]="aaa"
A[1]="bbb", A["b"]="bbb"
A[2]="ccc", A["c"]="ccc"
Далее,
KILLVAR "A", 1
Имеем:
A[0]="aaa", A["a"]="aaa"
A[1]="ccc", A["c"]="ccc"
Т.о., числовые индексы поменялись, но это для нас неважно, т.к. мы пользуемся строковыми.
Что интересно, KILLVAR не поддерживает строковые индексы. Недоработка. Приходится явно указывать соответствующий числовой индекс.
Неактивен
Nex написал:
Что интересно, KILLVAR не поддерживает строковые индексы. Недоработка. Приходится явно указывать соответствующий числовой индекс.
На эту "недоработку" я давно уже пытался обратить внимание.
Пока же для реализации удаления элемента по строковому ключу я пользуюсь такой функцией:
#УдалитьИзМассиваПоКлючу ! Параметры ! 1. 0 - Имя массива (тип: строка) ! 2. 1 - Строковый ключ удаляемого элемента (тип: строка) !---------- dynamic "$<<$ARGS[0]>>[$ARGS[0]] = '!@#$%^del^%$#@!'", $ARGS[1] killvar $ARGS[0], arrpos('$' + $ARGS[0], '!@#$%^del^%$#@!') !---------- --- УдалитьИзМассиваПоКлючу
Суть работы функции:
Неактивен
Переименовал тему "Поиск нуля в несуществующем массиве" в "Особенности работы с массивами в QSP".
Неактивен
Повторяю, есть два способа работы с массивами. Один из них опирается на "реальный размер массива", всегда известный через ARRSIZE, другой - на заданный автором диапазон.
Твое решение подходит только для тех, кто работает по первому способу.
На эту "недоработку" я давно уже пытался обратить внимание.
А кто помешал? Взял бы и обратил внимание, мое или Байта. На форумах ты об этом не писал.
Отредактировано Nex (08.09.2011 15:50)
Неактивен
Nex написал:
Повторяю, есть два способа работы с массивами. Один из них опирается на "реальный размер массива", всегда известный через ARRSIZE, другой - на заданный автором диапазон.
Твое решение подходит только для тех, кто работает по первому способу.
А можно привести код с примером работы по второму варианту (где автор задаёт диапазон), чтобы понимать, чем же это отличается от "реального размера массива"?
Неактивен
Nex написал:
См. тему "Как сделать?", последнюю страницу. Я там привел пример работы с двумерным массивом с размерностью, определенной автором(10x10).
Ладно, скопируем пример оттуда:
i = 0 :loop_i j = 0 :loop_j IF $карта[j+","+i] = "": *P " " ELSE *P $карта[j+","+i] END j = j + 1 IF j<10: JUMP 'loop_j' END *NL i= i + 1 IF i < 10: JUMP 'loop_i' END
и попробуем разобрать отличия в подходах применительно к изначально поднятой в данном топике теме.
Автор в своём коде использует массив "карта" со строковыми значениями элементов и индексов. При этом изначально массив никак не инициализируется — пустое значение, возвращаемое QSP при обращении к незаполненному явно автором элементу, вполне устраивает. Подразумевается, что в данном массиве хранится 100 элементов, хотя возвращаемое функцией ARRSIZE значение будет по мере заполнения массива (как значимыми, так и пустыми значениями) меняться от 0 до 100.
Да, это отличается от подхода, когда автор формирует некий список значений, и размер этого списка отражает в каком-то смысле "результат" работы. Например, формирование перечня предметов, которые игрок может увидеть в текущей локации.
Но влияют ли эти отличия в описанных подходах к работе с массивом на работу функции ARRPOS (с ограничением диапазона поиска реальным размером массива) или приведённой функции удаления элемента по строковому ключу?
Нет, не влияют.
Рассмотрим работу этих функций применительно к примеру Некса.
ARRPOS в случае поиска возвращает числовой (и только числовой!) индекс массива. В данном примере смысла от числового индекса нет никакого — автор адресует ячейки строковыми индексами, и соответствие строковых и числовых индексов может быть довольно хаотичным. Если же эта функция используется просто для определения наличия в таком массиве (с подразумеваемым размером в 100 элементов), то всё равно автору нужно сравнивать возвращаемую позицию со своим предполагаемым размером массива, поскольку при его полном заполнении функция вернёт позицию 101 элемента, что некорректно. Однако подобное применение функции ARRPOS скорее исключение из обычного применения. И именно для таких исключительных ситуаций можно в функцию ARRPOS добавить параметр, определяющий верхнюю границу поиска, — но никак не делать это основным методом.
Функция удаления элемента по строковому ключу прекрасно удалит элемент, сдвинув "коллекцию" элементов. Однако, поскольку используются строковые индексы, то на работу автора с этим массивом это никак не повлияет — остальные элементы сохранят свои значения. Особенности же подхода к работе с данным массивов просто делает использование данной функции ненужным — проще будет просто присвоить нужному элементу пустое значение.
Вот я и говорю, что ты, Некс, как-то всё усложняешь, уходя от своего любимого "общего" подхода.
Неактивен
Nex написал:
Извиняюсь, я имел в виду тот же пример, но с адресацией через формулу m[row*row_width + column]. Невнимательно посмотрел.
Различия минимальны.
Функция удаления элемента по строковому ключу здесь вообще не нужна — нет строкового ключа. И, по-прежнему, удалять конкретный элемент в рамках данного примера надобности нет — достаточно просто заполнить его пустым значением.
Применительно же к функции ARRPOS — ситуация выглядит аналогично описанной ранее: при поиске пустого элемента в данном массиве тоже придётся отслеживать, чтобы возвращаемый индекс не выходил за пределы ста элементов. Поэтому и в этой ситуации, которая всё также является скорее исключением, куда полезнее по умолчанию ограничивать диапазон поиска функции ARRPOS реальным значением массива (ARRSIZE), но при этом добавить дополнительный параметр — верхнюю границу диапазона.
Кстати, инициализация всех элементов данного массива производится одной строчкой: m[max_row * row_width + max_column] = 0
. После этого указывать какую-либо верхнюю границу диапазона вообще нет надобности — все 100 (в приведённом примере) элементов массива теперь реально существуют (ARRSIZE('m')=100) и заполнены пустыми значениями.
Неактивен
Olegus t.Gl. написал:
Функция удаления элемента по строковому ключу здесь вообще не нужна
Не знаю, при чем здесь вообще удаление. Я про удаление не говорил.
Olegus t.Gl. написал:
Применительно же к функции ARRPOS ... в этой ситуации... куда полезнее по умолчанию ограничивать диапазон поиска функции ARRPOS реальным значением массива (ARRSIZE), но при этом добавить дополнительный параметр — верхнюю границу диапазона.
Как раз об этом я и говорил. Приятно видеть, что пытаясь меня переспорить ты пришел в итоге к тому же выводу.
Olegus t.Gl. написал:
Кстати, инициализация всех элементов данного массива производится одной строчкой
Как будто я этого не знал. Одной или десятью, сути это не меняет: явная инициализация массива противоречит принятой практике использования языка QSP.
Неактивен
Nex написал:
Как раз об этом я и говорил. Приятно видеть, что пытаясь меня переспорить ты пришел в итоге к тому же выводу.
Ну так цель была не переспорить тебя, а достичь конкретно сформулированного и устраивающего всех решения, которое бы решило максимальный перечень проблем и которое можно было бы предложить разработчикам платформы для реализации. И кстати, фраза про добавление дополнительного параметра появилась у меня куда раньше, чем приведённая тобой цитата, и звучала так:
Olegus t.Gl. написал:
И именно для таких исключительных ситуаций можно в функцию ARRPOS добавить параметр, определяющий верхнюю границу поиска.
И в этот момент я как раз и имел в виду твоё предложение, поданное в довольно путаной манере:
Nex написал:
Хорошим решением, теоретически, был бы ввод необязательного параметра, определяющего предполагаемый размер массива. Если указан - ищем значение в указанных пределах по первому способу, если не указан - в существующих элементах массива по второму.
Особенно если учесть, что в своих объяснениях помимо "первого" и "второго" варианта различного использования массивов ты ещё вводишь понятия авторов "A" и "B", собирающихся использовать массивы каждый по-своему. Пиши яснее — и тогда на твои предложения можно будет сразу ссылаться.
Неактивен
Ну, ты понял наконец, о чем я говорил? Вот и славненько.
в своих объяснениях помимо "первого" и "второго" варианта различного использования массивов ты ещё вводишь понятия авторов "A" и "B", собирающихся использовать массивы каждый по-своему
Авторы "А" - используют один способ, авторы "B" - другой.
Отредактировано Nex (11.09.2011 19:50)
Неактивен
Nex написал:
Авторы "А" - используют один способ, авторы "B" - другой.
Если бы всё было действительно так, но:
Nex написал:
Минус первого варианта для авторов A и B - им придется …
Минус второго варианта для авторов A…
То есть в своих пояснениях ты допускаешь, что авторы обоих типов могут пользоваться обоими вариантами, что изрядно путает. Впрочем, это уже к делу не относится…
Мы пришли к определённому консенсусу — что действительно славненько.
Неактивен