LINUX.ORG.RU

Nim lang

 ,


0

4

Народ, кто-нибудь балуется Nim-ом? Надо популяризировать язык, скоро уже 1-я версия выйдет. А то что все про Rust :-)

Я тут just for fun, решил реализовать упражнения из «Functional programming in Scala» на Nim-е: https://github.com/vegansk/nimtests/tree/master/fpinnim. Язык пока справляется, хотя баг репорты бывают и пишутся. Надеюсь, в дальнейшем это перерастет в написание функциональной версии stdlib-а для него. А язык ох как хорош. Тут тебе и отсутствие требования наличия vm, в отличии от Scala, и нормального размера бинарники, в отличии от Haskell, и для JS бэкэнд пишется. И ffi не только с сями, но и с плюсами. В общем компилируемый, мультипарадигменный, опциональный GC, имеет effect system, macroprogramming, etc. А в devel сейчас еще и кроссплатформенное скриптование на нем добавили.



Последнее исправление: vega (всего исправлений: 1)

Ответ на: комментарий от vega

Скажи, пожалуйств, что не так в этом коде?

import math

var a: array[1..5, char]

for i in low(a)..high(a):
  a[i] = char(random 10)
  echo(a[i])
И как вообще скастовать число в символ?

Deleted
()
Ответ на: комментарий от Deleted

Скажи, пожалуйств, что не так в этом коде?

Коды символов в промежутке [0;10)

import math

var a: array[1..5, char]

for i in low(a)..high(a):
  a[i] = ('A'.int + 10.random).char
  echo(a[i])
vega
() автор топика
Последнее исправление: vega (всего исправлений: 1)
Ответ на: комментарий от Deleted

Хуже.

Пруф какой-нибудь будет? А то сказать я тоже что угодно могу.

Как по мне, то из «ужасных спецсимволов» в расте только лайфтаймы. При этом местами наоборот лучше чем в плюсах так как нет rvalue reference/universal references. Плюс лямбды более аккуратные, да и много других мелочей.

С дженериками тоже плюс/минус так же - нет костыпей в виде typename в «сложных местах». Зато «многословнее» из-за того, что явно ограничения прописывать надо, но этого в плюсах просто нет, ну и внятные сообщения об ошибках того стоят. А вот как концепты появятся, то мы ещё посмотрим где хуже будет.

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

Ну и ловко ты на паскали с питонами съехал.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Но таки вырывается вперед за счет '.

Лайфтаймы - да, такого в плюсах нет. Зато есть rvalue reference/universal references и лямбды страшнее. Так что, по прежнему считаю, что на одном уровне.

DarkEld3r ★★★★★
()

Кстати, для всех убоявшихся strong spaces, создатель языка по этому поводу отписался:

;-) well fear not, I won't make it the default and I might even remove the feature completely

vega
() автор топика
Ответ на: комментарий от DarkEld3r

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

В этом плане в Nim есть templates (http://nim-lang.org/docs/manual.html#templates), которые практически один в один подставляются, а для макросов есть quasi quotes (http://nim-lang.org/docs/macros.html#quote,stmt,string), чтобы не генерировать AST вручную

vega
() автор топика
Ответ на: комментарий от Manhunt

то как насчет mbeddr?

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

А отказ от совместимости позволяет больше всего интересного сделать.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Deleted

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

Ну вот для меня синтаксис важен, хотя, пожалуй, и не важнее всего остального. Но в расте мне не нравятся (в плане синтаксиса) только макросы. Они и правда уродские. В остальном всё весьма неплохо.

Да, лайфраймы «замусоривают» код, но они дают новые возможности, так что оно того стоит. Тем более, что не так уж они ужасны и не везде нужны.

DarkEld3r ★★★★★
()
Ответ на: комментарий от vega

Где он стандартный?

А разве нет? Я вижу, что отступы именно в два пробела, ну и «сложные выражения» выравниваются на одном уровне. Вот рандомный код по ссылке:

proc callProc[T](p: proc (x: T), x: T) =
  when T is void:
    p()
  else:
    p(x)

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Я вижу, в этом треде все таки есть красная тряпка :-) Определение стандарта можно услышать? Я уже похоже лет 5 стандартами Nim-а пользуюсь, правда вот с самим языком знаком несколько месяцев.

Короче, вот например: https://github.com/szahn/NimrodLangTutorials/blob/master/switch_case/switch_c...

vega
() автор топика
Последнее исправление: vega (всего исправлений: 1)
Ответ на: комментарий от vega

В этом плане в Nim есть templates

Да, я бегло смотрел. Выводы делать не стал - недостаточно вник.

Растовые макросы, как уже говорил, мне не нравятся.

DarkEld3r ★★★★★
()
Ответ на: комментарий от vega

Определение стандарта можно услышать?

Ок, мы друг друга не поняли. Я не собирался утверждать, что в «стандарте Nim» (его ведь и нет?) это прописано. Просто если на официальном сайте и в стандартной библиотеке используется именно такой стиль, то это довольно близко к «стандарту».

Кстати, для Nim есть тулза для автоформатирования? Из коробки, в смысле. Если есть, то она что-то с отступами делает?

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Кстати, для Nim есть тулза для автоформатирования? Из коробки, в смысле. Если есть, то она что-то с отступами делает?

Нет, есть вот это, но пользовать нельзя. AST содержит только комментарии для документации, а обычные коменты эта штука убивает: https://github.com/def-/nimfmt/blob/master/nimfmt.nim

vega
() автор топика
Последнее исправление: vega (всего исправлений: 1)
Ответ на: комментарий от DarkEld3r

Зато есть rvalue reference/universal references

Ок, тогда добавим, что в rust есть ! для макросов.

лямбды страшнее.

В С++ лямбды абсолютно точно те же функции по синтаксису + мы явно указываем, что и как захватываем внутрь. Вся разница в []. В rust же вместо [] добавили ||, т.е. по спецсимволам разницы нет. Но при том в С++ [] несет смысловую нагрузку и позволяет делать то, что в rust нельзя. Кроме того в С++ все лямбды выглядят одинаково, а в rust как бог на душу положит. Не считая того, что в rust они добавляют головной боли:

fn make_adder(a: i32) -> Box<Fn(i32) -> i32> {
    Box::new(move |b| a + b)
}

fn main() {
    println!("{}", make_adder(1)(2));
}
auto make_adder( int a ) {
    return [a]( int b ) { return a + b; };
}

int main() {
    printf( "%d\n", make_adder(1)(2) );
}

Ту вариант С++ возвращает результат на стеке, а описание замыкания точно такое же как и у обычной функции. Вариант на rust сам за себя говорит.

anonymous
()
Ответ на: комментарий от vega

Нет, есть вот это, но пользовать нельзя.

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

DarkEld3r ★★★★★
()
Ответ на: комментарий от tailgunner

okay.

Стоит немного усложнить и разницы практически нет:

|b: &mut Z| -> F { ... }
[a]( Z& b ) -> F { return ...; }

Хотя если писать только код для a + b, то да - rust рулит.

anonymous
()
Ответ на: комментарий от DarkEld3r

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

Это единственное из Go, от чего у меня остались теплые воспоминания :-)

vega
() автор топика
Ответ на: комментарий от anonymous

Стоит немного усложнить и разницы практически нет

Разница всё же есть, и не в пользу Си++. И, возможно, type inference позволит сократить вариант для Rust.

Хотя если писать только код для a + b, то да - rust рулит.

Ну то есть даже ты согласен, что простые вещи в Rust выглядят проще.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Ок, тогда добавим, что в rust есть ! для макросов.

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

Вся разница в []. В rust же вместо [] добавили ||, т.е. по спецсимволам разницы нет.

Это не так. В расте || - это список параметров лямбды, а не перечисление того, что захватывать.

и позволяет делать то, что в rust нельзя.

Давай на конкретном примере.

Кроме того в С++ все лямбды выглядят одинаково

Правда что ли? И опциональное указание возвращаемого типа тебя не смущает? А сокращённая форма записи?

[ capture ] ( params ) mutable exception attribute -> ret { body } 	(1) 	
[ capture ] ( params ) -> ret { body } 	(2) 	
[ capture ] ( params )        { body } 	(3) 	
[ capture ]                   { body } 	(4) 	
Одинаково, да.

Ту вариант С++ возвращает результат на стеке, а описание замыкания точно такое же как и у обычной функции. Вариант на rust сам за себя говорит.

Не понял сути претензий.

DarkEld3r ★★★★★
()
Ответ на: комментарий от tailgunner

Разница всё же есть, и не в пользу Си++.

Есть.

И, возможно, type inference позволит сократить вариант для Rust.

В С++ тоже.

Ну то есть даже ты согласен, что простые вещи в Rust выглядят проще.

Зато сложные - сложнее. А это гораздо хуже.

anonymous
()
Ответ на: комментарий от DarkEld3r

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

Речь шла про спецсимволы. Никто не делает из этого проблемы.

Это не так. В расте || - это список параметров лямбды, а не перечисление того, что захватывать.

Спасибо, кэп, напоминаю «речь шла про спецсимволы».

Давай на конкретном примере.

[&b,c=v,d]

Правда что ли? И опциональное указание возвращаемого типа тебя не смущает? А сокращённая форма записи?

[] - начало, {} - конец. Опиши теперь в rust.

Не понял сути претензий.

Ты не видишь лишних усилий и оверхедов в коде на rust?

anonymous
()
Ответ на: комментарий от anonymous

Кстати насчет оверхеда, низкоуровневых ЯП и лямбд:

atexit( []{ printf("Bye!\n"); } );

Rust так умеет? А если нет - сколько усилий надо для того, что бы не написать a + b, а прикрутить хендлер для общения с libpng например?

anonymous
()
Ответ на: комментарий от anonymous

Речь шла про спецсимволы. Никто не делает из этого проблемы.

Речь шла про замусоривающие код спецсимволы.

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

Спасибо, кэп, напоминаю «речь шла про спецсимволы».

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

[] - начало, {} - конец. Опиши теперь в rust.

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

[&b,c=v,d]

И чем это полезно? Хотелось бы более практичный пример.

Ты не видишь лишних усилий и оверхедов в коде на rust?

Ну в расте возвращается не замыкание, так что на плюсах это будет std::function. То, что иначе нельзя - это да, неприятно.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Rust так умеет?

Умеет:

std::rt::at_exit(|| println!("Bye!"));

а прикрутить хендлер для общения с libpng например?

Вопрос вообще о чём? О том, что язык не совместим с С и надо писать биндинги?

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Речь шла про замусоривающие код спецсимволы.

println! вместо println - это замусоривание кода.

И в С или плюсах тут наоборот изобретают соглашения типа «макросы в верхнем регистре» и т.д.

В С и плюсах макросы слишком примитивны и далеки от языка (они вообще в препроцессоре). Только потому на них и делают упор.

И чем это полезно? Хотелось бы более практичный пример.

auto collector( const string& start ) {
    return [s=start]( char c ) mutable { return s+=c; };
}
anonymous
()
Ответ на: комментарий от DarkEld3r

Умеет:

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

Вопрос вообще о чём? О том, что язык не совместим с С и надо писать биндинги?

О том как именно надо писать биндинги и есть ли там место лямбдам.

anonymous
()
Ответ на: комментарий от anonymous
auto collector( const string& start ) {
    return [s=start]( char c ) mutable { return s+=c; };
}

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

anonymous
()
Ответ на: комментарий от DarkEld3r

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

Ровно как и для обычной функции. Ничего нового.

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

А в «простых» на несколько строк не будут. А еще там есть move, например, которые удаляли-удаляли, да выудаляли.

anonymous
()
Ответ на: комментарий от anonymous

println! вместо println - это замусоривание кода.

Нет, это дополнительная информация.

Можно спорить о том нужна она или нет, но опыт показывает, что в С/С++ для макросов эту информацию тоже стараются донести. Разница только в том, что гарантий нет.

и далеки от языка (они вообще в препроцессоре)

Ну в расте они тоже фактически другой язык. И тоже на них действуют другие правила.

Относительно кода - да, это может быть удобно, но не кажется мне сильно важным.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

И, возможно, type inference позволит сократить вариант для Rust.

В С++ тоже.

В примере Си++ ты его уже использовал.

auto make_adder( int a ) {

Ну то есть даже ты согласен, что простые вещи в Rust выглядят проще.

Зато сложные - сложнее. А это гораздо хуже.

Пример можно?

tailgunner ★★★★★
()
Ответ на: комментарий от DarkEld3r

Нет, это дополнительная информация.

Окай.

но опыт показывает, что в С/С++ для макросов эту информацию тоже стараются донести.

В С/C++ на макросах даже min/max не выпишешь. Потому и надо кричать громко, что смотри внимательно, бл%дь, тут мины. В языках с нормальными макросами такой проблемы нет.

anonymous
()
Ответ на: комментарий от tailgunner

В примере Си++ ты его уже использовал.

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

Пример можно?

Был уже, с возвратом лямбды.

anonymous
()
Ответ на: комментарий от anonymous

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

Можно.

О том как именно надо писать биндинги и есть ли там место лямбдам.

https://doc.rust-lang.org/stable/book/ffi.html

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Ровно как и для обычной функции. Ничего нового.

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

А в «простых» на несколько строк не будут.

Покажи пример что ли.

А еще там есть move, например, которые удаляли-удаляли, да выудаляли.

И зачем их удалять?

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

В языках с нормальными макросами такой проблемы нет.

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

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

Плюс повёрнутость многих на «явности/очевидности».

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

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

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

Покажи пример что ли.

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

И зачем их удалять?

https://github.com/rust-lang/rust/issues/3676

anonymous
()
Ответ на: комментарий от tailgunner

Это? Си++ немного выиграл за счет auto в определении функции.

Добавь еще Box.

anonymous
()
Ответ на: комментарий от DarkEld3r

Затем, что я плохо представляю случаи, когда это станет проблемой в плане читаемости.

set_callback( action_id, |&mut x: &'a [T], y: &'a i32| <Rc<Answer> as Clone>::clone(&rc_answer).do_something() +
    match x { 1 => 2, 2 => 3, ... _ => ... } +
    ..., hello, type )

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

anonymous
()
Ответ на: комментарий от anonymous

Можно конечно сказать - форматируй и все будет ок.

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

ovk48 ★★★
()
Ответ на: комментарий от anonymous

Можно конечно сказать - форматируй и все будет ок. Ну или не делай так.

Дык и в С++ так можно. А ещё можно, если доводить до абсурда, пробелов столько вставить, чтобы выражение за экран уехало.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Дык и в С++ так можно

Там по открывающей скобке всегда можно быстро найти закрывающую.

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

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

anonymous
()
Ответ на: комментарий от anonymous

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

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

anonymous
()
Ответ на: комментарий от anonymous

Там по открывающей скобке всегда можно быстро найти закрывающую.

Про помощи IDE/редактора - да. Но что это даст? Для понимания всё равно придётся всю строку разбирать.

а тупо выписать длинное выражение может любой не особо старательный кодер

Поэтому вещи типа gofmt и нужны.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Пруф какой-нибудь будет?

Всё что было в это треде на расте этому пруф. На c++ выражение может быть длиннее и менее заспецсимволировано, а на расте снова смесь "!№:?%:* даже там, где без них можно обойтись. Если не приводить в пример примитивные выражения.

паскали с питонами

А что ты думал я в пример поставлю? c++, befunge, malbolge? Как думаешь, почему в раст-команде нет своего Гвидо, или Вирта? Или как в команде nim'a нет такого человека? У меня есть ответ, и я хотел бы услышать твой.

Deleted
()
Ответ на: комментарий от DarkEld3r

И с++ и rust страдают от читабельности. Давай не сравнивать двух калек, т.к. неконструктивно думать в терминах «у кого менее худо».

Deleted
()
Ответ на: комментарий от Deleted

Всё что было в это треде на расте этому пруф.

Ну то есть показать тебе нечего.

а на расте снова смесь "!№:?%:* даже там, где без них можно обойтись

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

Между прочим, я указал на «проблемные» моменты в расте вместе с какими-никакими причинами. От тебя же конструктивного ничего не было.

А что ты думал я в пример поставлю?

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

Как думаешь, почему в раст-команде нет своего Гвидо, или Вирта?

Если честно, то мысль не понял.

DarkEld3r ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.