Видимо автор языка не любил Си. Хороший оператор. Не обязательный, но правильный.
Опять мои пять копеек
Когда-то я писал i++, потому что "все так пишут". Потом узнал разницу между ++i и i++ - в первом случае происходит простой инкремент, во втором - сначала копируется значение i (в общем случае могущее быть большим и тяжёлым объектом), и только потом происходит инкремент старой копии. Поэтому я стал писать ++i. Однако потом меня захватила идея читабельности кода, и с тех пор мне кажется, что выражение i += 1 более "говорящее", чем ++i
Так что вопрос правильности - субъективный, зависит от мотивов
Dimka, а выскажись по той же линии о C++, Java, PHP, Perl и JavaScript. Интересно.
Про PHP мне сказать нечего - я на нём только 3 строчки написал и то давно. Мнения не имею.
Говорить о C++ можно только в контексте C. В стародавние времена 70-х годов, когда переменные были не длиннее 8 символов, нажатие кнопки на клавиатуре терминал отрабатывал десятки миллисекунд, а экран был 30х20 символов или около того, синтаксис с обилием значков, компактных синтаксических конструкций и префиксов у переменных реально ускорял процесс набора кода и повышал читабельность. Сейчас с использованием автогенераторов кода и средств ускорения набора это не актуально. В то же время более "словесный" синтаксис Algol и последующих языков с моей точки зрения выглядит более аккуратным.
Возможность в C/C++ напрямую работать с памятью, чёткое разделение указателей и значений - вещь незаменимая в своём классе задач. В то же время добавление в C++ ссылок на мой взгляд создало элемент неочевидности в коде: в отдельно взятом алгоритме, вызывающем другие функции, нельзя гарантировать сохранность значений переменных - это отдано на откуп программисту - возникает потенциал для ошибок. Математическим идеалом (на практике при работе с железом недостижимым) с моей точки зрения являются stateless вычисления, к которым тяготеет функциональное программирование. Наличие состояний, изменяющихся со временем областей памяти, на которые ведут постоянные ссылки - это всё ослабление инкаспусляции и повышение рисков ошибок, от которых в принципе не может защитить строгая типизиация. Указатель сразу "сигнализирует" о том, что в данном месте используется скорее всего разделяемая в нескольких местах кода область памяти; ссылка же выглядит, как обычная переменная (в традициях структурного подхода локальная), а работает как глобальная переменная со всем из этого вытекающим. Особенно это важно в нынешние времена параллельных вычислений.
Множественное наследование, вытекающее из отстутствия синтаксической конструкции (и тем самым выраженной в языке концепции) interface, на мой взгляд является не очень хорошим атавизмом в C++. Более поздние языки, запрещающие множественное наследование, но разрешающие реализацию множества интерфейсов, в этом вопросе выглядят "стройнее". Почему так - это отдельная тема
Java, если говорить о синтаксисе, язык неплохой, нормально реализующий концепции ООП (для языка со строгой типизацией). Про стиль синтаксиса C-образный или Algol-образный я выше сказал. Pure ООП приводит к громоздкости кода - на всякий чих нужно заводить маленький классик. Однако структура программы, принципы размещения кода по файлам и файлов по пакетам в Java довольно приятные, чем-то похожие на Python. Все эти маленькие классики хорошо инкапсулируются в файлах и не портят общую структуру программы. У Java есть проблемы на уровне виртуальной машины, связанные с оптимизацией и производительностью, поэтому я слышал жалобы на то, что компилятор вынуждает программиста некоторые вещи писать неочевидным способом - это, на мой взгляд, не проблема синтаксиса, поэтому эту часть языка я комментировать не буду. Последние версии в рамках непонятно какой общей тенденции во всех языках добавляют всякий синтаксический сахар для упрощения кода, избавления от маленьких классиков, от излишнего boxing'а простых типов в объекты. Что-то полезное, что-то нет, но по сравнению с вакханалией в C# Java выглядит лучше.
Синтаксис Java, не различающий явным образом переменные ссылок и значений (лишь по типам) и необходимость для некоторых вещей использовать механизм boxing'а (особенно автоматического) вместе с не очень эффективным в данном вопросе компилятором приводят к неочевидному коду, дающему неожиданные для программиста последствия в части производительности. Введение generic-типов в 5-й версии во многом позволяет снизить остроту этой проблемы. Сама идея освободить синтаксис от "лишних" значков, различающих ссылки и значения, скорее всего правильная, но "дырявые абстракции" и неэффективные компиляторы сильно портят преимущества этой идеи. Опять же вылезает то обстоятельство, что нет stateless-вычислений, поэтому именно программист всегда должен помнить, где у него ссылка, а где значение - это важно для операций сравнения, для внесения изменений (нужно копировать перед изменением или нет). При stateless-вычислениях этот вопрос не возникает - в общем случае считается, что всегда происходит копирование (например, такая идея реализована при работе со строками в .NET), а чтобы повысить производительность, достаточно интеллектуальный транслятор языка сам должен определять, что можно не копировать в данном месте, заменив ссылкой и сэкономив память и время исполнения, а что нужно копировать обязательно.
Про Perl я могу говорить лишь осторожно. Я не использовал его богатые библиотеки и не уверен, что знаю многие приёмы программирования на нём. Тем не менее его синтаксис на мой взгляд совершенно невменяемый - не видно никакого центрального стержня, любая фенечка реализуется дополнительной синтаксической конструкцией со всякими префиксами. Сами конструкции тоже не обладают каким-то однообразием, вернее, они однообразно разнообразны - стиль Perl
. Инстанцирование модулей (позволяющее реализовать ООП) сама по себе идея неплохая, но на уровне синтаксиса она выливается в некие соглашения о кодировании и наименованиях, что я не приветствую. Если есть какая-то программистская концепция, по-моему она должна выражаться в синтаксисе языка непосредственно, так, чтобы на уровне трансляции сразу было понятно, что программист реализовал, а что забыл. Т.е. применение ключевых слов предпочтительнее, чем применения специально выделенных для этого методов, атрибутов, переменных и т.п. Можно и так сказать: если некая концепция является элементом языка, то нужны ключевые слова и синтаксические конструкции, если же она является элементом библиотеки языка, то, напротив, она должна реализовываться через элементы языка (транслятор не должен о ней знать). Эти два уровня должны чётко различаться, причём первый уровень должен стремиться к минимализму. Можно ввести промежуточный уровень "синтаксического сахара", каждый элемент которого должен иметь понятную реализацию (или макроопределение) через базовые средства языка (как это делается, например, в Ruby). В Perl же (по моим впечатлениям) все эти уровни имеют некую общую пересекающуюся "серую зону", что усложняет транслятор и делает код более запутанным.
У Perl есть ещё одна не очень хорошая черта - наличие специализированных глобальных переменных, описывающих разные вещи: от результатов выполнения операций до списка параметров процедуры. Не знаю точно, как эти переменные разделяются в параллельных потоках, но скорее всего при помощи неких костылей. К преимуществам Perl можно отнести тесную интеграцию с командными оболочками, высокое быстродействие программ (по сравнению с прочими скриптовыми языками, и, наверно, в немалой степени это связано с различением переменных-сылок и значений), встроенные регулярные выражения (которые затем стали перенимать другие скриптовые языки) - всё это важно для сисадминов, для которых Perl и создавался.
RXL, зная твою любовь к Perl, я заранее согласен с тем, что моё мнение несправедливо, что Perl, если внимательно посмотреть, стройнее и логичнее, красивее и объектно-ориентированнее, и что я Perl знаю плохо.
Но ты спросил - я ответил
Ну что сказать о JavaScript... Чего-то особо выдающегося в плане синтаксиса у этого языка я не вижу. В части производительности - тоже. В части стандартных средств, встроенных типов - тоже. Всё типично для скриптовых языков. Чем кардинально отличается JavaScript (и Lua) от других языков - так это безклассовой версией ООП. Язык, в котором есть объекты, но на уровне синтаксиса нету классов. Благодаря этому синтаксис языка упрощается. В теоретическом плане единственной абстракцией является ассоциативный массив (он же словарь). Функции рассматриваются как данные, поэтому сохраняются в переменных и словарях наравне с прочими данными. И в этом смысле по стройности своей теоретической основы JavaScript и Lua ближе к Lisp, нежели все остальные языки. Конечно, в языке есть синтаксические надстройки, позволяющие пытаться использовать информацию о типах (в случае объектов типом признаётся функция-конструктор), но я не уверен, что это положительное явление. Отсутствие АТД (и классов) приводит к существенному падению производительности исполняемых программ, поскольку на каждый вызов функции через переменную интерпретатор вынужден производить дополнительные проверки корректности вызова, при этом каждый раз не имея информации (обычно определяемой классом или хранящейся как RTTI), что в данном случае подразумевается под тем или иным вызовом. Тем не менее большой проблемой это не видится, так как и сами проверки значительно упрощаются. ООП без классов задействует альтернативные механизмы обобщения и повторного использования кода: наследование классов заменяется делегированием объектов через их прототипы. Тем не менее в JavaScript это делегирование с прототипами несколько однобоко. Прототип определяется у конструктора объекта, и все объекты, созданные одним конструктором, имеют один общий объект-прототип - программист не может простым способом управлять этой привязкой и выбирать между общим прототипом или индивидуальными прототипами для каждого объекта. Общий прототип удобен для создания примесей (к коим, как к концепции, я отношусь скептически), но в общем случае как альтернатива наследованию он чаще всего неудобен. Однако это неудобство несложно обойти, поскольку имеется возможность вызвать цепочку конструкторов для одного объекта (замыкания в памяти) - информация о типе потеряется, но объект унаследует все свойства, которые в нём создали и переопределили всего его конструкторы в порядке их исполнения.
В традиционном холиваре статическая vs динамическая типизации я предпочтений не имею. Каждый способ типизации влечёт за собой свои особенности организации процесса разработки. Если их учитывать, эффективность разработки больших программ на языках с первым и вторым способом типизиации будет примерно одинаковой, просто по-разному будет выстроен производственный процесс.