Хм, в таком случае извиняюсь. К вам в профиль не заглядывал. Да и вроде как не троллил, пытался просто пообсуждать. Впрочем, всего доброго, эта ветка явно изжила себя.
К сожалению, вы не совсем понимаете мой вопрос. Я упоминаю defer только как механизм для гарантированного закрытия, не более. Я не говорю, что он обязателен для чего-либо. Мой вопрос хотя бы о минимальной ситуации, когда переменная, содержащая неуправляемый ресурс, была создана (не передана снаружи) внутри функции, не "ушла наружу" и при этом не была корректно закрыта. По моему опыту, такая ситуация довольно часто встречается в реальном коде.
Чтобы проигнорить ошибку, вам придется сознательно написать вместо err — _ что означает "я сознательно игнорирую это значение, потому что так надо".
Окей, тут согласен. Давно не писал, возможно так и было. Впрочем, вопрос boilerplate остаётся, хоть и не так остро.
И чем при выходе из скопа не устраивают defer тогда?
Всем устраивает. Кроме того, что последний раз, когда я имел дело с Go, компилятор никак не предупреждал, что я его пропустил. Или ситуация поменялась, и я напрасно ною?
Я вам наступил на любимый мозоль, что вы мне аж по карме прошлись?
Поэтому спросил, для каких задач вам захотелось деструкторов и использовали ли вы финализаторы.
Боже, ну почему все так вцепились в слово "деструкторы"? Я уже в нескольких ветках написал, что было бы приятно иметь хотя бы ворнинг "здесь может утечь ресурс, поставь defer".
вроде Item, у которого есть один метод Less — для сравнения значений
Но чтобы получить реальный тип, который лежит в структуре — извольте тайп каст. Я говорю именно об этой ситуации.
В Джаве 1.5 тайп-касты же всё равно происходят, но автоматически, неявно, насколько я понимаю.
Да, происходят. На это ругается множество людей с самого выхода 1.5
Мне кажется, вы сильно переоцениваете роль компилятора :) С какой стати у вас должен быть сегфолт, если вы не проверили ошибку?
Как бы
val, err := someOp()
// здесь забыли вставить if err != nil { ... }, компилятор промолчит
val.field.fieldOp() // привет паника - или сегфолт, уже не помню
Память сборщик мусора почистит, понятное дело, но defer используется для того, чтобы выполнить какие-то действия при выходе из скопа
Кроме памяти есть ещё множество типов ресурсов. Самые простые — файлы и сокеты. И для многих из них хотелось бы точно знать, что они будут закрыты при выходе из скопа. Проблема даже не в необходимости явной инструкции для такого закрытия. Проблема в том, что компилятор в этом не желает помогать.
Хорошо, давайте попробую привести примеры. Сам код, увы, сейчас мне недоступен.
как именно вы не смогли "переиспользовать код" и к чему это привело из-за "отсутствия дженериков"
Стейт-прокси над стейтлесс сервером. Часть, ответственная за кеширование, была отделена от других кусков кода. Снаружи пришлось "просовывать" объект в виде interface{} и лямбду, которая его кастила к правильному типу и дёргала. Да, это непривычно для меня — я отвык от тайп-кастов по поводу и без с тех пор как перестал писать на голом С. Более общий пример — в Го любая не-встроенная структура данных будет построена на interface{}. Опять тайп-касты. В Java такая ситуация была до 1.5, после чего дженерики, хоть и урезанные, таки ввели.
как нынешняя обработка ошибок приводит к проблемам в коде
Как я сказал, конкретный код привести сейчас не могу. Был код такого вида, способный "обломаться" на любом этапе:
В добавок, если я забуду обработать ошибку, компилятор мне слова не скажет. И у меня будет NPE паника или сегфолт.
Для сравнения, на любом языке с исключениями:
return op1().op2().op3;
На Rust, который тоже работает через возвращаемые значения
op1()?.op2()?.op3()?
Может ещё конструкторы, ещё и с перегрузкой?
Вот кстати с отсутствием конструкторов как "специальных функций" я полностью согласен. Ловля нетривиальных проблем с порядком инициализации и "самоубийства" в С++ при исключении в конструкторе (а особенно в одном из инициализированных по умолчанию полей) — удовольствие ниже среднего. Перегрузка функций и методов по типу аргумента — дело скорее вкуса. Может быть удобна, но может быть и использована криво.
Обычно если "хочется деструкторов", то это вы ещё не отвыкли от предыдущих языков
…
Defer совершенно другую задачу решает.
Таки да, я привык, что если я открою какой-то ресурс и никуда его не дену — он сам помрёт без моего участия, в конце области видимости. По поводу же defer — а какую в таком случае задачу он решает? Разве не очистку в конце блока? Впрочем, меня вполне устроило бы предупреждение от компилятора, если я забываю почистить ресурс.
С деструкторами конечно проблемка, т.к. они требуют сильно подпилить семантику — либо вводить "волшебный тип-обёртку". Как вариант обхода — маркировать "закрывабельные" типы и при их наличии в скопе делать анализ потока управления, если может утечь — ругаться и требовать дефер. Но это отдельный геморрой. Считайте, что список выше в порядке "хотения".
Вы путаете простоту и выразительность. Питон выразительный, т.к. имеет довольно много сахара. Но относительно простой, т.к. там обычно один очевидный способ сделать что-то. Го, в свою очередь простой, т.к. там мало концепций, относительно простых для понимания, и не топчущихся друг другу по ногам. Однако, го не слишком выразителен, что приводит к boilerplate, в т.ч. на ряде частых и простых сценариев.
Non-nullable ссылки по умолчанию. Nil non-nil interfaces это честно говоря жёсткий косяк. Вопрос того, ссылки в Го или указатели, на самом деле дискуссионный.
Деструкторы в каком-то вменяемом виде. defer не очень способствует надёжному коду.
К слову, epoll(0), или BUSY_WAIT приводит к тому, что еполл сразу возвращается, независимо от кол-ва сработавших событий. Это приводит к тому, что текущий поток крутится в чём-то наподобие спинлока вместо того, чтобы сразу отдать остатки кванта. И да — это даёт прирост — но только в очень конкретных сценариях. И таки да, в нормальном продакшене так не делают, т.к. вместо прироста будет просадка.
Именно про это я и говорю, но. Конкретные оптимизации зависят от языка и я, так же, сказал почему.
Я спорю именно с тем, что оптимизации — это какая-то вещь в себе. Нет. Для оптимизаций нужны возможности, в том числе, со стороны языка.
Точно так же, как выбор языка не делается просто так. Он обусловлен той областью, в которой работает человек. Т.е. язык косвенно влияет и на опыт человека и на его компетенцию в данной теме.
Эээ… ну да, я согласен. Засим, думаю, ветку можно прикрывать.
Так, я уже перестал понимать, спорим ли мы с вами или говорим об одной вещи разными словами.
Вы начали с того, что топовое решение на Rust попало только на 31-е место, а вот на Go — аж на 15-е (потом поправили что на 11-е).
Я возразил, что на таком уровне вопрос уже не в языке, а в конкретных оптимизациях.
И вы начали аргументировать, что чем толще рантайм и слой абстракций в самом языке, тем больше проблем такие оптимизации делать. С чем я согласен.
Просто уточню, что решение на Rust (раз уж за него зацепились) отставало от 1-го места по очкам менее чем вдвое. И именно в этом контексте я и написал, что в таких условиях решает не язык, а конкретные оптимизации.
По отзывам довольно много приходит питонистов и рубистов, которым надо оптимизировать какой-то нагруженный кусок, а писать на С/С++ боязно. Плюс — хайлоад кап был чисто русский, так что могло быть просто мало народу в русскоязычном комьюнити. Я например узнал о соревновании сильно постфактум.
Что мешало всем остальным языкам «оптимизировать» «свои» «алгоритмы»? Я уж не буду говорить о том, что именно язык прямо и косвенно влияет на возможность оптимизаций. Косвенно через компетенцию автора в данном контексте, а прямо через возможности языка.
Приведу простые примеры. Откуда у человека, который писал на готовом веб-стеке на том же пхп/ноде есть необходимые навыки сетевого программирования?
Здесь не совсем понял, кого вы защищаете, а кому пеняете.
Си — КМК всё ясно, это язык, тождественный языку интерфейса системных библиотек. К тому же, до недавнего времени ему по факту не было альтернативы для таких задач.
Го — следуя вашей логике, откуда у человека, который писал на готовом net/http, необходимые навыки сетевого программирования?
Rust — упомянутые вами средства оптимизации там есть, но их надо применить; было ли это сделано в топовом решении — я не знаю.
А вообще в топ-50 попало решение на Perl — что тоже кое о чём говорит.
Или уточните, о чём речь.
Как вы будите оптимизировать аллокации на языке с ГЦ?
Эээ… пулинг и буферы, как и без ГЦ? Если конечно стек на этом языке такое позволяет.
А с неуправляемым ГЦ?
Это как? ГЦ который сам в истерике выделяет и удаляет память? :)
Проблема в том, какое определённое мнение ваши реплики, а также Crandel, сформируют о самом сообществе Rust у присутствующих здесь. СпокойнЕе надо быть. Тем более, что ребята из мэйл.ру не встали в позу, а спокойно, как адекватные люди, сказали "Упс, да, ошибочка".
Так вот, это сообщество нашло эту кажется простую ошибку спустя только 2 года. Выходит, проблема была и до статьи, что только добавляет очков к Go.
То есть если я найду в любой паблик статье про произвольный язык ошибку, я смогу говорить, что у него плохое сообщество — потому что не просматривает все статьи и не ищет в них ошибки с остервенением? Вот это реально был бы фанатизм.
Мне кажется, вопрос не в фанатизме, а в публичности — когда публичные действия "лица" некоммерческой организации противоречат одной из целей этой организации. Просто сидеть и контрибьютить в ядро можно и с Windows, если уж так припёрло. Это как актриса публично заявляет, что поддерживает общества по защите животных — но при этом ходит в натуральной норковой шубке.
Хм, в таком случае извиняюсь. К вам в профиль не заглядывал. Да и вроде как не троллил, пытался просто пообсуждать. Впрочем, всего доброго, эта ветка явно изжила себя.
К сожалению, вы не совсем понимаете мой вопрос. Я упоминаю defer только как механизм для гарантированного закрытия, не более. Я не говорю, что он обязателен для чего-либо. Мой вопрос хотя бы о минимальной ситуации, когда переменная, содержащая неуправляемый ресурс, была создана (не передана снаружи) внутри функции, не "ушла наружу" и при этом не была корректно закрыта. По моему опыту, такая ситуация довольно часто встречается в реальном коде.
Окей, тут согласен. Давно не писал, возможно так и было. Впрочем, вопрос boilerplate остаётся, хоть и не так остро.
Всем устраивает. Кроме того, что последний раз, когда я имел дело с Go, компилятор никак не предупреждал, что я его пропустил. Или ситуация поменялась, и я напрасно ною?
Я вам наступил на любимый мозоль, что вы мне аж по карме прошлись?
Боже, ну почему все так вцепились в слово "деструкторы"? Я уже в нескольких ветках написал, что было бы приятно иметь хотя бы ворнинг "здесь может утечь ресурс, поставь defer".
Но чтобы получить реальный тип, который лежит в структуре — извольте тайп каст. Я говорю именно об этой ситуации.
Да, происходят. На это ругается множество людей с самого выхода 1.5
Как бы
Кроме памяти есть ещё множество типов ресурсов. Самые простые — файлы и сокеты. И для многих из них хотелось бы точно знать, что они будут закрыты при выходе из скопа. Проблема даже не в необходимости явной инструкции для такого закрытия. Проблема в том, что компилятор в этом не желает помогать.
То есть по другим трём пунктам вопросов нет? :)
Хорошо, давайте попробую привести примеры. Сам код, увы, сейчас мне недоступен.
Стейт-прокси над стейтлесс сервером. Часть, ответственная за кеширование, была отделена от других кусков кода. Снаружи пришлось "просовывать" объект в виде interface{} и лямбду, которая его кастила к правильному типу и дёргала. Да, это непривычно для меня — я отвык от тайп-кастов по поводу и без с тех пор как перестал писать на голом С. Более общий пример — в Го любая не-встроенная структура данных будет построена на interface{}. Опять тайп-касты. В Java такая ситуация была до 1.5, после чего дженерики, хоть и урезанные, таки ввели.
Как я сказал, конкретный код привести сейчас не могу. Был код такого вида, способный "обломаться" на любом этапе:
В добавок, если я забуду обработать ошибку, компилятор мне слова не скажет. И у меня будет NPE паника или сегфолт.
Для сравнения, на любом языке с исключениями:
На Rust, который тоже работает через возвращаемые значения
Вот кстати с отсутствием конструкторов как "специальных функций" я полностью согласен. Ловля нетривиальных проблем с порядком инициализации и "самоубийства" в С++ при исключении в конструкторе (а особенно в одном из инициализированных по умолчанию полей) — удовольствие ниже среднего. Перегрузка функций и методов по типу аргумента — дело скорее вкуса. Может быть удобна, но может быть и использована криво.
Таки да, я привык, что если я открою какой-то ресурс и никуда его не дену — он сам помрёт без моего участия, в конце области видимости. По поводу же defer — а какую в таком случае задачу он решает? Разве не очистку в конце блока? Впрочем, меня вполне устроило бы предупреждение от компилятора, если я забываю почистить ресурс.
С деструкторами конечно проблемка, т.к. они требуют сильно подпилить семантику — либо вводить "волшебный тип-обёртку". Как вариант обхода — маркировать "закрывабельные" типы и при их наличии в скопе делать анализ потока управления, если может утечь — ругаться и требовать дефер. Но это отдельный геморрой. Считайте, что список выше в порядке "хотения".
Вы путаете простоту и выразительность. Питон выразительный, т.к. имеет довольно много сахара. Но относительно простой, т.к. там обычно один очевидный способ сделать что-то. Го, в свою очередь простой, т.к. там мало концепций, относительно простых для понимания, и не топчущихся друг другу по ногам. Однако, го не слишком выразителен, что приводит к boilerplate, в т.ч. на ряде частых и простых сценариев.
Всё же надеюсь, что некоторые элементы в Go 2 введут. Я бы лично не откзался от четырёх
К слову, epoll(0), или BUSY_WAIT приводит к тому, что еполл сразу возвращается, независимо от кол-ва сработавших событий. Это приводит к тому, что текущий поток крутится в чём-то наподобие спинлока вместо того, чтобы сразу отдать остатки кванта. И да — это даёт прирост — но только в очень конкретных сценариях. И таки да, в нормальном продакшене так не делают, т.к. вместо прироста будет просадка.
Да, точно. Извиняюсь.
Эээ… ну да, я согласен. Засим, думаю, ветку можно прикрывать.
Мне понравилась идея, предложенная на следующий хайлоад. Постепенно поднимать RPS. Выиграет тот, кто дольше всех проживёт, не выходя за SLA.
Так, я уже перестал понимать, спорим ли мы с вами или говорим об одной вещи разными словами.
Вы начали с того, что топовое решение на Rust попало только на 31-е место, а вот на Go — аж на 15-е (потом поправили что на 11-е).
Я возразил, что на таком уровне вопрос уже не в языке, а в конкретных оптимизациях.
И вы начали аргументировать, что чем толще рантайм и слой абстракций в самом языке, тем больше проблем такие оптимизации делать. С чем я согласен.
Просто уточню, что решение на Rust (раз уж за него зацепились) отставало от 1-го места по очкам менее чем вдвое. И именно в этом контексте я и написал, что в таких условиях решает не язык, а конкретные оптимизации.
По отзывам довольно много приходит питонистов и рубистов, которым надо оптимизировать какой-то нагруженный кусок, а писать на С/С++ боязно. Плюс — хайлоад кап был чисто русский, так что могло быть просто мало народу в русскоязычном комьюнити. Я например узнал о соревновании сильно постфактум.
Здесь не совсем понял, кого вы защищаете, а кому пеняете.
Или уточните, о чём речь.
Эээ… пулинг и буферы, как и без ГЦ? Если конечно стек на этом языке такое позволяет.
Это как? ГЦ который сам в истерике выделяет и удаляет память? :)
Проблема в том, какое определённое мнение ваши реплики, а также Crandel, сформируют о самом сообществе Rust у присутствующих здесь. СпокойнЕе надо быть. Тем более, что ребята из мэйл.ру не встали в позу, а спокойно, как адекватные люди, сказали "Упс, да, ошибочка".
То есть если я найду в любой паблик статье про произвольный язык ошибку, я смогу говорить, что у него плохое сообщество — потому что не просматривает все статьи и не ищет в них ошибки с остервенением? Вот это реально был бы фанатизм.
Это вы как-то палку перегибаете. Если одна статья с бенчмарками, пусть и от Мэйл.Ру, способна нанести серьёзный вред сообществу — я уж и не знаю.
Мне кажется, вопрос не в фанатизме, а в публичности — когда публичные действия "лица" некоммерческой организации противоречат одной из целей этой организации. Просто сидеть и контрибьютить в ядро можно и с Windows, если уж так припёрло. Это как актриса публично заявляет, что поддерживает общества по защите животных — но при этом ходит в натуральной норковой шубке.