Comments 41
Анимации реализованы? Т.е. посимвольное «движение».
0
Получил странную ошибку при запуске
field.nim(15, 14) Error: undeclared identifier: '..<'
+1
Спасибо за статью, сам недавно увлёкся «Нимом», развлечения ради сделал крестики-нолики на SDL, а вот с ООП как-то запутался. Теперь вроде разобрался :)
Отправил вам пулл-реквест «Good buy» > «Good bye» :) Радикальный способ исправлять орфографические ошибки!
Отправил вам пулл-реквест «Good buy» > «Good bye» :) Радикальный способ исправлять орфографические ошибки!
+2
Почти все нравится в Ниме, пробовали даже тут писать какие-то системные утилитки на нем, но отсутствие поддержки gzip (и даже сторонних модулей) неприятно удивило. Писать модуль с нуля времени не было, поэтому вернулись обратно на Python.
0
Так в нем же поддержка С-библиотек буквально из коробки. Просто портируете h-шник и вперед.
+1
Представьте, что человек последний раз программировал на C в школе. Возможно это и быстро, но нужно же разбираться во всем этом. Кстати, если это так быстро и просто — тем более вызывает удивление, что в стандартную библиотеку не была включена поддержка gzip.
-3
В Си нету пакетов. От слова «совсем». Потому что невозможно создать такую библиотеку, которая удовлетворяла бы параметрам: работать на любом железе, работать быстро, работать эффективно. А от Си именно это и требуется. Поэтому все библиотеки разрабатываются отдельно. Тот же gzip будет одним под десктоп (максимальное быстродействие), другим под мобильную платформу (минимальное потребление процессора) и третьим — под микроконтроллер (минимальное потребление памяти).
0
Мне кажется, сломанный getch() и необходимость использовать костыль в виде питона для запуска простейшей консольной утилиты — самое полезное, что можно было вынести о Nim из статьи.
+2
> of cmdExit:
echo «Good buy!»
Хорошая покупка! :)
echo «Good buy!»
Хорошая покупка! :)
+2
А для nim есть какой либо пакетный менеджер?
0
UFO just landed and posted this here
Так есть же ООП. Или без ключевого слова class ощущения не те?
0
UFO just landed and posted this here
А в каком месте статьи Вам показалось, что написано про синглтоны? Каждый вызов newGame и initGame из раздела про создание объектов создает новую переменную типа Game или GameObj.
0
Тута скорее ООП в стиле перла и Лиспа в духе: «хотите привычный ООП с классами и прочим cpp-каргокультом? На здоровье, язык это не запрещает»
0
UFO just landed and posted this here
Тут зависит от того, что Вы понимаете под классическим ООП.
Если наследование, инкапсуляцию, полиморфизм, то оно как учение Маркса, всесильно, потому что оно верно.
Если же «классы, конструкторы, деструкторы, private/protected/public + прочая калька с cpp/java/любойДругойДиалект» — то на мой взгляд с тех, когда это скопипастили из C++ в java
Если наследование, инкапсуляцию, полиморфизм, то оно как учение Маркса, всесильно, потому что оно верно.
Если же «классы, конструкторы, деструкторы, private/protected/public + прочая калька с cpp/java/любойДругойДиалект» — то на мой взгляд с тех, когда это скопипастили из C++ в java
+1
UFO just landed and posted this here
OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. © Alan Kay
Наследование — это лишь один из способов реализации [позднего связывания]. Полиморфизм вообще не понятно к чему из перечисленного Аланом относится.
Наследование — это лишь один из способов реализации [позднего связывания]. Полиморфизм вообще не понятно к чему из перечисленного Аланом относится.
+2
Читал документацию Nim — не нашел там интерфейсов или абстрактных классов и т.п. только наследование — как там предлагают реализовывать что-то работающее с абстракцией — только через одну ветку наследования и принятия объекта базового класса как параметра?
Т.е. как сделать что-то вроде этого:
Т.е. как сделать что-то вроде этого:
package main
type MyType struct {
A int
B int
}
func (v MyType) Val() int {
return v.A + v.B
}
type MyType2 struct {
V int
}
func (v MyType2) Val() int {
return v.V
}
type HaveVal interface {
Val() int
}
func PrintVal(v HaveVal){
println(v.Val())
}
func main(){
a := MyType{A:1, B:2}
b := MyType2{V:5}
PrintVal(a)
PrintVal(b)
}
+1
Хороший вопрос! Тоже люблю такие штуки в коде. К сожалению мои 300 строк на Nim не заставили меня столкнуться с такой необходимостью. Может быть зададите его на StackOverflow?
0
Пока спал, придумал вот что: можно решить эту проблему с помощью generic'ов:
Таким образом, ошибка будет поймана на этапе компиляции, что, собсно, и требовалось.
type
T1 = object
foo: string
T2 = object
bar: string
T3 = object
baz: string
method foobar(self: T1) =
echo self.foo
method foobar(self: T2) =
echo self.bar
proc foobarCaller[T](self: T) =
self.foobar()
var t1 = T1(foo: "T1")
var t2 = T2(bar: "T2")
var t3 = T3(baz: "T3")
foobar(t1) # компилируется, результат "T1"
foobar(t2) # компилируется, результат "T2"
foobar(t3) # не компилируется (!) Error: type mismatch: got (T3)
# but expected one of:
# interface_test.foobar(self: T2)
# interface_test.foobar(self: T1)
Таким образом, ошибка будет поймана на этапе компиляции, что, собсно, и требовалось.
0
Ага, а какие-то требования к входному типу задавать можно (кроме как в комментариях) — чтобы еще и понятно было какие методы требуются внутри foobarCaller?
+ еще задача — складывать похожие объекты в массив и потом что-то с ними делать, тоже через интерфейс.
что-то вроде
+ еще задача — складывать похожие объекты в массив и потом что-то с ними делать, тоже через интерфейс.
что-то вроде
...
func main() {
a := MyType{A: 1, B: 2}
b := MyType2{V: 5}
var arr = []HaveVal{a, b}
for i := range arr {
println(arr[i].Val())
}
}
0
Да, минус такого решения — это необходимость просматривать весь код функции, чтобы понять реальный интерфейс T. Напоминает duck typing с проверкой на этапе компиляции. В принципе, у шаблонных функций/методов в C++ та же проблема. Где-то (в boost?) видел адское решение, которое позволяет задать требования к T на уровне кода при объявлении шаблона. Выглядит жутко конечно.
С массивом аналогичное решение.
С массивом аналогичное решение.
0
т.е. если я положу в массив указатели на какой-то базовый объект, вроде Object или void, то потом в цикле по массиву шаблон будет на этапе выполнения кода уже подбирать какие методы вызывать?
Можете небольшой пример в несколько строк накидать — для работы с массивом как у меня во втором примере, я потом уже с ним у себя поэкспериментирую — так ли он себя ведет как нужно.
Можете небольшой пример в несколько строк накидать — для работы с массивом как у меня во втором примере, я потом уже с ним у себя поэкспериментирую — так ли он себя ведет как нужно.
0
На данный момент у меня даже не получилось создать массив разнородных объектов =) Пока пытался это сделать, нашел вот такую интересную возможность (правда она не сильно нужна для этой задачи):
P.S. Шаблоны в Nim это немного другая вещь. Мы сейчас говорим про Generic'и. И они работают на этапе компиляции, а не выполнения.
proc foo[T: MyType1|MyType2](x: T) = echo "do something"
P.S. Шаблоны в Nim это немного другая вещь. Мы сейчас говорим про Generic'и. И они работают на этапе компиляции, а не выполнения.
0
да, я понял что при компиляции. Поэтому и задал вопрос в ключе — что делать когда это потребуется решать при выполнении.
0
Можно посмотреть, как выкрутились в модуле json — банальные object variants, как в сишном GLib. Это для простых случаев. Если же заморачиваться, то решение — дерево объектов и методы. Я взял пример с сайта и чуть переделал:
Сгенерированный сишный код для этого примера особенно хорош.
type
A = ref object of RootObj
B = ref object of A
x: int
C = ref object of A
s: string
method `$`(v: A): string =
quit "to override!"
method `$`(v: B): string = $v.x
method `$`(v: C): string = v.s
var a: seq[A] = @[B(x:4), C(s:"Hello")]
for v in a:
echo v
Сгенерированный сишный код для этого примера особенно хорош.
+1
Дерево объектов — это как-то печально. Получается «нецелевое» использование наследования. А когда множественное наследование не существует, дерево объектов вообще будет практически неприменимо.
0
В документации так и написано, что это overkill feature. Кроме того, авторы языка не очень поощряют наследование:
In particular, preferring composition over inheritance is often the better design.Правда, примеров не густо.
Composition (has-a relation) is often preferable to inheritance (is-a relation) for simple code reuse. Since objects are value types in Nim, composition is as efficient as inheritance.
0
template foobarCaller(self) =
self.foobar()
мне такое в голову пришло (эффект тот же), но Ваш вариант явно лучше
мне такое в голову пришло (эффект тот же), но Ваш вариант явно лучше
0
В коде опечатка, вызов foobar(t3) на самом деле — это вызов foobarCaller(t3).
Правильный код
type
T1 = object
foo: string
T2 = object
bar: string
T3 = object
baz: string
method foobar(self: T1) =
echo self.foo
method foobar(self: T2) =
echo self.bar
proc foobar(i: int) =
echo "Int" & repr(i)
proc foobarCaller[T](self: T) =
self.foobar()
var t1 = T1(foo: "T1")
var t2 = T2(bar: "T2")
var t3 = T3(baz: "T3")
foobar(t1) # компилируется, результат "T1"
foobar(t2) # компилируется, результат "T2"
foobar(42) # компилируется, результат "Int42"
foobarCaller(t3) # не компилируется (!) Error: type mismatch: got (T3)
# but expected one of:
# interface_test.foobar(self: T2)
# interface_test.foobar(self: T1)
# interface_test.foobar(i: int)
0
Sign up to leave a comment.
Знакомство с Nim: пишем консольную 2048