Nim совершенный язык программирования


Оглавление (нажмите, чтобы открыть):

Nim: идеальный язык программирования

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

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

Идеальный язык

Сегодня мы поговорим о малоизвестном звере среди набирающих популярность языков программирования: Nim.

На текущий момент Nim является идеальным для меня языком в сравнении с C++, Java, D, Rust, Ruby, JavaScript, PHP и многими другими. Nim органично объединяет удачные концепции из других языков, таких как Python, Lisp, C, Object Pascal, Ada, Modula-3 и лишь автору известно, каких еще. Прежде чем делать выводы, мне довелось написать на нем не одну тысячу строк. Предупреждаю, что некоторые детали будут не сразу понятны людям из «мейнстримовых» языков: чтобы осознать эти вещи, их нужно потрогать.

Итак, приступим. Характеристики моего идеального языка:

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

Безопасность. Работа с данными в куче не обременяет управлением памятью. Освобождение системных ресурсов должно происходить автоматически. В той или иной степени это обеспечивают современные языки со сборщиком мусора и Rust.

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

Выразительность. Язык должен быть расширяемым и дружелюбным к разного рода DSL. Ruby, Perl и некоторые другие языки имеют в этом определенные успехи.

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

Низкий уровень. Мы его не хотим, но иногда его не избежать. Ручное управление памятью, где это необходимо, адресная арифметика, задачи жесткого реального времени. И в таких случаях мы не хотим использовать другой, «более низкоуровневый» язык.

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

Портируемость. Код на нашем языке должен запускаться везде, где запускается код на C. Любая ОС, любая архитектура, включая ARM, PIC и AVR, используемый в некоторых Arduino. Даже больше, было бы здорово запускать его в браузерах, поддерживающих Javascript!

Совместимость с религиозно-несовместимыми экосистемами. За декады существования C, C++ и Java было написано множество отличных библиотек. Было бы здорово в случае необходимости использовать их в проекте, написанном на нашем идеальном языке.

Звучит утопично, но Nim соответствует всему вышесказанному, и я бы не поверил, если бы не убедился в этом на собственном опыте.

О том, как начать писать на Nim, о его синтаксисе и других банальностях вам непременно следует почитать здесь:
— Nim by example
— How I start
— Официальное руководство

В данной статье я хочу показать более изощренные возможности Nim, позаимствовав некоторые детали из презентации создателя языка Nim, Андреаса Румпфа (Andreas Rumpf), недавно прошедшей в рамках OSCON.

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

Шаблоны

Начнем с выразительности и расширяемости синтаксиса:

Выполнение этого кода выведет результат:

Если любопытный читатель заглянет в промежуточный С-код, то он увидит, что весь HTML-код записан одной За это отвечает мощный механизм сворачивания констант (constant folding), реализованный в компиляторе Nim.

Макросы

Если же мощь шаблонов по какой-то причине вас не убедила, на помощь приходит тяжелая артиллерия — макросы. В Nim это процедуры, принимающие узлы AST (Abstract Syntax Tree — результат синтаксического анализа языка) в качестве аргументов и возвращающие модифицированный AST.

Следующий пример требует углубленных познаний в языке. Для примера попробуем добавить в Nim анализ покрытия кода (code coverage). Возьмем подопытную процедуру:

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

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

В результате компиляции мы увидим следующее:

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

Таким образом, менее чем в 30 строках кода мы реализовали полезный функционал, для которого в иных языках потребовались бы отдельные инструменты. С помощью макросов вы можете добавлять в язык различные функции, которых вам не хватает: интерполяция строк, pattern matching или что-то еще. Выверенный синтаксис Nim обеспечивает однозначность грамматики при использовании расширений. Увидев «загадочный» DSL-код, вы всегда знаете, с какими аргументами вызвать grep ;).

Управление памятью

Как уже было сказано выше, наличие развитых средств управления памятью является ключевой сильной стороной языка программирования. Nim позволяет использовать как ручной, так и автоматический способ управления памятью. Для этого в нем существуют такие модификаторы, как ref и ptr .

Рассмотрим их назначение на примере объектов:

Теперь у нас есть некий новый тип, и мы можем создавать объекты этого типа несколькими способами. Первый способ — создание объекта по значению:

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

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

В таком случае переменная pp будет ссылаться на объект, который находится в хранилище, управляемом сборщиком мусора, а реальный тип переменной будет ref Person (ref — управляемая ссылка). Такие объекты передаются в коде по ссылкам и умирают тогда, когда ссылки на данный объект в памяти отсутствуют.

Теперь перейдем к последнему, самому низкоуровневому способу работы с памятью, а именно — к работе с неуправляемым хранилищем памяти, которая осуществляется с помощью функций alloc, realloc и dealloc , по поведению напоминающие malloc, realloc и free.

Как можно определить из примера, в данном случае переменная up , как и в предыдущем случае, изменяет тип, то есть ее тип — не Person , а ptr Person , что обозначает небезопасный неуправляемый указатель, хранящий адрес объекта в памяти.

При этом в случае необходимости, для удобства использования таких типов с модификаторами, их можно явно обозначить с помощью ключевого слова type:

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

Взаимодействие с другими экосистемами

Под капотом Nim использует C, C++, Objective-C или JavaScript как промежуточный код. Это значит, что использование библиотек, написанных на этих языках, довольно тривиально. Другие языки, как правило, предполагают механизмы расширения через И здесь Nim справляется прекрасно, позволяя писать бриджи к другим языкам, как библиотеки.

Недолго думая, я набросал небольшую библиотеку jnim, доступную на GitHub. jnim позволяет «импортировать» модули Java. Выглядит это так:

Вся магия происходит внутри jnim. Для каждого определения jnimport создается одноименная сущность в Nim, и генерируется весь необходимый glue-код. Дальнейшим развитием jnim будет возможность не указывать поля и процедуры, а автоматически импортировать определения классов из Java-окружения на этапе компиляции.

Заключение

Nim — это мощный и практичный инструмент, достоинства которого трудно осветить в одной статье. Мы в ZEO Alliance недавно начали писать игровой проект на Nim, который, насколько я знаю, станет одной из первых коммерческих игр, написанных на этом языке.

Также мы популяризируем этот язык внутри Альянса, проводим ряд образовательных мероприятий для наших сотрудников и планируем пригласить в Украину автора Nim, Андреаса Румпфа.

Интересно, кто еще работает в этом направлении в Украине? Буду рад прочесть в комментариях ваши отзывы и мнения. Есть ли у вас опыт использования Nim? Сталкивались ли вы с задачами, для решения которых Nim был бы более эффективным инструментом?

Благодарю Ростислава Дзинько за секцию об управлении памятью в Nim и Андреаса Румпфа за вычитку и правку статьи.

Efficient, expressive, elegant

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula.

Efficient

  • Nim generates native dependency-free executables, not dependent on a virtual machine, which are small and allow easy redistribution.
  • The Nim compiler and the generated executables support all major platforms like Windows, Linux, BSD and macOS.
  • Fast deferred reference counting memory management that supports real-time systems.
  • Modern concepts like zero-overhead iterators and compile-time evaluation of user-defined functions, in combination with the preference of value-based datatypes allocated on the stack, lead to extremely performant code.
  • Support for various backends: it compiles to C, C++ or JavaScript so that Nim can be used for all backend and frontend needs.

Expressive

  • Nim is self-contained: the compiler and the standard library are implemented in Nim.
  • Nim has a powerful macro system which allows direct manipulation of the AST, offering nearly unlimited opportunities.

Elegant

  • Macros cannot change Nim’s syntax because there is no need for it — the syntax is flexible enough.

  • Modern type system with local type inference, tuples, generics and sum types.
  • Statements are grouped by indentation but can span multiple lines.

Recent articles

Version 1.0.2 released

The Nim team is happy to announce version 1.0.2, our first patch release following Nim 1.0.0.

Version 1.0 released

Featured projects

Karax

Karax is a framework for developing single page applications in Nim. Leverage Nim’s macro system to produce a framework that allows for the development of applications that are boilerplate free.

Nimbus

Nimbus aims to be a sharding client for Ethereum 2.0 Blockchain. Ethereum will potentially be on embedded systems, Nimbus will be designed to perform well on IoT and personal mobile devices.

5 свежих языков программирования

Перед вами 5 совершенно новых языков программирования. У них пока нет таких мощных покровителей, как Google или Mozilla, но определенно есть душа, способная в перспективе привлечь и их, и вас.

Stanza

L. B. Stanza — язык, вот уже несколько лет разрабатываемый в стенах Беркли. На текущий момент свежая версия — 0.11.8.

Что хорошего: удобный синтаксис, схожий с Python или Java. Компиляция непосредственно в машинный код, что делает язык чрезвычайно производительным. Динамическая типизация и параллелизм. Гибкая архитектура, предполагающая мультметоды и перегрузки функций, обеспечивающие всю мощь функционального программирования.

defn lazy-flatten (x) :
generate :
defn loop (x) :
match(x) :
(x:List) : do(loop, x)
(x) : yield(x)
loop(x)

val first-4 = take-n(4, lazy-flatten(`(a b (c (d e f (g) (h)) (i j)))))
println(first-4)

Nimrod, предшественник Nim, появился на свет еще в далеком 2004 году, компилятор в 2008, а первая официальная версия до сих пор не запущена. В январе этого года объявилась лишь ревизия 0.16.

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

# Compute average line length
var
sum = 0
count = 0

for line in stdin.lines:
sum += line.len
count += 1

echo(«Average line length: «,
if count > 0: sum / count else: 0)

Crystal

Ruby-подобный язык Crystal придется по душе опытным рубистам, ведь им практически не придется тратить время на «вкатывание». Язык активно развивается последние 3 года, актуальная версия — 0.11.

Что хорошего: статическая типизация без указания типов переменных или аргументов метода. Привязка Си-кода с использованием биндингов. Оценка времени компиляции и генерации кода. Компиляция прямо в машинный язык. А еще русская версия официального сайта.

# A very basic HTTP server
require «http/server»

server = HTTP::Server.new(8080) do |context|
context.response.content_type = «text/plain»
context.response.print «Hello world, got #
end

puts «Listening on http://127.0.0.1:8080»
server.listen

Еще один наследник Python, разрабатываемый для обеспечения удобства взаимодействия с кодами на C/C++, Java и Objective-C. Самая свежая версия — 0.8.

Мастер Йода рекомендует:  Введение в ООП с примерами на C#. Часть третья. Практические аспекты использования полиморфизма

Что хорошего: принцип KISS (keep it simple, stupid). Статическая типизация. Адаптация под разработку мобильных приложений: помимо подключения кодов на популярных языках, это возможность компилировать код для платформы Android.

redef class Int
# Calculate the self-th element of the fibonacci sequence.
fun fibonacci: Int
do
if self
None

actor Main
new create(env: Env) =>
let a = Doer.create()
let n: U32 = 5
a.do1(n)

Причин для создания нового языка программирования может быть множество: банальная скука, желание изменить традиционный подход, доработать существующий язык, предложить свой личный взгляд на «правильное» программирование. Однако до вершин и большой популярности добираются лишь те, что реально упрощают жизнь программиста и увеличивают его производительность с помощью синтаксиса или прилагаемых инструментов. Так, например, Go или Rust не просто предложили разработчикам удобный язык, они создали экосистему, в которой хочется работать. Именно поэтому их рейтинги так стремительно растут.

Перед вами 5 совершенно новых языков программирования. У них пока нет таких мощных покровителей, как Google или Mozilla, но определенно есть душа, способная в перспективе привлечь и их, и вас.

Stanza

L. B. Stanza — язык, вот уже несколько лет разрабатываемый в стенах Беркли. На текущий момент свежая версия — 0.11.8.

Что хорошего: удобный синтаксис, схожий с Python или Java. Компиляция непосредственно в машинный код, что делает язык чрезвычайно производительным. Динамическая типизация и параллелизм. Гибкая архитектура, предполагающая мультметоды и перегрузки функций, обеспечивающие всю мощь функционального программирования.

defn lazy-flatten (x) :
generate :
defn loop (x) :
match(x) :
(x:List) : do(loop, x)
(x) : yield(x)
loop(x)

val first-4 = take-n(4, lazy-flatten(`(a b (c (d e f (g) (h)) (i j)))))
println(first-4)

Nimrod, предшественник Nim, появился на свет еще в далеком 2004 году, компилятор в 2008, а первая официальная версия до сих пор не запущена. В январе этого года объявилась лишь ревизия 0.16.

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

# Compute average line length
var
sum = 0
count = 0

for line in stdin.lines:
sum += line.len
count += 1

echo(«Average line length: «,
if count > 0: sum / count else: 0)

Crystal

Ruby-подобный язык Crystal придется по душе опытным рубистам, ведь им практически не придется тратить время на «вкатывание». Язык активно развивается последние 3 года, актуальная версия — 0.11.

Что хорошего: статическая типизация без указания типов переменных или аргументов метода. Привязка Си-кода с использованием биндингов. Оценка времени компиляции и генерации кода. Компиляция прямо в машинный язык. А еще русская версия официального сайта.

# A very basic HTTP server
require «http/server»

server = HTTP::Server.new(8080) do |context|
context.response.content_type = «text/plain»
context.response.print «Hello world, got #
end

puts «Listening on http://127.0.0.1:8080»
server.listen

Еще один наследник Python, разрабатываемый для обеспечения удобства взаимодействия с кодами на C/C++, Java и Objective-C. Самая свежая версия — 0.8.

Что хорошего: принцип KISS (keep it simple, stupid). Статическая типизация. Адаптация под разработку мобильных приложений: помимо подключения кодов на популярных языках, это возможность компилировать код для платформы Android.

redef class Int
# Calculate the self-th element of the fibonacci sequence.
fun fibonacci: Int
do
if self
None

Nim (язык программирования) — Nim (programming language)

Nim

парадигма мульти-парадигма : составлен , одновременно , процедурное , крайне важно , объектно-ориентированный
Разработано Andreas Rumpf
Во-первых появился 2008 ; 11 лет назад ( 2008 )
релиз Preview
Typing дисциплины Статическая , сильный , Inferred , структурный
Платформа IA-32 , x86-64
Операционные системы Кросс-платформенная
Лицензия MIT
расширения файлов .nim
Веб-сайт NIM-Ланг .org
Под влиянием
Ada , Modula-3 , Лисп , C ++ , Object Pascal , Python , Оберон

Nim (ранее назывался Нимрод ) является обязательным , несколько парадигм , компилируемый язык программирования разработан и Андреас Rumpf. Он разработан , чтобы быть «эффективными, выразительными, и элегантным», поддерживая метапрограммирование , функциональная , передачу сообщений , процедурной и объектно-ориентированное программирование стили, предоставляя несколько функций , такие как время компиляции генерации коды, алгебраические типы данных , с внешней функцией интерфейс ( FFI) с C и компиляции в JavaScript , C и C ++ .

содержание

Описание

Nim статически типизированный. Он поддерживает во время компиляции метапрограммирования функции , такие как синтаксические макросы и термин переписывание макросов . Срочные переписываниями макросы позволяют библиотеки реализаций общих структур данных , такие как bignums и матрицы должны быть реализованы с эффективностью , как если бы они были встроенными средствами языка. Итераторы поддерживаются и могут быть использованы в качестве первых лиц класса в языке , как функции могут, эти функции позволяют функционального программирования , которые будут использоваться. Объектно-ориентированное программирование поддерживается наследование и множественной диспетчеризации . Функции могут быть универсальными и могут быть перегружены, дженерики дополнительно повышается за счет поддержки классов типа. Перегрузка операторов также поддерживается. Nim включает перестраиваемую автоматическую сборку мусора на основе отложенных подсчета ссылок с обнаружением цикла . В 2014 году Эндрю Бинсток (редактор главного журнала доктора Добба ) сказал : «Нимрод [прежнее название] . представляет самый оригинальный дизайн , который колеблется между Паскалем и Python и компилирует в код C или JavaScript.» Сегодня Nim компилирует C ++ тоже.

история

Начальное развитие Nim началось в 2005 году Андреас Rumpf. Первая версия Nim компилятор был написан на языке Pascal с использованием Free Pascal компилятор. В 2008 году версия компилятора , написанной в Нима был освобожден. Компилятор бесплатно и с открытым исходным кодом и разрабатывается группой добровольцев , работающих с Андреасом Rumpf. Язык был официально переименован из Нимрода в Nim с выпуском версии 0.10.2 в декабре 2014 года.

дизайн Язык

Синтаксис Nim похож на Python .

В деталях, это зависит от:

  • Modula-3 : прослежено против нетрассируемых указателей
  • Object Pascal : безопасный типа битовых наборов (набор символов), случай синтаксиса оператора, различные имена типов и имена файлов в стандартной библиотеке
  • Ada : типы поддиапазона, особый тип, безопасные варианты / объекты случая
  • C ++ : Перегрузки, обобщенное программирование
  • Python: Off стороне правило
  • Lisp : Макро система, охватывают AST, homoiconicity
  • Oberon : Экспорт маркера
  • C # : Async / Await , лямбда — макросы
  • Перейти : Перенести


Кроме того , Nim поддерживает унифицированный синтаксис Function Call (UFCS) и идентификатор равенства.

составитель

Компилятор Nim излучает оптимизированный C — код и откладывает компиляции на внешний компилятор использовать свою оптимизирующую и портативность способность. Многие компиляторы поддерживаются в том числе Clang и GNU Compiler Collection (GCC). Компилятор может также испускает C ++ , Objective-C , и JavaScript код , чтобы легко взаимодействовать с интерфейсами прикладного программирования (API) , написанные на этих языках. Это позволяет создавать приложения для прошивки и Android .

Компилятор Nim является само-хостинг , а это означает , что написано на языке Nim.

инструменты

проворный

Ловкий является менеджером пакетов , используемым Nim для упаковки модулей NIM. Он использует NimScript для конфигурации. Ловкие работы на Git репозиториях как основной источник пакетов. Его список пакетов хранится в JavaScript Object Notation ( JSON файл) , который свободно доступен в Nim-Лэнга / пакетов репозитория. Этот файл JSON обеспечивает шустрый с нужной URL Git клонировать пакет и установить его.

c2nim

c2nim помогает генерировать новые привязки путем перевода ANSI C кода Nim код. Выход человеческого считываемый код Nim , который предназначен для отлажены вручную после процесса перевода.

Choosenim

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

Nimfix

Nimfix является инструментом, который позволяет конвертировать старый стиль Nimrod код Nim кода. Nimfix в настоящее время бета-качество.

pas2nim

pas2nim является инструментом для перевода Object Pascal оберток для Nim кода. Он был использован для перевода первоисточники Pascal компилятора Nim. Только то , что легко сопоставляется Nim поддерживаются. Free Pascal, Delphi класс стиля или другие модные функции не поддерживается. В это время, развитие и поддержание в основном в тупик.

py2nim

py2nim является инструментом , используемым для transpiling кода Python в идиоматический код Nim. Развитие активно, с планами по расширению объема кода на Python , который может быть полностью переведен на Нима.

Библиотеки

Программа Nim может использовать любую библиотеку , которую можно использовать в C и C ++ программы. Языковые привязки существуют для многих библиотек, например , GTK + , SDL 2, Cairo , OpenGL , WinAPI , Zlib , libzip , OpenSSL и Curl . Nim работает с PostgreSQL , MySQL и SQLite базы данных. Nim может взаимодействовать с Lua и Python интерпретатор.

Примеры

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

Привет, мир

Реверсивный строку

Простая демонстрация показывает многие из особенностей Nim в.

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

Stropping

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

Метапрограммирование

Это пример метапрограммирования в Nim, используя свои шаблоны объектов.

genType Вызывается во время компиляции и Test создается тип.

Обертывание функции C

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

В этом коде хорошо известная printf функция импортируется в Нима , а затем использовали.

сообщество

Проект имеет баг — трекер с вики организовано GitHub и форумом. Презентация на O’Reilly Open Source Конвенции (OSCON) в 2015 году имели место. O’Reilly Сообщество: Эфирные Языки: Nim, Scala , Python.

H Nim и Go против Wikipedia в черновиках

.collapse»>Содержание

Вступление

Прошлая неделя на Хабре прошла под знаком Go.
В последнее время я все чаще начал слышать о новом языке Nim.
Оба языка компилируемые, быстрые, кроссплатформенные и достаточно легкие для входа. Go уже успел завоевать любовь многих, Nim только начинает этот путь. Мне были интересны оба языка, но сложно выбрать кто из них окажется лучше пусть даже и для проектов for fun.

Алгоритм

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

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

Решение на Go потребовало внешней библиотеки для парсинга HTML и в целом получилось несколько многословным из-за возврата статуса ошибок (но это скорее фишка языка).

Решение на Nim использует только стандартные библиотеки, зато 9 штук.

Итоги

В примере по умолчанию мы ищем путь от страницы Sort до страницы SAP: Sort ⇒ GNU/Linux ⇒ SAP

На Ubintu в vagrant получаются следующая картина:

Язык Размер исполняемого файла Скорость на стандартном примере Скорость на сложном примере UNIX ⇒ PostgreSQL
Go 5 959 424 byte real 0m6.031s
user 0m0.216s
sys 0m0.120s
real 0m26.078s
user 0m2.788s
sys 0m1.648s
Nim 701 589 byte real 0m1.974s
user 0m0.240s
sys 0m0.024s
real 1m2.921s
user 0m4.224s
sys 0m1.376s

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

В заключение несколько получившихся цепочек:
Nim ⇒ Си_(язык_программирования) ⇒ Go
Windows ⇒ 1985_год ⇒ Индия
Интернет ⇒ Английский_язык ⇒ Новая_Зеландия ⇒ Кошка
Стрела ⇒ Бамбуковые ⇒ Велосипед ⇒ Коленный_сустав
Half-Life_2:_Episode_Three ⇒ Half-Life_(серия_игр) ⇒ Эмблема ⇒ Вечность
Go ⇒ 2009 ⇒ 9_марта ⇒ Счастье
Nim ⇒ 2015 ⇒ 9_марта ⇒ Счастье

Увидел свет язык программирования Nim 1.0

Представлен релиз языка системного программирования Nim 1.0. Версия 1.0 преподносится как стабильный выпуск с длительным сроком поддержки для которого будет гарантировано сохранение обратной совместимости в стабилизированной части языка. Отдельно в компиляторе доступен экспериментальный режим, в котором будут развиваться новые возможности, которые могут нарушать обратную совместимость. Некоторые API в стандартной библиотеке также пока помечены как нестабильные и будут переводиться в разряд стабильных по мере готовности. Код проекта поставляется под лицензией MIT.

Язык Nim использует статическую типизацию и создан с оглядкой на Pascal, C++, Python и Lisp. Исходный код на языке Nim компилируется в представление на C, C++ или JavaScript. В дальнейшем полученный C/C++ код компилируется в исполняемый файл при помощи любого доступного компилятора (clang, gcc, icc, Visual C++), что позволяет добиться производительности близкой к Си, если не учитывать затраты на выполнение сборщика мусора. По аналогии с Python в Nim в качестве разделителей блоков применяются отступы. Поддерживаются средства метапрограммирования и возможности для создания предметно-ориентированных языков (DSL).

Nim: совершенный язык программирования

Группа: Главные администраторы
Сообщений: 14349
Регистрация: 12.10.2007
Из: Twilight Zone
Пользователь №: 1

Программирование*,
Rust*
Предлагаю читателям «Хабрахабра» перевод статьи «A Quick Comparison of Nim vs. Rust». Мои замечания будут выделены курсивом.

Rust и Nim — два новых языка программирования за развитием которых я слежу. Вскоре, после моего первого поста о Rust, вышел в свет Nim 0.10.2. Это побудило меня поближе познакомиться с Nim и, естественно, сравнить его с Rust.

В этом посте я собираюсь показать вам две простых программы написанных на Nim и Rust с грубым сравнением их времени выполнения и высказать мои субъективные впечатления от программирования на этих языках.

Пример №1: Подсчёт слов (wordcount)

В этом примере используется файловый I/O, регулярные выражения, хеш-таблицы (ассоциативные массивы) и парсинг аргументов переданных команде. Как следует из названия, прогрмма подсчитывает количество слов в файлах или stdin.

Usage: wordcount [OPTIONS] [FILES]

Options:
-o:NAME set output file name
-i —ignore-case ignore case
-h —help print this help menu

Мастер Йода рекомендует:  12 бесплатных инструментов для поиска уязвимостей и вредоносных программ на сайте

Если мы передадим аргумент -i, то результат будет таким:

2 case
1 file
1 files
1 h
2 help
.

Программа на Nim достаточно проста. В ней используются tables.CountTable для подсчёта слов, parseopt2.getopt для парсинга аргументов команды и sequtils.mapIt для функциональной операции мэппинга. Для регулярных выражения я выбрал модуль pegs, который рекомендуется документацией Nim заместо re.

Деректива на строке 3 гарантирует что процедура doWork выбрасывает только исключение IOError. Для этого я поместил input.findAll(peg»w+») внутрь try выражения в строке 21 чтобы отловить исключения, которые, теоретически, могут возникнуть.

proc doWork(inFilenames: seq[string] = nil,
outFilename: string = nil,
ignoreCase: bool = false) <.raises: [IOError].>=
# Open files
var
infiles: seq[File] = @[stdin]
outfile: File = stdout
if inFilenames != nil and inFilenames.len > 0:
infiles = inFilenames.mapIt(File, (proc (filename: string): File =
if not open(result, filename):
raise newException(IOError, «Failed to open file: » & filename)
)(it))
if outFilename != nil and outFilename.len > 0 and not open(outfile, outFilename, fmWrite):
raise newException(IOError, «Failed to open file: » & outFilename)

# Parse words
var counts = initCountTable[string]()
for infile in infiles:
for line in infile.lines:
let input = if ignoreCase: line.tolower() else: line
let words = try: input.findAll(peg»w+») except: @[]
for word in words:
counts.inc(word)

# Write counts
var words = toSeq(counts.keys)
sort(words, cmp)
for word in words:
outfile.writeln(counts[word], ‘t’, word)

Для лучшего понимания Rust я реализовал простую структуру BTreeMap сродни collections::BTreeMap, но в конечном итоге я использовал collections::HashMap для справедливого сравнения с Nim (код BTreeMap остался в репозитории для ознакомления). Пакет getopts используется для парсинга аргументов команды в мою структуру Config. Далее всё должно быть понятно.

Часть кода из моего проекта Rust wordcount:


// Parse words
let mut map = collections::HashMap:: ::new();
let re = regex!(r»w+»);

Zachary Dremann предложил pull request в котором используется find_iter. Я оставил captures_iter для согласованности с Nim версией, но немного улучшил свой код.

Сравнение времени выполнения

Я скомпилировал код с флагами -d:release для Nim и —release для Rust. Для примера взял файл в 5 мегабайт составленый из исходников компилятора Nim:

$ cat c_code/3_3/*.c > /tmp/input.txt
$ wc /tmp/input.txt
217898 593776 5503592 /tmp/input.txt

Команда для запуска программы:

$ time ./wordcount -i -o:result.txt input.txt

Вот результат на моём Mac mini с процессором 2.3 GHz Intel Core i7 и памятью 8 GB: (1x = 0.88 секунды)

    В Rust regex! работает быстрее чем Regex, и r»[a-zA-Z0-9_]+» быстрее чем r»w+». Все 4 комбинации были протестированы.

Версия «debug» просто для сравнения

  • Nim работает на 1-2% медленнее с флагом —boundChecks:on, я не стал добавлять этот результат в пример.
  • Пример №2: Игра «Жизнь»

    Этот пример запускает «Жизнь» в консоле с фиксированными размером поля и шаблоном (для изменения размера или шаблона отредактируйте исходный код). В нём используется ANSI CSI код для перерисовки экрана.

    После запуска экран будет выглядеть примерно так:

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

    Вот часть кода из моего проекта Nim conway:

    type
    Cell = bool
    ConwayMap* = array[0.. = 2 and nlive Conway <
    Conway <
    map: [[false; MAP_WIDTH]; MAP_HEIGHT],
    >
    >

    pub fn init(&mut self, pattern: &[&str]) <
    let h = pattern.len();
    let h0 = (MAP_HEIGHT — h) / 2;
    for i in 0..(h) <
    let row = pattern[i];
    let w = row.len();
    let w0 = (MAP_WIDTH — w) / 2;
    for (j, c) in row.chars().enumerate() <
    self.map[i + h0][j + w0] = c == ‘1’;
    >
    >
    >

    /// Iterate to next state. Return false if the state remains unchanged.
    pub fn next(&mut self) -> bool <
    let mut newmap = [[false; MAP_WIDTH]; MAP_HEIGHT];
    for i in 0..(MAP_HEIGHT) <
    for j in 0..(MAP_WIDTH) <
    let mut nlive = 0;
    for i2 in i.saturating_sub(1)..cmp::min(i+2, MAP_HEIGHT) <
    for j2 in j.saturating_sub(1)..cmp::min(j+2, MAP_WIDTH) <
    if self.map[i2][j2] && (i2 != i || j2 != j) <
    nlive += 1;
    >
    >
    >
    newmap[i][j] = match (self.map[i][j], nlive) <
    (true, 2) | (true, 3) => true,
    (true, _) => false,
    (false, 3) => true,
    (false, _) => false,
    >;
    >
    >
    // let changed = self.map != newmap;
    let changed = true;
    self.map = newmap;
    changed
    >
    >

    В строке 49 я определил переменную для отслеживания изменения отображения, но простое сравнение self.map != newmap не работает для массивов длинной более 32 элементов, пока вы не реализуете трейт PartialEq.

    Отмечу, что я использовал небезопасный libc::exit в моём main.rs, что очень не характерно для Rust. Zachary Dremann предложил pull request в котором элегантно избегается libc::exit с использованием макроса select! и неблокирующего таймера. Возможно вы захотите посмотреть.

    Сравнение времени выполнения

    Для сравнения времени выполнения необходимо произвести некоторые изменения в коде:

      Закомментировать вызов sleep в conway.nim и

    Изменить количество итераций цикла с 300 до 3000

  • Перерисовка поля тратит много времени, поэтому произведены два замера (1) с перерисовкой и (2) без неё (т.е. с закомментированными строками вывода поля на печать в conway.nim и main.rs)
  • Вот результаты при компиляции с флагами -d:release для Nim и —release для Rust:

    (1) with map print
    1x
    1.75x
    1.87x
    1x=3.33s

    (2) without map print
    1x
    1.15x
    1.72x
    1x=0.78

    Т.к. Rust делает проверку на выход за границу списка, для справедливости я добавил колонку Nim/bc:on для Nim версии скомпилированной с флагом —boundChecks:on.

    Хоть Nim и Rust компилируемые языки с рассчётом на хорошую производительность они очень разные. Для меня их сходства заключаются в следующем:

      компилируемые и статически типизированные

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

    композиция вместо наследования (похоже на тренд в новых языках?)

    простая связка с Си

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

    Философия: свобода или дисциплина

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

    Однако есть и обратная сторона у такой свободы: могут пострадать ясность, чистота и поддерживаемость. Вот небольшой пример: в Nim import импортирует все имена модуля в ваше пространство имён. Имена из импортируемого модуля могут быть ограничены использованием синтаксиса module.symbol или использованием from module import nil для контролируемого ограничения, но, скажите мне, кто будет этим пользоваться? Тем более, что этот подход не характерен для Nim. В результате вы не сможете понять какие имена пришли из какого модуля при чтении чужого (или собственного) кода (к счастью, противоречий наименований не случается, т.к. в таких случаях Nim заствляет отделять мух от котлет).

    Ещё примеры: UFCS позволяет использовать len(x), len x, x.len() или x.len как вам вздумается; не разделяет имена с подчёркиванием и разным регистром, так mapWidth, mapwidth и map_width будут преобразованы в одно и тоже имя (я рад что они включили правило «частичной чувствительности к регистру» в версии 0.10.2, поэтому Foo и foo будут считаться различными именами); в порядке вещей является использование неинициализированных переменных. В теории, вы можете следовать строгим принципам кодирования, но при программировании в Nim вы будете чувствовать себя более раскованно.

    С другой стороны, Rust чтит дисциплину. Его компилятор очень строгий. Всё должно быть предельно ясно. Вы заранее получаете правильные подходы. Неоднозначность — это не про код на Rust…

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

    Оба имеют свои плюсы и минусы. Как программист, я больше наслаждаюсь от Nim; как майнтейнер, я бы лучше сопровождал продукты написанные на Rust.

    Визуальный стиль: Python или C++

    Как и Python, Nim использует отступы для отделения блоков кода и в нём меньше всяких знаков. Rust более похож на C++. <>, ::, <> и & будут знакомы C++ программистам, плюс Rust добавляет некоторы новые вещи вроде ‘a.

    Иногда Nim может быть слишком буквальным. Для примера, я думаю синтаксис match в Rust:

    match key.cmp(&node.key) <
    Less => return insert(&mut node.left, key, value),
    Greater => return insert(&mut node.right, key, value),
    Equal => node.value = value,
    >

    выглядит чище, чем выражение case в Nim:

    case key
    of «help», «h»: echo usageString
    of «ignore-case», «i»: ignoreCase = true
    of «o»: outFilename = val
    else: discard

    Но, в целом, код на Nim менее зашумлен. По моему мнению, особенный беспорядок в Rust вносят параметры времени жизни [i](lifetime parameters) и это уже не изменится.

    Управление памятью: Сборщик мусора против ручного управления

    Хоть Nim и позволяет небезопасное управление памятью и обеспечивает поддержку управления сборщиком мусора в рантайме для более предсказуемымого поведения. Это всё ещё язык со сборщиком мусора, который обладает всеми плюсами и минусами от него. Объектам в Nim присваиваются копии значений. Если для вашей задачи сборщик мусора не помешает, то управление памятью в Nim не будет вызывать у вас проблем.

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

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


    В зависимости от ваших требований, либо вам будет достаточно сборщика мусора Nim, либо ваш выбор падёт на Rust.

    Сильные стороны Nim:

    1. Продуктивность: в одинаковых временных рамках вы запилите больше возможностей в Nim
    2. Простота в изучении
    3. Компилируемый язык как скриптовый, хорош для протипирования, интерактивного исследования, пакетной обработки данных и т.д
    4. Фишечки:

    • переопределение методов
    • определение новых опереаторов
    • именованные аргументы и значения по-умолчанию
    • мощные макросы

    Сильные стороны Rust:

    1. Настоящий системный язык прогрммирования: встраиваемый, без сборщика мусора, близок к железу
    2. Безопасный, дисциплинирующий, надёжный
    3. Сильная команда ядра и активное сообщество
    4. Фишечки:

    • превосходная реализация сопоставления с образцом (pattern matching)
    • перечисления (enum), хотя в Nim перечисления тоже хороши
    • let mut вместо var (маленькая, но важная вещь)
    • мощный синтаксис разыменования структур

    Обработка ошибок: в Nim используется общий механизм исключений, Rust использует возвращаемый тип Result (и макрос panic!). У меня нет предпочтений в этом, но я посчитал важным упомянуть это различие.

    Релиз 1.0 на подходе

    Nim и Rust должны зарелизиться в этом году (Rust зарелизился). Это очень здорово! Rust получил уже достаточно много внимания, но и Nim становится более известным. Они очень разные на вкус, но оба великолепные новые языки программирования. Rust показывает себя с лучшей стороны в вопросах производительности и безопасности. Nim проворный (игра слов: Nim is nimble), выразительный, реализует сильные стороны скриптовых и компилируемых языков. Они оба станут отличным дополнением вашего инструментария.

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

    Вышел релиз языка программирования Nim 1.0

    Представлен релиз языка системного программирования Nim 1.0, пишет OpenNET.

    Версия 1.0 преподносится как стабильный выпуск с длительным сроком поддержки и гарантированным сохранением обратной совместимость в стабилизированной части языка. Отдельно в компиляторе доступен экспериментальный режим — в нём будут развиваться новые возможности, которые могут нарушать обратную совместимость. Некоторые API в стандартной библиотеке также пока помечены как нестабильные и будут переводиться в разряд стабильных по мере готовности. Код проекта распространяется под лицензией MIT.

    Язык Nim использует статическую типизацию и создан с оглядкой на Pascal, C++, Python и Lisp. Исходный код на языке Nim компилируется в представление на C, C++ или JavaScript. В дальнейшем полученный C/C++ код компилируется в исполняемый файл при помощи любого доступного компилятора (clang, gcc, icc, Visual C++), что позволяет добиться производительности близкой к Си, если не учитывать затраты на выполнение сборщика мусора. По аналогии с Python, в Nim в качестве разделителей блоков применяются отступы. Поддерживаются средства метапрограммирования и возможности для создания предметно-ориентированных языков (DSL).

    Реально ли создать супер-язык программирования — отвечают эксперты

    В мире так много языков. Более 7 тысяч естественных языков, например, русский, английский и пр. Языков программирования не намного меньше, под 3 тысячи. И сейчас, пока вы читаете эту статью, какой-то школьник уже кодит на своем собственном языке. Если у естественных языков есть много общего, то сходства можно найти и в языках программирования. Наш подписчик задался вопросом, которым мы хотим поделиться с вами:

    «Среди языков программирования очень много общего. Почему, используя принципы ООП, до сих пор не создан супер-язык язык программирования?»

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

    Рустам Кильдиев , руководитель отдела разработки BigData компании «Иннодата»

    Области применения языков программирования очень разнообразны: интегральные схемы, веб, системное ПО и т.п. Уникальный супер-язык это универсальность, а, как известно, универсальность ведёт к потере каких-то «фишек», что не всегда приемлемо. Кроме того, принципы ООП очень хороши, но не являются «серебряной пулей». Сейчас быстрыми темпами всё большую популярность набирает Функциональное программирование, которое отлично подходит для параллельного/конкурентного программирования, особенно в эпоху производительности, большого объёма данных и остановки роста частот, на которых работают процессоры. Сейчас целенаправленное создание супер-языка не имеет смысла из-за отсутствия целевой аудитории. На данный момент уже есть огромное количество специалистов, умеющих работать в существующих языках. Массово всем изучать, переучиваться на новый язык экономически нецелесообразно. Кроме специалистов, есть много наработок, библиотек и инструментов, которые нужно будет переписывать на новый язык, что тоже вряд ли будет хорошим решением. Сейчас просматривается плавная эволюция: одни языки сменяются другими, появляются улучшенные варианты (примеры — Java в Kotlin или Scala, JavaScript в TypeScript), делаются попытки объединить языки (прим. JavaScript и Scala в Scala.js). Приведёт ли это к созданию универсального языка (особенно ООП)? Мне кажется, что нет, но время покажет.

    Сергиус Офицеров , преподаватель HackerU

    (ответ подготовлен совместно с Михаилом Субботиным, преподавателем израильской высшей школы IT и безопасности HackerU)

    ООП — не панацея, есть еще и функциональное программирование, и process-oriented programming, и логическое программирование, и много всяких парадигм и подходов. Не будем забывать, что каждый язык программирования был создан для лучшего решения конкретной задачи. Универсальных решений нет нигде, почему они должны быть в программировании?

    Мастер Йода рекомендует:  XML-RPC на языке Python

    Виктор Ефимов , системный архитектор REG.RU

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

    Для разных людей и разных задач лучшими будут разные языки с разным функционалом, нет единого критерия. Язык C работает быстро, но не поддерживает автоматическое управление выделением и освобождением памяти, Python его поддерживает, но медленнее C++. В Go гораздо лучше многопоточность (что позволяет эффективнее писать производительные и сетевые приложения), чем в Python, но нет понятия «класса» из ООП (из-за чего сложнее быстро прототипировать или описывать бизнес-логику).

    C++ поддерживает ООП и быстро работает, однако на нём не пишут веб-сайты, на Ruby пишут веб-сайты, но не пишут firmware для роутеров.

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

    Большинство программ для Linux написано на C, хотя C++ может то же, что C, и, кроме того, лучше поддерживает ООП. Есть два одинаковых по функционалу языка — Ruby и Python, но только один выбивается в лидеры.

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

    Изъять внедрение PHP кода прямо в HTML (кстати, в своё время этот функционал считался крайне полезным, сейчас же считается очень вредным), GIL из Python, Monkey patching из Ruby (да, и определить, какие черты худшие, сложно — всё субъективно: не всем нравится, что в Go нет классических исключений). И самое главное, добавить слишком много лучших черт в один язык не получится, только выбрать некоторые из них, ибо слишком много функций — тоже плохо (пример — Perl6).

    ООП — всего лишь одна из методологий программирования, годная не для всех задач, и поддержка его языком не является основополагающим фактором, делающим язык хорошим. Для веб-программирования достаточно минимальной поддержки ООП, само ООП может пригодиться в предметной области приложения, но не всегда. Для системного программирования ООП редко нужно. Есть куча задач, для которых ООП подходит, но которые так же хорошо можно сделать и без него.

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

    Олег Власенко , заместитель генерального директора СимбирСофт

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

    Во-первых, потому что меняется техника (hardware).

    Во-вторых, потому что меняются технологии и инструменты – когда-то программисты использовали перфокарты, потом консоли, потом появились IDE, системы контроля версий и многое другое.

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

    В четвертых, потому что ИТ компании через создание языков создают свои собственные платформы, на которую «подсаживают» весь мир. (Sun, а позже Oracle – платформа на Java, Microsoft – платформа на C#) Есть еще в пятых, в шестых и т.д.

    Это все заставляет языки программирования плодиться и размножаться, а не только изменяться и исчезать. И хотя последние 30 лет ООП – господствующая методология, но существует множество компьютерных языков, в которых изначально заложена другая методология. Например, с одной стороны это старые добрые ассемблер и Си, а с другой стороны вполне современные HTML, SQL, Erlang и тысячи других. ООП так или иначе оставляет свой след в современных языках, но даже в сравнительно близких языках (например Java и C#) ООП реализован по разному.

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

    Александр Пряхин , декан факультета веб-разработки GeekUniversity, онлайн-университет Mail.Ru Group

    В замечательной книге Дугласа Адамса «Автостопом по Вселенной» есть прекрасный эпизод, в котором огромный компьютер в течение семи с половиной миллионов лет вычислений искал ответ на «главный вопрос жизни, Вселенной и всего такого».
    В результате он выдал ответ «42». Но, как сказал сам компьютер: «Мне кажется, если уж быть с вами абсолютно честным, то всё дело в том, что вы сами не знали, в чём вопрос».

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

    В существующем мире IT языки программирования — это инструменты, каждый из которых призван решать свою задачу. Так, множество Enterprise систем пишутся на Java, который зарекомендовал себя именно отточенностью на этот слой приложения.
    Актуальные в мире Highload микросервисы отлично пишутся на Go и том же Java, потому что вновь эти инструменты оказываются удобными для создания подобного рода вещей. Порядка 80% сайтов используют PHP, который так любит погонять сообщество. И это тоже неспроста — это говорит о пригодности инструмента. А пригодность складывается не только из того, насколько хитроумную абстракцию Вы сможете написать на нём, а ещё и на экономической составляющей.

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

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

    Егор Болгов , Fullstack Developer, SEMrush

    Честно говоря, для меня это два различных вопроса: «Почему не создан супер-язык программирования?» и«Почему не все языки программирования объектно-ориентированы?»

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

    Отвечая на первый вопрос в целом, становится ясен ответ и на второй — для некоторых задач объектно-ориентированное программирование является бессмысленным усложнением, например, надо сформировать программу для робота по выполнению нескольких фиксированных операций: передвинуть, закрыть манипулятор, передвинуть, открыть манипулятор. В данной ситуации совершенно нет необходимости описывать объекты, операции над ними и т.д.

    Андрей Борю , преподаватель образовательного курса «Профессия «Веб-разработчик»» университета digital-профессий «Нетология»

    Позволю себе перефразировать вопрос: «Почему до сих пор существует так много языков программирования, а не один универсальный?» Сегодня в мире существует более 30 различных языков программирования. И почти все из них появились для решения конкретных задач и лишь впоследствии эволюционировали до своих полноценных версий. К примеру, всем известный php изначально был просто шаблонизатором, а одной из целей создания современного golang было решение реальных проблем, возникающих при разработке программного обеспечения в Google.

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

    Евгений Картавец , руководитель отдела обучения GeekBrains, Mail.Ru Group

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

    Есть несколько причин того, что многообразие языков сохранилось, и все не переехали дружно на какой-нибудь Python. Некоторые языки уже прочно заняли свою нишу. У каждого языка есть сильные и слабые стороны, для одних задач он подходит лучше, для других хуже. Кроме того, язык часто обрастает инфраструктурой — фреймворками и т.д., удобных аналогов для которых может не быть в других языках.

    Екатерина Кошкарова , ведущий специалист департамента информационных решений компании РДТЕХ

    Смотря что подразумевать под супер-языком программирования. Если мы говорим о языке, на котором нужно реализовать искусственный интеллект, то почему за основу следует брать именно ООП? У объектно-ориентированных языков есть свои недостатки, такие как избыточность, сложность проектирования, относительная неэффективность. Безусловно, у ООП есть и свои плюсы: повторное использование компонент, задействование библиотек… Но, может, для супер-языка возьмем что-нибудь более гибкое? ��

    Игорь Шеко , Front End Developer, Voximplant

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

    Еще одна проблема кроется в самом понятии ООП: с момента появления этого термина мы спорим, что именно он означает. Есть активные сторонники как Smalltalk подхода, так и более поздних идей, появившихся в C++. Кроме того, сейчас сложно найти язык с чистым ООП. Взять хотя бы TypeScript — он поддерживает и ООП, и функциональное программирование, и событийно-ориентированное, и еще несколько парадигм программирования. Такие языки называются мультипарадигмальными, и сейчас их расцвет.

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

    Ян Орещенков , технический директор бельгийско-белорусской IT компании CactusSoft

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

    Микаэл Караманянц , директор компании-разработчика мобильных приложений Рашенсофт

    Есть несколько причин.

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

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

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

    Новая версия языка программирования Nim 0.18.0

    Представлен значительный релиз языка системного программирования Nim 0.18.0. Язык использует статическую типизацию и создан с оглядкой на Pascal, C++, Python и Lisp. Код проекта поставляется под лицензией MIT.

    Исходный код на языке Nim компилируется в представление на C, C++ или JavaScript. В дальнейшем полученный C/C++ код компилируется в исполняемый файл при помощи любого доступного компилятора (clang, gcc, icc, Visual C++), что позволяет добиться производительности близкой к Си, если не учитывать затраты на выполнение сборщика мусора. По аналогии с Python в Nim в качестве разделителей блоков применяются отступы. Регистр написания символов в идентификаторах не учитывается. Поддерживаются средства метапрограммирования и возможности для создания предметно-ориентированных языков (DSL).

    В новом выпуске отмечается ряд существенных новшеств и изменений, связанных с проведением чистки стандартной библиотеки перед релизом 1.0. Также внесена большая порция изменений, нарушающих обратную совместимость. Оператор индексирования «[]» теперь выдаёт ошибку, если запрошенный диапазон выходит за границы строки, вместо выдачи подпадающий под запрос части строки (например, var myString = «hello world»; myString[6 .. 45] теперь инициирует исключение IndexError). Также изменена логика обработки коллекций оператором «$» и прекращено приведение массивов array[x, char] к типу cstring. Спецсимвол «\n» теперь выводит только код перевода строки без кода возврата каретки.

    • Добавлен модуль strformat, предоставляющий поддержку форматируемых строковых литералов, позволяющих определить строку, содержащую подстановки (например let name = «Fred»; doAssert fmt»My name is .»), в стиле «f»-строк Python 3.6;
    • В генератор документации добавлен макрос runnableExamples, позволяющий протестировать работу приводимых примеров кода;
    • Добавлен новый макрос mapLiterals, упрощающий создание массивов и последовательностей (например, «let x = mapLiterals([12, 34, 15, 1], uint32)»);
    • Изменён алгоритм управления памятью. Новый алгоритм TLSF позволяет снизить фрагментацию памяти, ценой усложнения операций alloc и dealloc;
    • Серия изменений в модулях для асинхронного ввода/вывода. Представлена унифицированная реализация asyncdispatch и новая процедура getIoHandler, возвращающая дескриптор ввода/вывода или epoll/kqueue. В модуле asyncjs появилась новая реализация async await для бэкенда JavaScript;
    • Пакетный менеджер Nimble обновлён до версии 0.8.10, в которой появилась возможность размещения нескольких пакетов Nimble в одном репозитории Git или Hg;
    • Из stdlib в обособленные пакеты Nimble переведены библиотеки gentabs, libuv, polynumeric, pdcurses, romans, libsvm и joyent_http_parser. Объявлены устаревшими basic2d и basic3d, вместо которых следует использовать такие пакеты, как glm, arraymancer и neo.
    Добавить комментарий