Pull to refresh

Comments 206

Вот с идеей статьи согласен, для своей области Lua идеален. Но где в статье хоть что то кроме воды?

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

Выглядит как чистой воды маркетинг.

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

Адекватные люди давно переписали свои приложения и библиотеки с Lua на другие языки. Пример: Torch->PyTorch.
Дальше додумывайте сами...

Torch это библиотека, каким боком это относится к обсуждаемому вопросу и как противоречит утверждению что lua встраевыемый скриптовый язык

Как пример. Lua встроен в Quik, самый распространенный в России биржевой терминал. Когда-то это был 32 разрядный Lua 5.1, с огромным количеством качественно сделанных библиотек на все случаи жизни и большим дружелюбным комьюнити.
Теперь Quik стал 64 разрядным, встроенный Lua тоже (v. 5.4). 64-разрядных библиотек мало, а те что есть сильно глючные. Исправлять и поддерживать желающих мало. Lua стал походить на латынь. Язык иногда очень полезный, но мертвый.

Lua примерно в 10 раз быстрее python, а LuaJit примерно в 100 раз быстрее.

Дальше додумывайте сами.

Это в сравнении с какой версией? А то ведь в Питон после 3.13 завезли свой "ускоренный в 10 раз JIT-компилятор".

Проверял на версии 3.11.

На каком примере? Обучения или инференса нейросетей, для чего существует pyTorch? Учитывая то, что python там -- просто обвязка и клей между компонентами, а вычисления неявно выносятся в numpy, blas, cuda у меня есть ряд объективных сомнений, что получится обогнать на сложном примере работы с векторами и матрицами.

Вы посмотрите эту обвязку. Так сотни и более операторов. каждый оператор это несколько строк байт-кода. Каждая строка байт-кода будет обрабатываться VM.

Каждый вызов функции это куча проверок. В скриптовых языках применяется динамическая типизация. Это куча проверок типа, выбор исполняющей функции.

Рекомендую посмотреть код питона или луа или VM любого другого скриптового языка.

В скриптовых языках применяется динамическая типизация

Боюсь, тут просто нет понимания, что такое numpy и pytorch и как они применяются. Рекомендую вникнуть глубже, разобраться, много ли выходит динамической типизации и характерных для Python структур данных в памяти при их использовании.

Могу лишь пример из практики привести: был у меня в старину процесс, который на mapreduce кластере на сотнях жирных нод считал всякую векторную арифметику на десятках TiB данных. Считал через numpy + blas.

В какой-то момент, я всё-таки решил проверить оптимальность такой конфигурации. Переписал на голом C (+blas) особо нагруженную часть. Ускорение по cpu time оказалось в пределах 15%. Выбросил этот C кусок и больше не вспоминал

numpy,torch,blas - это библиотеки. blas написан на фортране, torch написан на С. Для скриптовых языков сделаны лишь обертки.

В скрипт.языке любая команда - это функция. Т е сложение двух переменных не есть команда CPU, а есть функция, в которой читаются значения переменных, при этом динамически определяется их тип и потом вызывается опять же функция для исполнения операции сложения. При этом лишь jit компилятор что-то может оптимизировать. Компилятор скрипт.языка делает лишь байт код.

blas написан на фортране

в данном случае я подразумеваю не конкретную библиотеку, а blas-интерфейс к векторным инструкциям процессора, который реализует несколько разных библиотек вроде mkl.
хотя фортран в Python вполне встречается. взять хотябы популярную зависимость scipy -- там >17% кода на фортране, который транслируется в C с помощью f2c, компилируется и вызывается

Т е сложение двух переменных не есть команда CPU, а есть функция, в которой читаются значения переменных, при этом динамически определяется их тип и потом вызывается опять же функция для исполнения операции сложения.

вот я и говорю -- нет понимания, что такое numpy.

это не pure python библиотека. в numpy статическая типизация. и массивы со значениями, а не указателями на структуры объектов. и все операции с numpy типами никакую динамическую типизацию содержимого не проходят. только однократную самих numpy коллекций на стыке взаимодействия с python. 100 значений в массиве или 1000000 -- не важно. python структура данных объекта в памяти будет только одна -- самого массива, не его элементов

да и вычитать данные из внешнего источника можно сразу в numpy-массивы, мимо python списков, и выгрузить наружу.


и ведь это только начало бесчисленной горы трюков оптимизации в экосистеме python, на которой пострен примерно весь существующий ML. включая всё, что делает, к примеру, OpenAI.
"у каждого свой python"

Статья да и мои комментарии относятся к скриптовым языкам. Вы мне рассказываете про библиотеки. Эти библиотеки реализованы не на скриптовых языках. Они одинаково работают и в питоне и в луа и в С.

Я например использую torch и на луа и на питоне. Но torch в луа это Luajit.

И в этом есть преимущество луа перед питоном.

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

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

Вы посмотрите эту обвязку. Так сотни и более операторов. каждый оператор это несколько строк байт-кода. Каждая строка байт-кода будет обрабатываться VM.

И чем толще обрабатываемые данные, тем меньше это будет заметно.

Что и как там реально "завезли", посмотрим при выпуске какой-нибудь 3.18. Пока что говорить не о чем.

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

Назначение скриптового языка в том, чтобы вызвать библиотеку на C, замаскированную под функцию , которая и делает всю работу. Быстродействие Lua или Python реального значения не имеет.

Если бы. Скрипты содержат не только вызов С библиотек, но и описание алгоритмов, а также обращения к таблицам, векторам, стекам, структурам, потокам. И все это делает виртуальная машина данного языка. Вот она и определяет быстродействие приложения. Более того есть много библиотек написанных на скриптовом языке.

Какая жесть, зачем?

Хотя и бекенд люди на ноде пишут...

Очевидно Вы не в теме.

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

В отличии от питона, луа встраивается практически в любые микропроцессорные системы.

Питон отлично встраивается в микропроцессорные системы: https://micropython.org/

Надо ещё с PyPy сравнить.

Мне больше нравится язык Squirrel (Quirrel). Нормальная индексация массивов, синтаксис, похожий на C/Java/JavaScript.

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

Мне squirrel как язык тоже больше понравился, но его никто не разрабатывает и в нём остались серьёзные проблемы, например, глючные регексы. А ещё в Lua есть jit, что делает его заметно быстрее.

А классы чисто внутренние или можно из приложения притащить. То есть например: создаём класс в си, создаём массив объектов этого класса и с этим массивом работаем уже в скрипте?

там рефлексию человеческую до сих пор не завезли, поэтому через внешние генераторы типа swig или tolua++, которые из хедеров генерят обёртки - вполне.

Читал, что его используют Краники (Left 4 Dead 2, Portal 2). Как он там поживает, интересно…

А для меня например нормальная индексация массивов с 1. А Паскаль - лучший язык в мире после Forth.

Нормальная индексация массивов

есть что добавить к утверждению автора про спорную "нормальность" индексации с нуля, окромя вкусовщины?

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

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

А так - да, полностью изучается за вечер, есть на всех десктопах и на всех мобилках, разве что медленнее её только Python когда его не ускоряют.

хаха.. язык, который неправильно считает фибоначчи?)

Серьезно?

Абсолютно. В принципе, при влюблённости в Lua, можно сказать что ошибка не в самом языке а в библиотеке арифметики неограниченной точности, на что при отсутствии влюбленности скорее всего ответят - а мне а) плевать и б) может это язык на авторов библиотек так влияет что они лажают.

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

Т.е. реализацию вы писали не сами, а взяли готовую и вините в этом язык?

Откуда Вы взяли что я что-то писал? Стандартный пакет, причина в нём наверно, итог - результат расчёта ошибочен.

И винить в этом на нашем уровне, ибо очевидно - профессуры MIT здесь близко нету, следовательно никто не занимается собственно языком как математическим конструктом, нужно именно язык.

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

Пакеты с библиотеками забагованы и тупо и молча врут - виноват язык, хотя в том же самом принцмпе вероятно можно написать их и правильно. В другую сторону - то, что для Python очень много библиотек, достоинство чьё? Кого ни спросишь, скажет что языка Python, А не самом деле, если подумать - не вполне. Но это важно на таком уровне, где в интерпретации текстов, будь они хоть сто раз всего лишь комментарии, не ошибаются.

Язык не виноват, что вы не узнали о границах представления IEEE 754, которое используются в качестве чисел в Lua. Милионное число Фибоначчи намного больше предела возможностей double.

О чём Вы поёте с голоса нейронки? Какие IEEE 754. где Вы это слово краем уха уловили?

Узнайте же продвинутый факт, может на собесе пригодится. IEEE 754 - это про числа с плавающей точкой, а числа Фибоначчи - целые. Связи - никакой.

Для расчёта чисел Фибоначчи в Lua пишут что-то вроде

local bint = require 'bint'(40000)

https://www.lua.org/pil/2.3.html

Lua has no integer type, as it does not need it. There is a widespread misconception about floating-point arithmetic errors and some people fear that even a simple increment can go weird with floating-point numbers. The fact is that, when you use a double to represent an integer, there is no rounding error at all (unless the number is greater than 100,000,000,000,000). Specifically, a Lua number can represent any long integer without rounding problems. Moreover, most modern CPUs do floating-point arithmetic as fast as (or even faster than) integer arithmetic.

Постыдились бы, учитель. Импортировали какую-то мутную библиотеку и теперь брешете на весь язык из-за неё.

UPD: вы просто неправильно ею воспользовались

local bint = require 'bint'(40000)

Вы же знаете, что в скобочках указывается количество бит представления? Из 40000 бит можно получить чуть больше 12 тысяч десятичных разрядов, тогда как милионное число Фибоначчи для своего представления требует 209 тысяч разрядов.

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

UPD. Здесь нет никого кто бы занимался собственно языками. Были бы - да, из-за этого хаять Lua было бы нельзя, ибо язык - это одно, а компилятор, библиотеки, документация, инструментарий, сообщество - это другое, и к собственно языку относится только первое. Но на нашем (Хабра, страны если угодно) для любых практических целей важно только второе. Так что хаять не только можно, но и нужно.

Никакая библиотека не заменит прямоты рук и умения читать документацию.

Это уже оффтоп, но я выяснял простую и очень практическую вещь - чего ожидать по совокупности всех факторов. Понимая, что никто на практике углубляться в каждую частность не будет. Это наверно не так если под началом 300 человек и можно выделить спецкопателей…

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

За прямоту рук и чтение документации прятаться не получится, руки и глаза одни и те же. И Lua - единственный язык с которым случилась, по моим масштабам, катастрофа. А языки сработавшие так чисто да гладко что я аж удивился - Go, JavaScript, Julia и Racket. Последняя парочка - с учётом того что это не для создания приложений, конечно.

Я сам не знаю как к этому относиться, но получилось так.

Вы читали статью? Мне кажется, автор и пытался ответить на такие претензии. А вам совет - если ищите язык программирования, не берите чужие куски кода для сравнения, а читайте документацию и разбирайтесь, для чего язык был создан. Очень важно использовать язык по назначению.

Если бы выход за пределы возможностей был обнаружен, то было бы хорошо.

Ни один современный ЯП не выдаст вам warning в рантайме когда возникнет ситуация потери точности floating point-переменной, это глупо и бессмысленно, и поэтому Lua тут ничем не отличается от остальных языков.

Какое отношение

ситуация потери точности floating point-переменной

имеет к целым числам?

Ни один современный ЯП не выдаст вам warning

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

Какое отношение

ситуация потери точности floating point-переменной

имеет к целым числам?

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

Это подтверждает гипотезу что все, ещё раз - ВСЕ, современные языки - убогое гуано

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

может произойти

Происходит? Если подумать как работает библиотека чисел произвольной точности - это вряд ли.

Да и на иных языках иначе - нет ни инициализации ни проблем. Может произойти и не происходит - пробуйте ещё.

Ответ не верный

А какой тогда? Если неверный - то так и писали бы.

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

Происходит? Если подумать как работает библиотека чисел произвольной точности - это вряд ли.

Причем здесь "произвольной точности", если речь про идет про float/double переменные. С ними конечно происходит, если запихать туда что-то больше FLT_MAX/DBL_MAX. Точно так же, как это происходит в других языках для таких же переменных типа float/double.

Запустите подобный код на любом ЯП

 uint64 i = 0;
 double d = 0;

 while (i == d)
 {
     i += 1;
     d += 1;
 }

И обнаружьте, что примерно после 9007199254740992 значение во double-переменной теряет точность, не смотря на то, что там вообще нет дробной части.

А какой тогда?

Так я в комментарии выше и написал какой правильный.

ВСЕ, современные языки - убогое гуано

Простите, если пропустил ответ на этот вопрос (поискал выше, но не нашёл) - можете привести список хороших языков? Очевидно, там не будет современных, но из этого не следует, что все несовременные хороши.

Хороших - Хороших вопрос вкуса, а что получше - извольте.

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

  • Racket выжил, значит был лучшим из Лиспов, которые распознали сразу и немедленно стали убивать фрагментацией. Решает те же задачи что и все интерпретируемые языки, только лучше, и много чего ещё.

  • Julia сделана компетентными людьми для себя, то есть для компетентных людей, а их мало. Поэтому идёт ниже радара, вот и живая пока.

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

На пол лиги ниже

  • JavaScript достаточно быстр и достаточно выразителен, пришлось придумывать TypeScript чтобы народ не учился писать на таком JS какой он есть.

Дело не в возрасте, а в обстановке. Когда верх взяли bean counters а рынок стал массовым, следовательно глупым, это сказалось на развитии языков.

Спасибо. А можете пояснить по отношению к каждому языку из вашего списка (да хотя бы в общем, если по отношению к каждому много работы) - в чём именно их хорошесть? Как тупой перлист, я не очень понял, в чём конкретно плохость осуждаемых современных языков (увы, б.м., недостаточно внимательно читал). Вот Perl (пятый) плох? А PHP, который после выхода 7-й версии стал довольно шустрым? Java, Scala, Rust, Haskell?...

Go - это их провал.

Если это из "получше", то почему провал?

Когда верх взяли bean counters а рынок стал массовым, следовательно глупым, это сказалось на развитии языков.

Туплю и не понимаю. Можно это развернуть?

Мнение, конечно, личное.

хотя бы в общем

Как пример хорошести - Delphi. Делаем то, что делают все, делают потому что полнота по Тюрингу общая, но так, чтобы не нужно было слишком много писать дури ради компилятора и компилятор работал быстро. Добавляем идеи ООП, хороши они или плохи - отдельный вопрос, но добавляем их все и удобно. Имея ООП - делаем библиотеку под GUI. Всей грязи - неудобные begin и end, казалось что писать долго, зато глазами выхватывается хорошо. Ошибка - всё равно требуются костыли сопоставлять. В итоге - смотрится хорошо, работает быстро, интуитивно понятно ибо сделано не случайным образом, а из определённых общих соображений, то есть предсказуемо.

Как пример нехорошести - Perl. my $t0 = [gettimeofday];

my и $ - помогаем интерпретатору осознать факт существования переменной. Дважды. Ну, а [] можно выучить. Была конкретная задача - работа с текстом. Решили, потом приспособили HTML гнать. Работает - да. Что то же самое можно было сделать как DSL на Racket, попутно получив примерно порядок к производительности - ну не сделали, работает же.

То же PHP... увидел $ - досвидос, я свои мозги на помойке не находил. А кто менее touchy - нормально, пол Интернета на PHP. А с Интернетом - как в стандарте видишь MAY в ассортименте градаций - тоже досвидос, хоршо время полечило и с WebAssembly можно на 95% маразма забить.

Java - собрала всё худшее отовсюду, но лучше чем Win API, Котлин что, без серьёзных причин возник? Источник Java - политика, не самого высокого уровня.

Rust - это феномен. Компилятор туп и медлителен, некоторые вещи вопиют, например указать времена жизни в заголовке процедуры - это чисто безумие, параметры живут своё время вне процедуры, это против самой базовой идеи подпрограммы. По жизни, однако, не мешает. Cargo - далеко впереди CMake и прочего. Переписать на Rust - бодрое движение, людям нравится и получается неплохо. Плюс иллюзия - я выучу нечто странное и выделюсь, меня оценят. Как Java указывала на то, как ужасен Win32, так и Rust указывает на то, до чего погоня за фичами довела C++.

Haskell дальше описания не смотрел, в функциональное программирование уже могут все.

Можно это развернуть?

Такое, если с ходу не понятно, лучше не разворачивать.

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

Да с чего бы?

my $t0 = [gettimeofday];

Что тут плохого? Ну кроме названия переменной, за которое отвечает человек, а не язык.

Ну, а [] можно выучить.

В смысле выучить?.. Документация к Time::HiRes отчётливо говорит, что результат работы функции зависит от контекста:

"In array context returns a two-element array with the seconds and microseconds since the epoch. In scalar context returns floating seconds like Time::HiRes::time() (see below)."

Контекст списка (массива) можно задавать либо нотацией списка (круглые скобки), либо нотацией ссылки на список (квадратные скобки). Сравните:

 $ perl -MTime::HiRes="gettimeofday" \
> -E '@t0 = (gettimeofday); say join ", ", @t0;'
1743685617, 633295
 $ 
 $ perl -MTime::HiRes="gettimeofday" \
> -E '$t0 = [gettimeofday]; say join ", ", @$t0;'
1743685664, 166936
 $ 
 $ perl -MTime::HiRes="gettimeofday" \
> -E '$t0 = gettimeofday; say $t0;'
1743685746.70668

Всё соответствует документации, тут скорее надо запоминать (хотя зачем, всегда можно посмотреть), что функция ведёт себя по-разному в зависимости от контекста. А насчёт квадратных скобок, круглых, фигурных, сигилов - ну да, синтаксис и семантику языка до определённой степени желательно знать наизусть. Ну или не пользоваться им. И у Perl с этим всё довольно просто и логично - если разобраться, конечно.

my и $ - помогаем интерпретатору осознать факт существования переменной. Дважды.

Это совершенно не соответствует действительности.

Во-первых, переменные можно вводить и без модификаторов типа "my", если работать без режима "strict".

Во-вторых, помимо "my" есть ещё "our", "state", "local". И всё это не об объявлении переменной, а об объявлении особенностей поведения переменной - напр., области видимости

В третьих, "$" это не обозначение переменной, тут совершенно другой смысл, чем в PHP. Это обозначение типа создающейся переменной или, при использовании уже существующей - типа доступа к данным. "$var" - скалярный тип, "@var" - список (массив), "%var" - хэш-таблица. Есть ещё сигилы, и нюансы использования скалярных типов и специальных нотаций для создания ссылок на массивы (как это делается в приведённом вами примере) или хэш-таблицы, но не буду вдаваться.

Озвученные вами претензии конкретно к Perl исходят от незнания базового синтаксиса.

Что тут плохого?

Насилие над личностью. Ну не нужен нормальному человеку этот $.

В смысле выучить?

В смысле что [] в норме - индексация и уж точно не вызов функции.

Во-первых, переменные можно вводить и без модификаторов типа "my", если работать без режима "strict".

С режимом, без режима... Это медвежья услуга языку - вынос грязи на всеобщее обозрение.

"$var" - скалярный тип, "@var" - список (массив), "%var" - хэш-таблица.

Ага. Идея типа ставить ! в конце имени функции если она изменяет аргумент. Но тут грязи меньше - ! не обязателен, а изменяет или нет - точно бинарный признак неизменный на остаток вечности. А по первому символу - так и будем добавлять. Это казалось хорошей идеей, оказалось - отнюдь.

Озвученные вами претензии конкретно к Perl исходят от незнания базового синтаксиса

Вот за эту глупость спасибо. Я трачу карму на антропологические исследования, очень поверхностные, любительские но вдохновлённые работами старинного, в смысле не раскатанного политкорректностью, автора Lucien Lévy-Bruhl, на материале аудитории Хабра. Наличие сильного, до подавления логики, и скорее всего неотрефлексированного желания увидеть как кто-то в чём-то не разбирается - это обнаружилось недавно. Очень интересно...

Ни один современный ЯП не выдаст вам warning в рантайме когда возникнет ситуация потери точности floating point-переменной, это глупо и бессмысленно

Ну если слегка позанудствовать, то не так. Стандарт IEEE754 требует поддержки флага Inexact (всего там пять флагов). Те, кто стремится хотя бы сделать вид, что поддерживает его (как C, C++), исполняют операции нативно и умеют управлять этим флагом. Rust позволяет это же через C FFI. Возможно, ещё какие-то новые языки ввели поддержку. И это реально работает, по крайней мере на реализациях, что я тестировал на его предмет (Linux, FreeBSD). Совсем уж редко, но можно требовать мгновенной генерации исключения.

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

В Lua, так же как в Python, Java (рантайм), .NET (рантайм), этого не завезли. Поэтому про "ни один" у вас точно неверно. Но если вы не лезли на нижний уровень, то можете об этом и не знать.

there is no rounding error at all (unless the number is greater than 100,000,000,000,000)

Округление "целого" типа это всегда неожиданность. Привет JavaScript

Lua имеет определенную популярность, о чем тут спорить

Подозреваю что там упустили момент с индексацией массивов. В своё время на Lua делал лабы и курсовые по численным методам, всё ок было и даже преподавателю принимавшему работы понравился язык.

Можете считать что я и есть тот самый преподаватель. Теперь объясните как нужно упустить момент чтобы десятитысячное число считалось правильно, а миллионное - нет.

Ваш лучший выбор - ответ "не знаю", это садись - три. А нечнёте нести околесицу - будет садись два.

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

ровно та же проблема будет и на javascript, который представляет числа как Number, а под капотом вместо реализаций BigInterger лежит тупо double.
При этом я верю, что реализации с bigInteger можно найти на любом языке.

Так можно и плюсам/шарпам/джаве предъявить, что их реализация чисел фибоначчи не работает на простом Integer.

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

Чтобы считать числа Фибоначчи в JavaScript пишут типа

  let a = 0n
  let b = 1n

Кстати, откуда Вы взяли про "простой integer"? Знаете кого-то кто способен на глупость такого масштаба? Я ничено подобного не писал...

я думал, из контекста понятно, что "простой интеджер" - это с фиксированным числом разрядов (16, 32, 64), в отличие от упомянутого BigInteger, где разрядов можно заводить, пока память не кончится.

Вот пример, когда JavaScript молча делает ошибку:

console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992
console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992

Ошибку? По моему чётко доказано, что значение Number.MAX_SAFE_INTEGER - правильное.

а где ошибка?

вам известен смысл Number.MAX_SAFE_INTEGER ?

вы в своих вычислениях вышли за пределы в которых гарантируется точность, и что удивительного получить такой результат? вышли за пределы точности и получили не точный результат

ОНО ЖЕ ПРОКРИЧАЛО, что дальше больше не safe, но это Вас не остановило.

Где одно кричало? Если константу не использовать, то точно также переполнение дабла будет неожиданно

"Когда вы пересекали границу, вы видели красные флаги?" (ц)

Что в JavaScript нет целых, есть double, и для него это не ошибка - в документации описано явно и открыто и в интернетах на каждом углу. Точно так же как и то, что если его использование ограничить int32 или uint32, то будет вполне себе нормальное целое, не хуже, чем у остальных.

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

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

Использование в качестве стартовой позиции в массиве 1 имеет смысл, когда вы рассуждаете как человек. (...) Если я правильно помню, таково было соглашение в языке Pascal, который, на мой взгляд, заслуживает огромного уважения.

В языке Pascal диапазон индексов мог быть произвольным интервальным типом и указывался при объявлении массива: ... array [from .. to] of ... Но с «человеческой» точки зрения нумерация с единицы действительно удобнее, что нашло своё отражение, например, в классической математике.

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

А где в классической математике это нашло отражение?

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

Конкретно для самих массивов длины n объектов типа T, упрощая, денотация — это функция I → T, где I — индексное множество (например, фактор-группа ℤ/nℤ, или тип Fin n, смотря какой формализм вам приятнее). И чем больше структуры на индексном множестве, тем с ним приятнее работать. И, в частности, включение нейтрального элемента в это множество делает его группой, удобным типом, и так далее.

Натуральные числа в большинстве математических школ начинаются с нуля.

Ну это вообще говоря неверно. В математике не существует конвенции -- включать или не включать ноль в натуральные числа. Поэтому многими предлагается вообще не использовать их, а говорить: позитивные целые числа. Но логичнее всего было бы не включать, ибо натуральные числа используются для счёта объектов.

Wikipedia: Natural numbers

Wolfram: Natural Numbers

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

Дело не в конвенции, а в том, какие умолчания более часто распространены. И, опять же, личный опыт — умолчание «ноль включается» распространено больше, особенно в англоязычной литературе. В data N = Z | S Nу вас Z интерпретируется как ноль, в начальной алгебре [zero, suc] : 1 + N → N zero интерпретируется тоже как ноль, в произвольных топосах «треугольная часть» natural numbers object интерпретируется как ноль, и так далее.

Но логичнее всего было бы не включать, ибо натуральные числа используются для счёта объектов.

Они используются далеко не только для этого. Но, впрочем, чем «ноль объектов» плох?

Тем что, например, можно реализовать контейнер (массив) в виде энума из 3 вариантов. Пустой, содержит 1 элемент, содержит болле 1 элемента. Зачем такие извращения? Затем, что каждый вариант имеет свой АПИ. Из пустого контейнера ничего нельзя читать, а можно только мутировать/добавлять. Единичный контейнер это опшионал который в том числе можно трактовать и как массив, т.е. должен поддерживать оба АПИ, и только третий вариант по АПИ это привычный нам массив. Опять зачем все эти сложности? Затем, что имея паттерн матчинг вам на уровне языка будет запрещено использовать не валидное для данного состояния АПИ, ну например функция подсчёта среднего не сможет быть закодированна с ошибкой новичка когда сумма всех элементов делится на число элементов без проверки на ноль. Если сюда ещё и зав типы подсыпать то вообще можно статически во время компиляции гарантировать мемори сэйфти для всех случаев. А при чем тут 0? А при том что 0 в такой парадигме это не часть натуральных чисел, а нулл - маркер отсутствия числа, единица тоже спец маркер граничного случая, и только все остальные числа это числа.

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

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

А при чем тут 0? А при том что 0 в такой парадигме это не часть натуральных чисел, а нулл - маркер отсутствия числа, единица тоже спец маркер граничного случая, и только все остальные числа это числа.

Так я запутался, единицу в итоге тоже вычёркиваем из натуральных чисел?

А на самом деле всё проще:

Затем, что каждый вариант имеет свой АПИ. Из пустого контейнера ничего нельзя читать, а можно только мутировать/добавлять.

Тип функции для чтения

read : Fin n → Vec n a → a

гарантирует отсутствие чтений из пустого контейнера (и многое другое) без каких-либо крайних случаев.

Единичный контейнер это опшионал который в том числе можно трактовать и как массив, т.е. должен поддерживать оба АПИ

Оба — это какие?

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

(>>=) : Vec n a → (a → Vec m b) → Vec (n × m) b

или, если хочется максимальной точности,

(>>=) : {out-count : a → Nat}
      → (xs : Vec n a)
      → ((x : a) → Vec (out-count x) b)
      → Vec (sum (map out-count xs)) b

после чего предыдущий вариант сводится к этому при out-count ↦ const m. С таким >>= изоморфизм Maybe a ≅ Vec 1 a строится (и доказывается) тривиально.

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

Потому что групповая структура не у самих адресов, а у оффсетов/индексов, а адреса — это множество, на котором действует эта группа. Group action, все дела. И, кстати, для того, чтобы это действие было определённым, и чтобы вы не поехали кукухой в слоях изоморфизмов, в группе индексов должен быть обычный арифметический ноль.

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

А как у древних народов дела с понятием массивов?

Вопрос: а почему ноль/null не является маркером границы, а именно единица. И вот еще что: как это ноль не является натуральным числомчислом (я просто матешу забыл) — примитивный подсчет говорит: у Хорхе было два яблока, но хитрый Санчес его надул и теперь у Хорхе осталось ноль яблок. Как мы это покажем? Каким знаком? Нулл, ноль и в какой массив чисел запишем - натуральные, вещественные?…

Еще для определения рациональных чисел: Q = Z / N, где Z - целые, N - натуральные. С нулем не получится такой лаконичной записи.

Тоже верно. Нас в СПбГУ именно так и учили.

Если требуется уточнять, то:

  • ℕ₀ - если включает ноль.

  • ℕ⁺ - если не включает, минимальное равно 1.

Удвоение линии в ℕ - знак множества, в Unicode для таких базовых множеств есть свои символы.

Я эту нотацию помню ещё с конца 80-х эпизодически, а массово с 90-х.

UPD: ISO 80000-2 пошёл против этого, факт. Странное решение.

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

0 - это ноль герц, постоянная составляющая и заодно центр оси. Просто поскольку дискретное преобразование Фурье периодическое, вводить туда отрицательную координату необязательно. А вот в непрерывном преобразовании она уже есть, есть частота со знаком плюс, и есть та же самая частота со знаком минус. Контринтуитивно, да.

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

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

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

Если учитывать англоязычные, то в большинстве учебников (а также научных статей, и так далее) ноль таки включается.

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

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

Если учитывать англоязычные, то в большинстве учебников (а также научных статей, и так далее) ноль таки включается.

Хотелось бы, конечно, увидеть хотя бы один пример авторитетного учебника по математике, в котором определяется, что |N = {0, 1, 2, ...}

А то беру я, например, «Pre-Calculus»
и читаю на стр. 23:

... where n is a natural number (a positive integer, or counting number like 1, 2, 3, 4, etc.).

Или, к примеру, «Abstract Algebra: Theory and Applications», на с. 4:

N = {n : n is a natural number} = {1, 2, 3, . . .};

Не знаю, что для вас авторитетно, но:

  • прямо сейчас читаемая мной Bird'овская Algebra of Programming

    включает ноль

  • Riehl в своей Category Theory in Context

    включает ноль

    (кстати, обратите внимание — нумерация последовательности с нуля), и в других местах ссылается на множество натуральных чисел как на моноид (по сложению), что требует нуля.

  • Goldblatt в Topoi тоже включает ноль, например, на с. 29:

    Continuing even further we can consider the infinite collection
    ω ={0, 1,2, 3 , . . . }
    of all natural numbers [...]

    и в других местах предполагает, что ноль входит в натуральные числа.

  • Формулировка упражнения 8 на с. 21 в Маклейне

    включает ноль

  • Jacobs в Categorical Logic and Type Theory в поясняющем примере во введении предполагает ноль натуральным числом:

    one can distinguish between zero as a natural number 0:N and zero as a real number 0:IR

  • Верещагин-Шень в «Лекциях по математической логике и теории алгоритмов» пишут (том 1, с. 7):

    [...] где N — множество натуральных чисел {0, 1, 2, . . .}.

    Там же:

    Отметим кстати ещё два расхождения: в школе натуральные числа начинаются с единицы, а в некоторых книжках — с нуля (мы тоже будем называть нуль натуральным числом).

  • Успенский-Верещагин-Шень в «Колмогоровской сложности и алгоритмической случайности» тоже предполагают, что 0 — натуральное число (следует из изложения, нет сходу кратких цитат).

  • Flori в A First Course in Quantum Topos Theory говорит (с. 37):

    Examples of monoids are (N, +, 0) [...]

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

  • Aluffi в Algebra: Chapter 0 пишет

    N: the set of natural numbers (that is, nonnegative integers)

    что включает ноль.

Продолжать, или хватит?

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

Спасибо за многочисленные примеры. Из них, вообще говоря, можно предположить, что включение нуля в множество натуральных чисел является признаком профессиональной деформации дискретных математиков и программистов. Для их задач удобнее оперировать множеством (|N U 0), а вводить для него новое обозначение они почему-то не хотят, проявляя упорство Королевы из «Двенадцати месяцев».

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

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

Правда, непонятно, причём тут какие-то деформации.

Ну вот кстати. Если брать нормальные университетсткие учебники, а не "Algebra of Programming", то многие нуль не включают.

Там было упомянуто ещё восемь книг. Никакие из них не являются нормальными университетскими учебниками, по-вашему?

Кстати, что вместо Bird'а посоветуете? Меня раздражает, что там в упражнениях есть существенные ошибки — например, особенно впечатлило предложение с дающимся там уровнем теорката доказать, что категория функторов A^B имеет экспоненциалы, если A декартово замкнута. Это перебор, ибо известное мне по более категориальным текстам построение требует ко-Йонеду и enriched category theory, а в предлагающихся автором решениях ответ очевидно неправильный. Тем не менее, более хорошего текста, связывающего «абстрактный нонсенс» и вполне себе живое программирование, я не видел.

Курс Алгебры, Винберг. По моему мнению в числе лучших учебников.

Как дела с прочими упомянутыми мной в предыдущем комментарии книгами?

Курс Алгебры, Винберг.

Общего у него с обсуждаемой книгой только «Алгебра» в названии. Это вообще про другое.

По моему мнению в числе лучших учебников.

Для абстрактной алгебры в смысле этого Винберга Алюффи ИМХО получше.

а вводить для него новое обозначение они почему-то не хотят, проявляя упорство Королевы из «Двенадцати месяцев».

Повторюсь:

  • ℕ₀ - если включает ноль.

  • ℕ⁺ - если не включает, минимальное равно 1. (N⃰ или ℕ⃰ по ISO, увы.)

Но обычно в пределах одного источника просто уточняют во введении.

Спасибо за многочисленные примеры. Из них, вообще говоря, можно предположить, что включение нуля в множество натуральных чисел является признаком профессиональной деформации дискретных математиков и программистов. Для их задач удобнее оперировать множеством (|N U 0), а вводить для него новое обозначение они почему-то не хотят, проявляя упорство Королевы из «Двенадцати месяцев».

Не знаю можно ли считать государственный стандарт авторитетным, но ГОСТ Р 54521 устанавливает что множество N включает нуль, а множество без нуля называется N*

Любопытный пример. Авторитетным, наверное, считать можно, но учебником — вряд ли. В любом случае, разногласие в отношении понятия натуральных чисел может быть предвестником того, что научный мир «уточнит» их определение и произойдёт то же самое, что произошло с небесным телом под названием Плутон — однажды он перестал быть планетой.

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

Этот стандарт ссылается на ISO 80000-2, где те же определения, а тот, увы, вполне авторитет.

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

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

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

У нас младший делал примерно также, но мы поступали много либеральнее, выбрасывая эти камни во время дневного/ночного сна. В результате сейчас дома есть, в общем-то профессиональный, хотя и нижнего уровня, микроскоп + куча полудрагоценных осколков.

А детка пошёл изучать другие числа и всё равно подсел на компьютерные игры.

В начальной школе и отрицательных чисел нет, и корень из минус единицы брать нельзя

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

Кстати ноль - это еще самостоятельная граница между положительными числами и отрицательными, еще одна его особенность.

И чем вообще ноль отличается тогда от отрицательных чисел? Уж логичнее его к ним тогда относить.

Ноль не похож на остальные натуральные числа - на него нельзя делить.

Это недействительный аргумент, потому что деление вообще некорректно вводить во множестве натуральных (ℕ⁺, ℕ⃰, без нуля) целых чисел. Даже если вы попытаетесь исхитриться определить деление, например, так, что для заданных n, d ищется пара q, r таких, что q*d+r = n, то вы тогда не сможете определить деление нацело: в этом случае r = 0. Будете костылить разделением на два случая, с r и без r? Мы тогда должны откатить всю математику во времена где-то Кардано, во всяком случае, до Виеты. На это ни один разумный математик не пойдёт.

Нет, деление определяется над целыми числами. В крайнем случае - намеренно перекошенно - над ℕ₀, но тогда уже надо делать исключение для нуля, а зачем тогда ограничиваться? (Ну кроме как исследуем операции в компьютере, "unsigned division".)

Придумали бы новое название <любое слово> для целых чисел, начинающихся с нуля и всем было бы хорошо.

Пока что контекста достаточно.

Кстати ноль - это еще самостоятельная граница между положительными числами и отрицательными, еще одна его особенность.

Смысл этой границы недостаточен, чтобы задля неё идти на такие жертвы.

И чем вообще ноль отличается тогда от отрицательных чисел? Уж логичнее его к ним тогда относить.

:)))

Попробуйте рассмотреть ситуацию в целом. Не один аспект, а всю арифметику со всеми целями и операциями, включая многократные применения и особые случаи.

Это недействительный аргумент, потому что деление вообще некорректно вводить во множестве натуральных (ℕ⁺, ℕ⃰, без нуля) целых чисел

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

Ну, в таком случае, единственное подходящее для него множество - целые числа.

Смысл этой границы недостаточен, чтобы задля неё идти на такие жертвы.

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

Попробуйте рассмотреть ситуацию в целом. Не один аспект, а всю арифметику со всеми целями и операциями, включая многократные применения и особые случаи

Аксиомы Пеано смотрят на это с удивлением: "1 не следует ни за каким натуральным числом".

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

Аксиомы Пеано смотрят на это с удивлением: "1 не следует ни за каким натуральным числом".

Они определяют ℕ⁺, но за ним дальше идут методы построения дальше (целые, рациональные и так далее).

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

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

Математика школьная - многочлены. Элементы считаются с 1

Матан.. матрицы.. номера строк и столбцов c 1

Ряды.. элементы начинаются с 1

Степенные ряды с нуля начинаются: a x^0+b x^1+c x^2...

В мире матриц пытаются разизобрести 0 обратно?

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

В матрицах и векторах считать на индексах не нужно. Вы вообще могли бы договориться называть компоненты трёхмерного вектора x как x_q, x_α, x_з, и в семантике бы ничего не изменилось (особенно на школьном или начально-вузовском уровне). Даже разные формулы вроде скалярного произведения выглядели бы так же — xy = x_q y_q + x_α y_α + x_з y_з, или, сокращённо, xy = Π x_i y_i, где i пробегает по элементам { q, α, з }.

Единственная причина начинать в векторах-матрицах счёт с единицы — чтобы не таскать в нотации «минус один» у последнего компонента n-мерных векторов. Выглядит стрёмно.

А вот там, где считать нужно (количество возведений в степень в рядах и многочленах, например) — там счёт с нуля.

Единственная причина начинать в векторах-матрицах счёт с единицы — чтобы не таскать в нотации «минус один» у последнего компонента n-мерных векторов. Выглядит стрёмно.

Кстати, по этой же причине в OCaml'е тоже удобнее считать с 1:

for i = 1 to n do
   ...
done

Но это вообще странное семейство языков — там, например, самый лучший отступ это 3 пробела, а не 2 или 4. :-)

с «человеческой» точки зрения нумерация с единицы действительно удобнее

С единицы привычнее считать номера по порядку. А смещения от начала - с нуля. В программировании чаще нужно второе.

отсчет с 0 у времени есть, и человек тоже попривык

а ёщё отсчёт от 0 у скорости, отсчёт от 0 у расстояния
это отсчёт, а не индекс,
то есть - мы первый раз отсчитали от 0,
а - мы нулевой раз отсчитали от 0 - ну даже кринжово както звучит

а - мы нулевой раз отсчитали от 0 - ну даже кринжово както звучит

Нет, он первый. Но в другом значении этого слова (начальный, антоним к "последний"). Если бы вдруг вместо слова "последний" придумали говорить "девятый" (upd: скорее наоборот, ведь "первый", а не "одиный"), то проблема была бы яснее.

Вот Ada использует атрибуты 'First и 'Last.

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

и ещё многие погромисты привыкли к циклу for - настолько, что он для них роднее и понятнее более модных альтернатив - в смысле на лету читается чуть ли не подсознанием. Но их всё время пытаются переубедить.

Это как нумерация этажей. У англичан с 0 (ground), а в России с 1

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

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

А если 20 лет массивы с нуля считал, то это, извините, уже в днк. Стоит расслабиться на мгновение — ошибешься.

А если 20 лет массивы с нуля считал, то это, извините, уже в днк. Стоит расслабиться на мгновение — ошибешься.

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

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

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

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

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

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

Как же вы разные (человеческие) языки учите, у которых совершенно непохожие символы и грамматики?

Ну и вообще: две нотации на сотни (или тысячи) языков программирования -- это по вашему проблемы? Тут инженеры или кто?

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

Нет, не то чтобы "неправильную нотацию" изучить/освоить совсем нельзя было - люди вон бывает и на лиспе программируют, и на форте, и вообще на всяком. Но зачем? Обратная польская нотация посложнее будет, чем "единичковые" массивы. И я тут имею ровно такое же мнение - она тоже не нужна, ибо придумана для компиляторов-калькуляторов, а не для эффективной работы программистов.

Разницы нет, пока не надо задумываться об этом при интеропе. Стандартом де-факто является интероп с Си. А там нумерация с 0, потому что это следует из арифметики указателей.

Что это за мифический человек, который что-то умеет программировать но не привык индексировать с нуля?

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

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

Является ли человек который готовит себе яишницу на завтрак поваром?

Ну, как говорится "зависит от определения", но вообще да. Есть кулинария, т.е. от латинского culina - кухня. Это в целом о деятельности на кухне, в частности о готовке. Так что такой человек кулинар. У нас как-то больше распространилось слово повар.

Если брать в узком смысле, т.е. как именно специализацию, то нет.

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

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

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

Контекст, зависит от контекста

Ну вот он я. Что-то умею программировать. Но не привык и не люблю индексировать с нуля. Потому что в естественном языке принято обозначать словом "первое" начальное значение. Первое место. Первый в очереди. Первое число месяца. Нигде не используется "нулевой". Бонусом - если элемент в коллекции один, то его индекс (был бы) - тоже один.

Но нет же. На PDP-11 видите ли надо было экономить одну команду, зато теперь человечество в каждом поколении учится думать в 0-индексации и отлаживает идиотские ошибки. Особенно доставляет -2 какой-нибудь, чтобы взять предпоследний элемент.

Хотя, как просто могло бы быть в альтернативной реальности: в массиве из 10 штук - первый элемент имеет индекс [1], последний, десятый - индекс [10]. Предпоследний - 10-1, индекс [9]. Но так слишком скучно будет программировать: что написал, то и работает :)

PS: Древний как ... анекдот: а у вас в исходном коде тоже есть месяц "Нуллябрь" ?

PS: Древний как ... анекдот: а у вас в исходном коде тоже есть месяц "Нуллябрь" ?

Значит, у вас есть "послябрь".

Хотя, как просто могло бы быть в альтернативной реальности

Если бы летоисчисление начали с нуля. Теперь "человечество в каждом поколении учится", что XXI век начинается не в 2000 году, а перед годом 1 шёл год -1.

XXI век начался 1 января 2001 года.

Интересно, а зачем "послябрь" ? Нуллябрем можно забить первый элемент enum-а например, чтобы первый месяц года попадал на человеко-читаемое значение. Чтобы не писать -1 к пользовательскому вводу, если язык не позволяет определять ordinal (Java). Вряд ли в production живёт код с таким enum, но в академических целях почему бы и нет. Для языка с индексацией с единицы по умолчанию был бы просто первый элемент JANUARY, последний - DECEMBER, а ещё один то куда?

Я просто к тому, что "первый" можно считать не привязанным к конкретному числу (может, он на самом деле соответствует "-1" или "A" или ещё чему), как "последний".

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

Интересно, а зачем "послябрь"

для обходя через итераторы конечно же!

с++ std::end() Returns an iterator to the end (i.e. the element after the last element) of the given range

Но нет же. На PDP-11 видите ли надо было экономить одну команду, зато теперь человечество в каждом поколении учится думать в 0-индексации и отлаживает идиотские ошибки. Особенно доставляет -2 какой-нибудь, чтобы взять предпоследний элемент.

В Си операция индексирования массива с именем a - a[i] идентична *(a+i), при этом a - указывает на самый первый (нулевой) элемент массива. Да и вообще, как говорится в K&R - "выражение в виде обращения к массиву по индексу эквивалентно ссылке по указателю со смещением". И это все сочетается и тесно связано с адресной арифметикой.

Допустим, индексация вместо нуля будет начинаться с единицы. И посмотрим на такой код:

int a[3] = { 5, 6, 7 };
int* ptr;

/* В комментариях указаны эквивалентные выражения */
ptr = a;    // или ptr = &a[1] или ptr = a+1
*ptr = 10;  // или a[1] = 10 или *(a+1) = 10 или *(ptr+1) = 10

/* Что будет выведено на экран? */
if ( a == a+1 )
    puts("WTF?!");
else
    puts("a != a+1");

Согласитесь, что при i не равном нулю, равенство между a и a+i будет выглядеть несколько загадочно.

Соглашусь... с оговоркой. Разработки бывают разные. И не обязательно на C. К примеру ну кто в 2025 году работает с адресной арифметикой в кровавом enterprise? А требования к коду, который обрабатывает бизнес-данные в соответствии с бизнес-алгоритмами для удовлетворения бизнес-пользователей :) - ещё оттуда. Как выше правильно замечено - был же Pascal, где программист говорил - мне нужен массив от 65 до 81, компилятор брал под козырёк и бежал компилировать что велено. А не выделывался такой весь "ты кожаный считай от нуля и нигде не ошибись в смещениях, потому что мне так проще будет".

Собственно комментарий выше - он не критика явления как такового. Да, есть железо, где до сих пор экономят каждый байт. K ПП x ещё можно вспомнить. Но, кажется, не следует возводить в абсолют требования индексации с нуля для произвольного языка X решающего спектр задач Y, просто потому, что "здесь так принято". Я нормально читаю текст вроде matcher.group(0).substring(1) , но предпочёл бы для строки начиная со второго символа в ней именно эту цифирь в коде и видеть

В моем С++ не только массивы с нуля, но и простая память обычно инициализируется нулем, а не единицей.

В моей математике на любом языке функция синуса симметрична относительно нуля. И y = x^2. И разные другие.

Я вас поначалу не так понял и вошел в кураж на ночь глядя, прошу прощения. Мне индексация с нуля привычнее и удобнее кажется.

Но нет же. На PDP-11 видите ли надо было экономить одну команду, зато теперь человечество в каждом поколении учится думать в 0-индексации и отлаживает идиотские ошибки.

PDP-11 ни при чём, проблема со всеми компьютерами. А, может, и не только с ними.

Хотя, как просто могло бы быть в альтернативной реальности: в массиве из 10 штук - первый элемент имеет индекс [1],

Ну так снова неоднократно упомянутые Паскаль и прочие :)

Потому что в естественном языке принято обозначать словом "первое" начальное значение. Первое место. Первый в очереди. Первое число месяца. Нигде не используется "нулевой".

Коллизия типа "первый час - это когда час ещё не прошёл, то есть ноль (двенадцать) с минутами" - неотъемлемая часть такого использования. Отсюда и растёт проблема с нулями.

Есть достаточно 1indexing языков (Julia, Wolfram Mathematica, R, Matlab), где нету реализации массивов как тупо указателя на первый :) элемент и вообще указателей как таковых и соответственно связанной с ними адресной арифметики (сишный вывернутый мехом внутрь index[array] == array[index], и количество ошибок связанных с array[N] для адресации последнего элемента). И эти костыли, которые экономили лишний байт в допотопных языках когда память измерялась в килобайтах и имеющие смысл когда язык недалеко от железа и хотя бы умеет в inline assembly, теперь из-за якобы "обратной совместимости" зачем-то тащат дальше, например в какие-нибудь js и python, труъ "программисты" которых понятия не имеют откуда вообще взялась индексация с 0, а если вдруг с 1 то это ужас-ужас-ужас.

Я вроде достаточно написал кода для взаимодействия Lua<->C, там где индексация вообще получается "смешанной" с разных сторон и это как-то не особо напрягало.

В Mathematica индексация с 1 вполне обоснована - в индексе 0 хранится тип.

{1, 2, 3}[[0]]
List
{1, 2, 3}[[1]]
1

Ну и в целом, 1 - это порядковый номер, а 0 - смещение относительно какого-то адреса.

В Математике индексация с 1 не потому что 0 уже был занят типом, скорее в пустое место между первым (1) и последним (-1) можно было что-нибудь воткнуть, размер, например, но путаницы было бы больше при случайном обращении к [[0]] по ошибке.

Осталось только понять зачем это "смещение" от 0 по адресу пытаются использовать для индексации в языках, в которых впринципе такой сущности как "указатель" на какой-то адрес в памяти и соответствующие манипуляции с ними и памятью отсутсвуют как класс.

В Си и языках которые допускают прямую работу с памятью и вообще можно inline assemby - пожалуйста. В верилоге индексация как в паскале хоть и произвольная, но считать биты в байте с единицы никто не будет, т.к. 2^0=1,

wire [7:4] w1;
wire [3:6] w2;

а тот кто массивы 0 индексируемых бит будет объединять в массивы 1 индексированных "слов" видно что очень не любит людей которым это потом после него разгребать придётся :)

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

Вместо нуля использовали "ничего". Ничего сложного, извините за каламбур, в этом нет.

Понятие нуля как числа - вопрос привычки, но с тех пор, как приучились к отрицательным числам, до этого он, по сути, не нужен. А отрицательные возникли тогда, когда стали считать в духе "вот тут 10 вёрст вперёд, потом 4 назад, потом снова 20 вперёд", и когда смогли отрешиться от того, что положительные деньги у тебя в кармане это то, что само уменьшается со временем, а отрицательные (долг) - само увеличивается.

  1. Дизайнеры уровней. Большинство (а может и все) Ниваловских игр как раз LUA использовали

  2. Excel и прочая бизнес-логика. Строки и колонки с 1 начинаются. Номенклатура - тоже

  3. Любые нумерованные списки, включая этот

Что значит недопонятый?

Он оказался очень востребованным во многих проектах, LuaTex существует и развивается уже 18 лет, Adobe Lightroom тоже использует Lua. Не говоря о всяческих конфигурациях: neovim, wezterm (список можно продолжать долго) и используют Lua вовсю. Размер и встраиваемость Lua позволяет не иметь его интерпретатора для использования с этими программами.

Единственная претензия (недостаток), что в Lua нет строгой статической типизации (шо, опять?), но практика показывает, что можно жить и так.

практика показывает, что можно жить и так

Можно, но зачем?

Ну если сложные объекты не передаются, то не нужно. А иначе как автокомплит будет работать?

Что хорошо в lua, так это библиотеки для встраивания почти во всех платформах. В 99% случаев когда вам хочется/бизнес просит сделать свой DSL, надо одернуть себя и просто добавить в проект поддержку скриптов на lua.

Вставлю 5 копеек про индексацию с единицы. Моё мнение — это огромная боль. Учитывая, что lua в основном используется для работы с API, написанным на C-подобных языках (и, соответственно, нумерацией с нуля), при попытке передать через это api массив в сторону lua, получаем что в ней массив начинается с нуля, а это с точки зрения языка неправильно. К примеру, известный парсер lua-json ломается из-за этого. При попытке передать массив в обратном направлении тоже получаем кашу.

Ну и вообще вот это самое API взаимодействия C с lua это огромная куча кода обычно, в которой если хочется передать структуру, то придется писать собственный преобразователь этой структуры в две стороны, и это очень больно.

Ну и ещё бесит отсутствие continue :)

Ну и ещё бесит отсутствие continue :)

goto continue
...
::continue::

Рассказ о возможностях языка без единой строчки кода. Интересное.

А Линус Торвальдс говорил недавно, что Rust лучше всех.. Так кому же верить?

Писал в свое время ботов для ВК на C++ и Lua. Это был самодельный движок для ботов, в плюсах была база получение входящих событий, а в lua их непосредственная обработка и вся логика бота.

Конечно я был криворукий и все постоянно падало, особенно от попытки сделать эту систему "многопоточной"..

Но, сам язык понравился своей простотой, как скелет языка можно сказать. Хотя стандартных фич некоторых сильно не хватает.

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

Причина индексации массивов с 0 не важна. Важно то, что это общепринято.

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

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

Наверное, в той стране есть какие-то преимущества. Жаль что тема преимуществ lua не раскрыта.

Правильно. Вот поэтому я и не стал учить С и ему подобные.

Если что угодно делать осознанно, не будет никаких проблем. Буддисты не дадут соврать.

Lua используется ещё в макросах МойОфис

На вентилятор спора про отличия Lua от остальных языков наброшу ещё такой аргумент: да, можно привыкнуть к индексации с единицы, глобальным переменным, чудному оператору "=~" и т. п., но зачем?

Lua далеко не единственный встраиваемый скриптовый язык: https://github.com/dbohdan/embedded-scripting-languages

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

эмм легковесный python и js? а можно в цифрах, вот последний lua на x64 вест 300кб

И что по скорости вызова как python/js функций из C так и C функций из python/js? я уж не говорю про сравнение с luajit

мне lua не очень нравится, у меня к нему накопилось не мало претензий за 8 лет работы как со встоенным языком и глупости вроде начала индексации с 1, а не нуля будут в самом конце этого списка. НО у него есть неоспоримые плюсы в виде его размеров, простоты и скорости

Размеры это конечно важно, особенно если это скрипт для игры размером в 100 Гб. Простота тоже хорошо, но выклеивать руками из таблиц все что нужно - я не понял этой простоты. Ассемблер тоже простой язык ;)

Скорость .. Ну, возможно.

так игры на 100гб далеко не единсвенная ниша встраивыемых язков

эмм легковесный python и js? а можно в цифрах, вот последний lua на x64 вест 300кб

pocketpy это ~400 кб x86_64. Там весь интерпретатор это один .c объемом ~20k LOC.

Само собой это не весь дистрибутив Python -- это сам язык, его builtins и несколько полезных модулей типа sys, math, json и т. п.

И что по скорости вызова как python/js функций из C так и C функций из python/js?

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

Сам по себе pocketpy примерно в 1.5 раза медленее lua, но при этом чуточку быстрее cpython. То есть соврешенно обычная производительность, к которой все привыкли.

Лично мое мнение -- если производительности скрипта уровня базовых lua/cpython/duktape не хватает, то с высокой долей вероятности вы что-то делаете не так, пытаясь сделать слишком многое силами скрипта.

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

эмм легковесный python и js? а можно в цифрах, вот последний lua на x64 вест 300кб

pocketpy это ~400 кб x86_64

Duktape (встраиваемый Javascript) еще меньше, 150-200 кб кода.

а что у js с целыми 64 битными?)

У Javascript в целом -- все нормально, BigInt поддерживается всеми "полноразмерными" реализациями: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

У duktape конкретно -- пока не очень хорошо, примерно как когда-то давно было у Lua. Довольно странно, BitInt не выглядит как что-то очень уж сложное. Надо будет поглядеть, может получится разобраться и сочинить MR. Другие встраиваемые реализации могут отличаться, я не в курсе.

а что у js с целыми 64 битными?)

Как вы быстро от сомнений в размерах бинарного кода перескочили на выискивание отдельных огрех =). Причем у Python видимо не нашли ничего? =)

Конечно у любого варианта, включая Lua, будут какие-то свои особенности. Вопрос в том сколько их будет и насколько они необычные (специфичные).

Принципы работы и даже особенности поведения настолько распространенных языков как Python или JS по сути уже стали стандартом де-факто. Вероятность что пользователь уже знаком с этими языками и их нюансами, или что эти знания пригодятся ему где-то еще довольно высока. При всех достоинствах Lua, его особенности как правило слишком специфичные.

да в целом то к сожалению я пока не нашёл "лучшего" встраиваемого языка, так что я just for fun тут спрашиваю.

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

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

Но 0/1-based нумерация — не самое упоротое, что бывает в жизни. Самое упоротое, что лично я видел — это background-position в CSS. Вот там веселуха. Там чтобы нарезать ленту на 8 кадров, надо 100% делить на 7 (!!!). Как и нумерацию с единицы, это обосновывают «удобством для человека».

Про нумерацию с 1. Представьте у вас есть матрица (2х мерный массив) NxM. И также вам нужно обращаться к элементам этого массива по сквозному индексу. Например, 5й элемент для массива 3 на 3 это (2 строка 2 столбец). Это если с нумерация строк/столбцов и индекса с 1. Так вот формулы, чтобы получить по индексу строку и столбец будут такие: row = (i - 1) div M + 1, col = ( i - 1) mod M + 1. Это если, опять же, нумерация с 1. А если с 0, то такие: row = i div M, col = i mod M. По сути, в случае нумерации с 1, происходит приведение к 0, а после вычислений - обратно к 1це. Не делать это - тупо быстрее чем делать. Да и выглядит понятнее.

Lua - прекрасный язык для того, чтобы быстро набросать скриптик на десяток-другой строк. Когда-то я выпустил джина из бутылки, сделав возможность написания расширений на Lua для одного программного продукта. Я и представить себе не мог, что позднее на нем начнут писать расширения на сотни тысяч строк кода. А потом карма сработала и заставила меня участвовать в разработке такого Lua расширения :)

Сейчас бы я ни за что на свете не стал бы использовать Lua для этой задачи. Вместо этого я бы использовал V8 чтобы можно было делать маленькие скрипты на JavaScript, что-то побольше на TypeScript, а большие проекты можно было бы писать на чем-то компилируемом в wasm и не мучаться.

чтобы можно было делать маленькие скрипты на JavaScript

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

з.ы чтобы совсем не скучно было надо просто собрать саму Lua в wasm :)

Сотня тысяч строк на Typescript выглядит как нечто поддерживаемое, в отличии от сотни тысяч строк на Lua.

Боюсь, но js хотя бы в TypeScript можно отрефакторить, немного полегчает :) А что делать с Lua совершенно непонятно. Пробовал делать конвертор из Lua в js, но генерируемый код все равно требует ручной доработки чтобы получилось что-то поддерживаемое, а для проектов таких размеров это слишком трудоемко.

для VS Code есть расширение sumneko/lua которое очень неплохо делает Code Server с выведением типов автодополнением и прочими плюшками, так писать скрипты сильно веселее

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

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

1) это дорого

2) сложно написать "обобщённый контейнер" и производить серриализацию дессиреализацию со стороны C

Метатаблицы это дешево. В LuaJIT так вообще незаметно.

может не использовать целые числа в качестве названия членов объекта?

А в чем конкретно состоит проблема? Больше 10 лет пишу на Lua, никогда не путал массивы с объектами.

Если только не делать дичь, когда в одной таблице одновременно и массив с дырами и ассоциативный массив (никогда не приходилось), все остальные варианты проверяются элементарно:
- наличие в таблице массива (проверка t[1])
- наличие в таблице ассоциативного массива (проверка pairs после ключа #t)
- является ли таблица ООП объектом (проверка метатаблицы и поля в ней)
- является ли таблица ООП объектом конкретного класса (сравнение метатаблицы)
- и т.д. и т.п

Это уже извращения, тогда как, например, в js у массивов и объектов разные методы, а тут это недоступно и приходится использовать функции.

А ещё например пустая таблица - это сразу и пустой массив и как её превращать в json? Двусмысленность получается, а json - это тоже современная лингва франка

Да обычные проверки, которые если нужны то помещаются в функции в отдельном модуле и на выходе имеем какой-нибудь utils.is_array().

Сериализаторы Lua знают об этой неоднозначности, и умеют ее обрабатывать с помощью метатаблиц. Но сериализовать нативные иерархии объектов языка напрямую в JSON это вообще не очень идея в любом языке, если только это не для последующей десереализации обратно в эту же нативную иерархию.

Чем не очень идея? Годами так делается во всех динамических языках, вроде js или питона

Тем, что нативная иерархия объектов и требуемый в другом месте формат JSON это две совершенно разные сущности. Банальный пример - первая может требовать полей которые не нужны во второй, или наоборот. В Java и C# такая сериализация настраивается явно с помощью аннотаций, а в Lua такой возможности нет.

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

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

Дело не в том, что "приходится". За счет рефлексии в Java и C# можно написать автоматическую сериализацию хоть всей иерархии целиком. Так просто не делают, потому что это почти никогда не нужно на практике, потому что объекты сплошь забиты полями которые требуют исключения или особой обработки сериализации.

Если мы удаляем какие-то поля, значит мы это делаем где-то в конкретном месте, например в функции. Причем делаем это в коде, который знает какие поля есть у объекта, а какие поля нужны JSON. А значит в этом же самом месте мы можем обрабатывать и случаи с неоднозначностями, навешивая требуемые метатаблицы.

Ещё надо трекать ссылки на другие объекты. Возможно, циклические.

Использование в качестве стартовой позиции в массиве 1 имеет смысл, когда вы рассуждаете как человек.

Вот почему мне комфортно жить в Израиле - этажи считаются с нуля, и я, как программист на Perl и всяких C-подобных языках, всегда знаю, на каком я этаже. Пусть и не рассуждаю, как человек... :)

А когда приезжаешь на многоуровневую парковку в ТРЦ, где нумерация этажей начинается с -2, а ты сразу на +2, сразу понимаешь что архитектор программист на паскале ;)

Скажите, а чем это лучше тикля?

Чуть менее упоротым синтаксисом (тикль вроде заметно старше)? Даже несмотря на все те вещи (~=, then, begin, end, continue) которые в Lua можно было бы сделать и более похожими на С.

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

Довольно аккуратным С api, но тут про tcl мало чего знаю, так что сложно сравнивать.

Lua в свое время и появился как альтернатива Tcl (со слов автора языка):

Однако у Tcl был непривычный синтаксис, не было хорошей поддержки описания данных, и запускался он только на платформах Unix. Мы не рассматривали Лисп или Scheme из-за их недружелюбного синтаксиса. Python был ещё во младенческом возрасте.

Иронично, что изначально Lua задумывался как

Из-за того, что большинство пользователей не было профессиональными программистами, языку следовало избегать замысловатого синтаксиса и семантики.

Но сейчас, когда C-подобные языки и Python по сути стали стандартом де-факто, Lua получился замысловатым в сравнении.

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

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

поскольку тот же Python больше не во младенческом возрасте

наброшу,

Сугубо имхо, но использовать пробел в качестве элемента синтаксиса языка это гораздо большая упоротость чем все вместевзятые: индексация с 1, глобальные переменные, begin/end и т.п.

В качестве встраиваемого скриптового языка в ядро (linux/netbsd) насколько знаю питон или js, пусть и подрезанные, запихать никто даже особо не пытался, а lunatik как-то живёт.

Делаешь игры в роблокс и не паришься насчёт создания движка. А вообще, луа подойдёт разве что для обучения детей программированию. Как первая ступень. Потом писать либо на питоне, либо на плюсах/решетке

Есть огромные области, где нужен легковесный язык скриптования. В геймдеве, например. Или в embedded.

Sign up to leave a comment.