Комментарии 18
Люблю Go, но. Вот код на Go:
backwardIterator := iter.Seq[int](func(yield func(int) bool) {
for i := range 5 {
v := arr[i]
if !yield(i, v) {
return
}
}
})
А вот на Питоне:
def iter():
for i in range(5):
yield i
Что-то мне подсказывает, что в плане читаемости Го очень сильно сдаёт позиции. И это если не вспоминать, что он изначально не мог похвастаться наилучшей читаемостью.
Я немного орнул когда увидел как выглядят дженерики, когда их зарелизили. Криво, но в целом терпимо, хотя и есть бесячие нюансы. Но вот грядущие итераторы заставляют меня раз за разом пробивать фейспалмы. Выглядит просто отвратительно.
Это разные языки. У них разный синтаксис.
Вопрос о читаемости скорее про то, лучше или хуже станет код, когда в нем будут использоваться итераторы. И скорее акцент на "использоваться", нежели на то, как они будут реализованы. Ведь мы хотим написать способ обхода 1 раз, потому что он возможно какой-то сложный, чтобы его потом во многих местах использовать. Вот мы создали итератор, у него есть какое-то имя. По его имени можно будет предположить, что будет происходить, не вчитываясь во внутрянку. Или вчитаться 1 раз, а не каждый раз заново.
А бесконечные if err не смущают?
А зачем `v := arr[i]` ? В 1.22 же как раз поправили неочевидное поведение переменных в range
Там переменная v в принципе не нужна, потому что это итератор, возвращающий только 1 значение (по крайней мере я так понял замечание). И, соответственно, yield(i)
.
Дженерики сильно упросили и сократили код. А вот итераторы ... Даже не знаю, без них вроде всегда можно обойтись.
Что-то навороты какие-то, аж С++ повеяло:) При этом лично я никаких особых потребностей в итераторах и проблем с классическими циклами не испытываю. Ну подумаешь классический цикл с параметром. Зато просто и прозрачно.
Хотя последнее время погрузился в Go, и некоторых вещей действительно не хватает. Самое простое - это как ни странно тернарный оператор c ? x1 : x2
Приходится писать три отдельных строчки кода с объявлением переменной вместо того, чтобы написать нужный код прямо внутри другого выражения.
Еще немного напрягает, что в "методах классов" нет неявного доступа к полям класса
func (app *Applictaion) foo() {
app.x = 100; // ok
x = 100; // error
}
Тернарник ещё ладно, можно терпеть отсутствие, тем более что с ним можно натворить много эпичных багов. Но вот какой-нибудь сахар для проверки указателя или интерфейса на nil (условное присваивание, условный вызов) был бы прям очень кстати.
Ошибки, как передавать ошибки из такого енумератора (исключений же у нас нет)?
В первой переменной передаем результат, во второй ошибку. В теле цикла ошибку обрабатываем. Если я правильно понял вопрос.
range не предусматривает наличие ошибки. В текущем виде итератор скорее всего придётся оборачивать какой-нибудь структурой, чтобы проверить на ошибку в итераторе. Но выглядит как не самый удобный костыль, надеюсь с ошибкой ещё что-то надумают.
Go 1.22: Rangefunc Experiment