Forwarded from Сколопендра.Шитпостинг (Александра Малютина)
Инверсия копипасты про тян #2: Эх, как же хочется массивную, загорелую, высокую, опытную в с*ксе, целованную, с накачанными руками, большими ступнями, бритую налысо альфу, успешную, с кучей друзей и подруг, открытую экстровертку, дабы вместе с ней участвовать в приятном социуме.
👍7💩3❤🔥2🤮2😭2
Блог*
Документация Go: "Go — простой язык, в нём есть только один цикл: for". Тем временем for: - Безусловный цикл - Цикл с предусловием - Цикл в стиле C - Цикл по слайсу - Цикл по строке - Цикл по мапе - Цикл по каналу
#prog #go
Тем временем в Go предложили сделать цикл по функциям (и по числам, но сегодня речь не об этом). Если конкретно — по функциям вида
* а как вообще отличается возврат из
* что делать, если функция-итератор игнорирует возвращаемое значение
* нормально ли это вообще, что при исполнении
* что делать, если
* можно ли сделать генерируемые компилятором проверки на подобное поведение без того, чтобы угробить перформанс из-за убогости Go-шного инлайнера?
* должны ли средства для инспектирования стека из пакета
Всех этих проблем лишены pull-итераторы (aka внешняя итерация) — функции вида
Но то обсуждение застопорилось по ряду причин.
Первая проблема — итерация с возможными ошибками. Честно, вот это как раз меньшая из проблем — можно было бы просто сделать стандартный обобщённый тип для пары
Вторая проблема — освобождение ресурсов после итерации — скажем, для итератора по содержимому файла или по результату SQL-запроса (для push-итераторов это не проблема, поскольку они могут исполнять произвольный код после вызова
В конечном счёте это обсуждение просто закрыли.
Для сравнения, в языках без GC (читай, C++ и Rust) для очистки используется RAII, а в языках с GC есть средства для явного автоматического закрытия по выходу из области видимости: try-with-resources и
Тем временем в Go предложили сделать цикл по функциям (и по числам, но сегодня речь не об этом). Если конкретно — по функциям вида
func(yield func(T1, T2) bool) bool
(а также func(yield func(T) bool) bool
и func(yield func() bool) bool
). Эти функции принимают тело цикла в виде функции, которая принимает на вход очередную переменную итерации и возвращает, нужно ли продолжать итерирование. Реализовывать это предлагают в виде синтаксической трансформации: код видаfor k, v := range iterfunc {преобразовывать в
// body
}
iterfunc(func (k K, v V) bool {
// body
return true
})
То есть реализовывать push-итератор (или, иначе, внутренняя итерация). Ввиду того, что в Go синтаксис вызова метода без скобок генерирует замыкание, захватывающее значение перед точкой, это делает возможным использование циклов для итераторов коллекций:for elem := range collection.Iter {Выглядит вроде просто, но такой подход порождает кучу дизайн-вопросов. Окей,
// ...
}
break
транслируется в return false
, а continue
— в return true
. Но вот что делать с return
в теле цикла? С goto
(да, он есть в Go)? С defer
(особенно, если там внутри recover
)? Последнее, кстати, вызвало больше всего вопросов в обсуждении. Да, это возможно всё проделать (более того, тестовая реализация, покрывающая всё это, уже есть), но семантика в этом случае вызывает вопросы. В частности:* а как вообще отличается возврат из
yield
за счёт достижения конца итерации и за счёт return
из функции, в которой цикл?* что делать, если функция-итератор игнорирует возвращаемое значение
yield
?* нормально ли это вообще, что при исполнении
break
может исполниться некий произвольный код, то есть итерация не обязательно будет немедленно завершена?* что делать, если
yield
(который, я напомню, может включать в себя нелокальный control flow) утекает и вызывается вне цикла?* можно ли сделать генерируемые компилятором проверки на подобное поведение без того, чтобы угробить перформанс из-за убогости Go-шного инлайнера?
* должны ли средства для инспектирования стека из пакета
runtime
показывать фреймы функции-итератора?Всех этих проблем лишены pull-итераторы (aka внешняя итерация) — функции вида
func () (T, bool)
. Они реализуемы на Go уже сейчас, они не требуют изменения языка¹, без проблем позволяют использовать весь control flow. А ещё — хотя я упоминания этого в обсуждении предложения не видел — позволяют сделать zip на итераторах (что на pull-итераторах, кажется, вообще не реализуемо (хммммм)). Наверное, можно подумать, что подобные итераторы уже предлагали к реализации. И вы абсолютно правы!Но то обсуждение застопорилось по ряду причин.
Первая проблема — итерация с возможными ошибками. Честно, вот это как раз меньшая из проблем — можно было бы просто сделать стандартный обобщённый тип для пары
(значение, ошибка)
, что и так используется в коде на Go (а ещё лучше, чтобы можно было использовать деструктуризацию — добавить наконец в язык настоящие кортежи вместо недоразумения под названием multiple function return values).Вторая проблема — освобождение ресурсов после итерации — скажем, для итератора по содержимому файла или по результату SQL-запроса (для push-итераторов это не проблема, поскольку они могут исполнять произвольный код после вызова
yield
). Это вызвало кучу обсуждения на тему того, как это реализовать. В частности: нужен ли метод Stop()
в интерфейсе итератора или вынести в отдельный интерфейс, кто и как должен этот метод вызывать, можно ли просто использовать io.Closer
для семантики очистки ресурсов...В конечном счёте это обсуждение просто закрыли.
Для сравнения, в языках без GC (читай, C++ и Rust) для очистки используется RAII, а в языках с GC есть средства для явного автоматического закрытия по выходу из области видимости: try-with-resources и
AutoCloseable
в Java, using
и IDisposable
в C#, with
и context manager в Python. В Go есть... Финализаторы. Которые не без своих проблем (1, 2), главная из которых — они не дают никаких гарантий по тому, когда будут выполнены.GitHub
spec: add range over int, range over func · Issue #61405 · golang/go
Following discussion on #56413, I propose to add two new types that a for-range statement can range over: integers and functions. In the spec, the table that begins the section would have a few mor...
👍4🤣4🤮1
Блог*
Документация Go: "Go — простой язык, в нём есть только один цикл: for". Тем временем for: - Безусловный цикл - Цикл с предусловием - Цикл в стиле C - Цикл по слайсу - Цикл по строке - Цикл по мапе - Цикл по каналу
И да, я кое о чём умалчивал до этого момента. Было обсуждение, которое рассматривало и pull-, и push-итераторы. Но реализовать Russ Cox в итоге решил push-итераторы.
Воистину, проклятый язык.
¹: хотя без языковой интеграции их использование выглядит немного неловко:
Воистину, проклятый язык.
¹: хотя без языковой интеграции их использование выглядит немного неловко:
for e, _ok := it.Next(); _ok; e, _ok = it.Next() {
// statements
}
GitHub
user-defined iteration using range over func values · golang go · Discussion #56413
There is no standard way to iterate over a sequence of values in Go. For lack of any convention, we have ended up with a wide variety of approaches. Each implementation has done what made the most ...
👍5🤡3
Блог*
Сасный супермаркет
Интересно. Ценники все, разумеется, на армянском. Но вот на этикетках-наклейках на развесную продукцию (фрукты, овощи, готовая еда) название написано на русском
Приснилось, что я форкнул Go и добавил в него иммутабельность. К чему бы это?
👍10😁7❤1🤔1
Forwarded from мне не нравится реальность
Did you know that
https://cohost.org/wafflelapkin/post/2124164-rust-huh-moment-of-the-day
Add
is object safe?https://cohost.org/wafflelapkin/post/2124164-rust-huh-moment-of-the-day
#prog #go
Go не разрешает битовые сдвиги для чисел с плавающей точкой. Например, следующая программа не компилируется:
Может, для константных выражений в Go исключение? Попробуем поменять
Go не разрешает битовые сдвиги для чисел с плавающей точкой. Например, следующая программа не компилируется:
package mainС ошибкой:
import "fmt"
func shift(x float32) float32 {
return x << 3
}
func main() {
fmt.Println(shift(1.0))
}
./prog.go:6:9: invalid operation: shifted operand x (variable of type float32) must be integer
Разумеется, если удалить функцию и заинлайнить её по месту вызова, то поведение не должно измениться:package mainИ это выдаёт... Ан не, не выдаёт никакой ошибки — компилируется и печатает 8.
import "fmt"
func main() {
fmt.Println(1.0 << 3)
}
Может, для константных выражений в Go исключение? Попробуем поменять
1.0
на 1.1
:./prog.go:6:14: invalid operation: shifted operand 1.1 (untyped float constant) must be integer
Спасибо, Go, очень полезно /s🔥10🤡7👌1