Главное меню
Мы солидарны с Украиной. Узнайте здесь, как можно поддержать Украину.

Nim (вроде)

Автор Vertaler, декабря 28, 2020, 06:38

0 Пользователи и 1 гость просматривают эту тему.

Vertaler

Стрч прст в крк и вынь сухим.

Vertaler

Как вы думаете, в каких случаях питон всё же лучше нима?

Подозреваю, что в ООП. (На этом месте можно ржать.) В ниме есть структуры и наследование структур. Функции в структуры не входят, зато они строго типизированы и определяются над структурами. Единственное, что есть слово method, которым определяется такая функция, которая будет работать не только с объектом нужного класса, но и с объектами его подклассов.

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

class A:
   def f(self, n):
      return n * 2
x = A()
print(list(map(x.f, [1,2,3])))


превращается в вот такой хитровыломанный код на ниме:

import sequtils, sugar

type A = ref object of RootObj
method f(this: A, n: int64): int64 {.base.} = n * 2

var x = A()
echo map(@[1,2,3], n => x.f(n))

Стрч прст в крк и вынь сухим.

wandrien


Vertaler

Цитата: wandrien от декабря 28, 2020, 07:33
А кто здесь вообще знает этот язык?)
Думаю, никто. Другой вопрос, что на русском языке про него почти ничего нет, так что почему бы и не.
Стрч прст в крк и вынь сухим.

Vertaler

Допустим, вы знаете, что срок годности чего-нибудь (бананов на полке или банковского вклада) составляет ровно 80 часов (или, к примеру, 99 дней). Или планируете отпуск. Или считаете, на сколько дней вам хватит нынешних рулонов туалетной бумаги. Или ещё что-нибудь.

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

nim> import times
nim> echo now()
2020-12-28T16:53:05+02:00
nim> echo now() + 80.hours
2021-01-01T00:53:12+02:00
nim> echo now() + 99.days
2021-04-06T16:53:17+03:00

Стрч прст в крк и вынь сухим.

wandrien


Vertaler

Цитата: wandrien от декабря 28, 2020, 17:08
Уперли из RoR?

https://api.rubyonrails.org/classes/Numeric.html
Какая красота! И в Руби это реальные методы интеджеров или там нет такого понятия?
Стрч прст в крк и вынь сухим.

wandrien

Цитата: Vertaler от декабря 28, 2020, 17:10
И в Руби это реальные методы интеджеров или там нет такого понятия?
В Руби:
1. Всё есть класс.
2. Класс можно дополнять как угодно (подмешивать новые методы).

Так RoR в класс чисел и внедряется.

oort

Цитата: Vertaler от декабря 28, 2020, 06:39
Как вы думаете, в каких случаях питон всё же лучше нима?

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

Vertaler

Цитата: oort от декабря 28, 2020, 20:49
Цитата: Vertaler от декабря 28, 2020, 06:39
Как вы думаете, в каких случаях питон всё же лучше нима?

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

Впрочем, импорты в питоне тоже иногда бывают... странными. Например, если в одном проекте одновременно tf и pytorch, порядок импортов важен. Во фласке тоже хитрости надо знать. А какое-нибудь from __future__ import annotations обязано висеть выше всех импортов, хотя не очень понятно зачем/почему.
Стрч прст в крк и вынь сухим.

oort

Гм. В питоне с этим не сталкивался уже я, но там это хотя бы ожидаемо. А ним, если те полтора человека, что им занимаются всерьез, таки его когда-нибудь допилят (во что верится, честно говоря, слабо), вероятно, будет иметь смысл сравнивать не с питоном, а с каким нибудь d или может быть даже rust. С питоном из компилируемых языков можно сравнивать разве что go (если питона посадить на mypy:).

Vertaler

Но можно ли всё-таки поместить функцию в Ниме внутрь структуры, если нам говорят, что функции в структуры не входят? Да, можем, если поместить саму функцию в список, а список в структуру.

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

proc f(n: int64): int64 {.nimcall.} = n * 2 # наш будущий метод
var fl = @[f] # помещаем метод в список

type A = ref object of RootObj # создаём простой класс
    ff*: seq[proc (n: int64): int64{.nimcall.}]
# и теперь всё, что этот класс может содержать, — это функции!

var x = A(ff: fl) # создали экземпляр класса
echo x.ff[0](11) # и вызвали "метод"


Печатает, разумеется, число 22.

Если ещё я смогу откопать возможность создания унарного правого оператора (пока знаю только о левых), да ещё из одного символа (что тоже не факт что возможно), чтобы каждый раз не писать
  • [/b], то мы приблизимся к ООП на Ниме уже вплотную.
Стрч прст в крк и вынь сухим.

Vertaler

Таки да, правых операторов в Ниме намеренно не предусмотрено, кроме одного (звёздочки).

:(
Стрч прст в крк и вынь сухим.

Vertaler

Подправил вчерашний код. Убрал лишнее, заменил seq на array фиксированной длины 1.

А потом выяснил, что класть функции в структуры таки МОЖНО (фактически питоновские статикметоды получаются). За каким дедом макаром тогда в мануале написано, что нельзя?..

proc f(n: int64): int64 {.nimcall.} = n * 2

type A = object
    ff*: array[1, proc (n: int64): int64 {.nimcall.}]

type B = object
    ff: proc(n: int64): int64 {.nimcall.}

var x = A(ff: [f])
echo x.ff[0](11)

var y = B(ff: f)
echo y.ff(12)
Печатает:
22
24


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

from sugar import `=>`
var z = B(ff: q => q * 2)

A nested proc can have generic parameters only when it is used as an operand to another routine and the types of the generic paramers can be inferred from the expected signature.


Зато так можно:

var z = B(ff: proc(q: int64): int64 {.nimcall.} = q * 2)
echo z.ff(13)
Печатает: 26
Стрч прст в крк и вынь сухим.

Vertaler

Разобрался ещё чуть-чуть. В принципе можно писать красивый лаконичный сахарный код. Занятно, конечно, что в Ниме при этом разные операторы для непосредственно лямбд и для "мест, куда будут подставлять лямбду".

from sugar import `->`, `=>`

type B = object
    f: (int) -> int

var b = B(f: (a:int) => a*2)
Портит этот кусок кода эстетически всего одна вещь: при создании экземпляра класса все аргументы передаются по именам, без этого вот ваще никак. Но в традиции использования языка входит создание отдельных функций вида initB(), и им уже можно передавать аргументы и просто так. Ну и значения по умолчанию у них тоже могут быть.
Стрч прст в крк и вынь сухим.

Vertaler

Цитата: Vertaler от декабря 28, 2020, 16:53
Ним в этом случае понимает речь человеческую.
Запишу также код для вычисления промежутка между сегодняшним днём и какой-то ещё датой.

import times; echo now() - initDateTime(1, mDec, 2020, 0, 0, 0)
Выдача: 7 weeks, 1 day, 19 hours, 49 minutes, 4 seconds, 769 milliseconds, 724 microseconds, and 891 nanoseconds

Обнаруженные проблемы:

1. Отсутствует функция today()
2. initDateTime() принимает 6 аргументов и ни аргументом меньше, несмотря на возможность дефолтных аргументов в Ниме
3. Интервал по дефолту выплёвывается (отображается) В НЕДЕЛЯХ, а не в днях. Для дней есть функция inDays()

Впрочем, 1 и 2 легко исправляются написанием кастомной функции в одну строчку, да и для 3 можно попробовать написать свой оператор, к примеру, *- и *+ (а заодно и свой тип данных?.. хотя тогда уже операторы не нужны). Но всё же хм.

Из фич, которые не хорошие и не плохие:

1. День впереди месяца, месяц впереди года (в питоне и джс не так!)
2. Месяц писать в формате mDec, mJan и т. д., эти переменные уже импортированы вместе с модулем times

Из хороших фич:

1. Не нужно писать datetime кучу раз, как в питоне
2. Не нужно делить результат на 86400 или ещё какое число, как в джаваскрипте,
3. Не нужно помнить, что декабрь -- 11-й месяц при счёте с нуля, как в джаваскрипте,
4. Не нужно помнить, что 12-й месяц -- это вообще по молчаливому хотению компилятора/интерпретатора январь следующего года, как опять же в джаваскрипте
Стрч прст в крк и вынь сухим.

Быстрый ответ

Обратите внимание: данное сообщение не будет отображаться, пока модератор не одобрит его.

Имя:
Имейл:
Проверка:
Оставьте это поле пустым:
Наберите символы, которые изображены на картинке
Прослушать / Запросить другое изображение

Наберите символы, которые изображены на картинке:

√36:
ALT+S — отправить
ALT+P — предварительный просмотр