Можно ли парсер логов сделать на расте? Да. Он будет быстрым? Да. Будет ли он столь же понятен изящен и лаконичен как на питоне или прости господи perl. Полагаю нет.
Думаю, вы сильно удивитесь, но Rust - это один из лучших языков для написания парсеров. Наличие нормальных енумов и довольно продвинутого pattern matching'а позволяет как очень легко описывать токены, так и легко разделять логику парсера под разные токены.
А это по вашему что такое? Api не стабилизировано, но тут проблема в том, что не нужны связные списки. И я слышал мнение, что не стоило его и добавлять, только место занимает и время отнимает от действительно полезных вещей.
всилу того как устроен язык и философия писателей его стандартной библиотеки
Да нет, просто не сдались эти списки никому. Не нужны они в 99.9999% случаев. Если вот прям ну уж очень хочется связный список, то я уверен, что можно найти на любой вкус и цвет на crates.io. Цитата из документации Rust:
NOTE: It is almost always better to use Vec or VecDeque because array-based containers are generally faster, more memory efficient, and make better use of CPU cache.
насколько я помню, все коллекции в Rust - дженерики относительно аллокатора, так что его можно менять как для отдельной коллекции, так и глобально;
в Rust атомики, насколько я понимаю, +- скопированны с плюсов, точно так же можно задавать Ordering;
ну да, +- if(i >= 0 && i <= vec.len()). Только это нужно только для доступа по индексу, что благодаря очень хорошо развитым итераторам не нужно. А в итераторах все проверки уже сделаны, при итерировании их уже не будет;
не знаю, читали ли вы статью до или после того, как я дополнил часть про "Fearless concurrency", там я более подробно расписал гарантии Rust в плане многопоточности. Вкратце, в safe Rust невозможны гонки данных (не путать с состоянием гонки), что, по моему мнению, упрощает написание многопоточного кода в разы;
Rust это уже тоже давно не про хайп. Он уже есть в Linux, он используется в Google, Facebook, Cloudflare и т.д. в тех местах, где ни C, ни C++ не справляются.
Насколько Rust "не просто лучший язык программирования, это что-то не от мира сего, на голову выше плюсов" решать вам. Я уже давно для себя решил, что Rust - это язык, который очень многие вещи делает правильно. И это делает его как минимум одним из самых лучших языков (и точно лучшим из тех, что я знаю).
Не помогут эти, помогут другие. Да, не получится (точнее я не знаю как) как-то хитро доказать компилятору то, что какие-то числа из рядом лежащего словаря вот 100% в границах массива. У меня в коде в части про BFS не просто так assert!(curr_node_idx < self.nodes.len()); стоит. Этой проверки хватит для того, чтобы больше обращения по curr_node_idx не проверялись, т.к. он внутри цикла не меняется. А уж одна проверка на большой цикл это не так страшно, там и так куча условий, которые, скорее всего, сломают автовекторизацию.
В этом моя проблема с Golang, они там очень много чего "забыли","не знали" или "проигнорировали". Не то, чтобы я считал себя умнее создателей Golang, они явно делали язык под свои конкретные нужды, но когда рандом с улицы (я) может за 5 минут найти дыру в языке, который только начал изучать, то это как-то не очень.
Ладно, зайдем с другого конца. Вы вот правда считаете, что вы один знаете, как правильно связные списки писать? В компиляторе Rust используется даже код сторонних библиотек, не говоря уже о стандартной библиотеке. Что-то мне подсказывает, что у них были причины на то, чтобы использовать отдельную реализацию с вектором, а не готовую из стандартной библиотеки.
Вот на всякий случай ссылка на то, как избегать лишних проверок выхода за границу массива в Rust. Не думайте, что все просто "забыли" или "не знали", что такие проверки могут вредить производительности. Просто они решаются другими способами и без возможности добавить уязвимость в том месте, где производительность (и цена этих проверок) не важна.
Я не поленился и посмотрел, как же в стандартной библиотеке Rust реализован двусвязный список. Не поверите, все на указателях, никаких векторов! BTreeMap и BTreeSet тоже на массивах внутри (т.к. это, собственно, BTree). BinaryHeap действительно в хранит ноды в векторе. Насколько я помню, так и рекомендуется для наилучшего использования CPU кеша.
и это почему-то считается в раст сообществе нормальным
Простите мою иронию, но не могу сдержаться. Угадайте, откуда я взял такой подход для своей реализации Aхо-Корасика? Я взял его из обучающей статьи, где как раз C++. Понятия не имею, почему автор решил сделать так вместо указателей, но, очевидно, в C++ такой подход тоже используется. Видимо C++ тоже "заставил сделать какую то хрень, изменить всю архитектуру приложения, получить за это потерю производительности, читаемости, поддерживаемости и тд,".
Добавлю Erlang в список на изучение, много про него слышал, но руки не доходили. Будет интересно посмотреть на такую реализацию многопоточности.
И да, то, что Rust в каких-то местах показывает себя очень хорошо не значит, что он там лучший и, тем более, что только Rust хорошо себя показывает. У меня с Golang проблема как раз в этом, прям супер нового и уникального в Rust не много, там просто много вещей, которые хорошо работали в других языках. Что мешало добавить хотя бы часть из них в Golang для меня загадка.
Возможно, но пока (за почти 4 редакции, 2015, 2018, 2021, и скоро будет 2024) такой проблемы нет, изменения не слишком значительны. Справедливости ради и времени не так много прошло, так что посмотрим, что получится.
Языка человек не знает (даже C он так и не осилил), но почему-то он уверен, что "у него нет ни одного преимущества перед Rust". Почему? Потому, что ему так кто-то сказал. Воля ваша, но это нездоровый подход.
А еще мне в школе "кто-то сказал" про правила русского языка, математику с геометрией (доказательства теорем, конечно, тоже давали, но что-то мне подсказывает, что никто из учеников не заметил бы ошибки в доказательстве), физику, химию и много чего еще. Жизнь у меня одна и проверить все самостоятельно невозможно. У C есть объективные проблемы, отрицать этот факт бессмысленно.
Мне бы хотелось больше вопросов по существу вопроса, а не по форме. Если я где-то не прав, вы не стесняйтесь, напишите. Если у вас будут хорошие аргументы я вам обещаю, что изменю свое отношение к C и C++.
Так гарантии, которые предоставляет Rust, есть уже с 1.0 (2015 года). От того, что в библиотеке старые подходы она хуже работать не станет.
Тут возможна проблема тогда, когда у библиотеки не обновляются зависимости и в части из них могли найти и исправить баги. Это да, но это относится не ко всем библиотекам, многие из них нет никакого смысла переводить на новую редакцию, от самого этого факта ничего не изменится.
самое сложное в Rust начинается, когда в коде появляются всякие Cell/RefCell/Rc/Arc
Я бы сказал наоборот, когда начинается что-то сложное появляются Cell/RefCell/Rc/Arc. Во многих случаях правильным было бы не добавление счетчиков ссылок и interior mutability, а структурировать программу так, чтобы они не были нужны. Конечно, это не всегда возможно, но не могу сказать, что они нужны часто. Safe варианты деревьев можно так писать, а можно, например, хранить все ноды в векторе и в качестве указателя использовать позицию ноды. И универсальный совет про лекции Алексея Кладова про эту ситуацию. Вообще эти лекции очень универсальны, там можно найти ответ практически на любой вопрос. Думаю смысл жизни тоже там есть.
"уродливый" всё равно неизбежен
Тут же дело не в "уродливости" кода, а в том, что можно один вариант поменять на другой с гораздо большей уверенностью в том, что код делает тоже самое.
Просто хочется с людьми поделиться, что огромное количество проблем, с которыми им приходится постоянно сталкиваться уже решена и можно больше не мучиться.
Погодите, в go операция вырезания куска массива-слайса может этот слайс расширить?! И это не баг, а документированное поведение?
Не просто документированное поведение, оно прямо в Golang tour описано. И не в том смысле, что не делайте так никогда, а как просто еще одна возможность языка.
Просто по сравнению с Java у Rust другие преимущества) Писать статью про все достоинства (да и недостатки) Rust на 7 часов непрерывного чтения я пока не готов, так что написал о том, что не представлено так ярко, как мне бы хотелось.
более или менее в порядке ... с многопоточкой
Насколько я понимаю, тех же гарантий, которые дает Rust в плане многопоточности у Java нет. Тут либо Rust, либо языки без мутабельности вообще.
Учасникам Rust Foundation теперь запрещено выступать на конференциях со своими данными?
при этом второе переписывание
Ну да. После нескольких переписываний C++ кода на C++. И после этого оказалось, что так же переписать код с C++ на Rust в двое быстрее, чем с C++ на C++.
Попробуйте скомпилировать код на С++, вы удивитесь как много ошибок компилятор таки найдёт
Как только C++ не будет компилироваться в случае, когда в коде есть гонка данных обязательно попробую.
Счастливый вы человек, раз не знаете. Скорее всего после следующего кода настроение у вас ухудшится, так что готовьтесь.
Чтение слайса после длины
package main
import "fmt"
func main() {
s := []int{2, 3, 5, 7, 11, 13}
printSlice(s)
// Slice the slice to give it zero length.
s= s[:0]
printSlice(s)
// Extend its length.
s = s[:6]
printSlice(s)
s= append(s, 7)
printSlice(s)
// Works just fine
d := s[0:cap(s)][11]
fmt.Printf("len=%d cap=%d d=%v\n", len(s), cap(s), d)
// Obviously this panics
g := s[11]
fmt.Println(g)
}
func printSlice(s []int) {
fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s[0:cap(s)])
}
С помощью такой техники можно создавать очень веселые гайзенбаги
package main
import (
"fmt"
"math/rand/v2"
)
type SlidingWindow struct {
s []int
offset int
size int
}
func (w *SlidingWindow) next() []int {
if w.offset > (len(w.s) - w.size + 1) {
return nil
}
t := w.s[w.offset : w.offset+w.size]
w.offset += 1
return t
}
func sliding_window(s []int, offset int, size int) []int {
return s[offset : offset+size]
}
func main() {
s2 := []int{1, 2, 3, 4, 5, 6}
if rand.IntN(10) > 5 {
s2 = append(s2, 7) // panics without append
}
sw := SlidingWindow{s2, 0, 3}
for w := sw.next(); w != nil; w = sw.next() {
fmt.Println(w)
}
}
Переопределение ключевых слов
package main
import (
"fmt"
"math/rand/v2"
)
func really_big_func() (a, b bool) {
// a lot of code
// Happy debugging, suckers
true := rand.IntN(10) > 5
false := rand.IntN(10) > 3
fmt.Println(true)
fmt.Println(false)
// a lot of code
return true, false
}
func main() {
fmt.Println(really_big_func())
}
Думаю, вы сильно удивитесь, но Rust - это один из лучших языков для написания парсеров. Наличие нормальных енумов и довольно продвинутого pattern matching'а позволяет как очень легко описывать токены, так и легко разделять логику парсера под разные токены.
А это по вашему что такое? Api не стабилизировано, но тут проблема в том, что не нужны связные списки. И я слышал мнение, что не стоило его и добавлять, только место занимает и время отнимает от действительно полезных вещей.
Да нет, просто не сдались эти списки никому. Не нужны они в 99.9999% случаев. Если вот прям ну уж очень хочется связный список, то я уверен, что можно найти на любой вкус и цвет на crates.io.
Цитата из документации Rust:
Отвечу на что смогу:
насколько я помню, все коллекции в Rust - дженерики относительно аллокатора, так что его можно менять как для отдельной коллекции, так и глобально;
в Rust атомики, насколько я понимаю, +- скопированны с плюсов, точно так же можно задавать Ordering;
ну да, +-
if(i >= 0 && i <= vec.len())
. Только это нужно только для доступа по индексу, что благодаря очень хорошо развитым итераторам не нужно. А в итераторах все проверки уже сделаны, при итерировании их уже не будет;не знаю, читали ли вы статью до или после того, как я дополнил часть про "Fearless concurrency", там я более подробно расписал гарантии Rust в плане многопоточности. Вкратце, в safe Rust невозможны гонки данных (не путать с состоянием гонки), что, по моему мнению, упрощает написание многопоточного кода в разы;
Rust это уже тоже давно не про хайп. Он уже есть в Linux, он используется в Google, Facebook, Cloudflare и т.д. в тех местах, где ни C, ни C++ не справляются.
Насколько Rust "не просто лучший язык программирования, это что-то не от мира сего, на голову выше плюсов" решать вам. Я уже давно для себя решил, что Rust - это язык, который очень многие вещи делает правильно. И это делает его как минимум одним из самых лучших языков (и точно лучшим из тех, что я знаю).
Не помогут эти, помогут другие. Да, не получится (точнее я не знаю как) как-то хитро доказать компилятору то, что какие-то числа из рядом лежащего словаря вот 100% в границах массива. У меня в коде в части про BFS не просто так
assert!(curr_node_idx < self.nodes.len());
стоит. Этой проверки хватит для того, чтобы больше обращения поcurr_node_idx
не проверялись, т.к. он внутри цикла не меняется. А уж одна проверка на большой цикл это не так страшно, там и так куча условий, которые, скорее всего, сломают автовекторизацию.В этом моя проблема с Golang, они там очень много чего "забыли","не знали" или "проигнорировали". Не то, чтобы я считал себя умнее создателей Golang, они явно делали язык под свои конкретные нужды, но когда рандом с улицы (я) может за 5 минут найти дыру в языке, который только начал изучать, то это как-то не очень.
Ладно, зайдем с другого конца. Вы вот правда считаете, что вы один знаете, как правильно связные списки писать? В компиляторе Rust используется даже код сторонних библиотек, не говоря уже о стандартной библиотеке. Что-то мне подсказывает, что у них были причины на то, чтобы использовать отдельную реализацию с вектором, а не готовую из стандартной библиотеки.
Вот на всякий случай ссылка на то, как избегать лишних проверок выхода за границу массива в Rust. Не думайте, что все просто "забыли" или "не знали", что такие проверки могут вредить производительности. Просто они решаются другими способами и без возможности добавить уязвимость в том месте, где производительность (и цена этих проверок) не важна.
Я не поленился и посмотрел, как же в стандартной библиотеке Rust реализован двусвязный список. Не поверите, все на указателях, никаких векторов! BTreeMap и BTreeSet тоже на массивах внутри (т.к. это, собственно, BTree). BinaryHeap действительно в хранит ноды в векторе. Насколько я помню, так и рекомендуется для наилучшего использования CPU кеша.
Простите мою иронию, но не могу сдержаться. Угадайте, откуда я взял такой подход для своей реализации Aхо-Корасика? Я взял его из обучающей статьи, где как раз C++. Понятия не имею, почему автор решил сделать так вместо указателей, но, очевидно, в C++ такой подход тоже используется. Видимо C++ тоже "заставил сделать какую то хрень, изменить всю архитектуру приложения, получить за это потерю производительности, читаемости, поддерживаемости и тд,".
Добавлю Erlang в список на изучение, много про него слышал, но руки не доходили. Будет интересно посмотреть на такую реализацию многопоточности.
И да, то, что Rust в каких-то местах показывает себя очень хорошо не значит, что он там лучший и, тем более, что только Rust хорошо себя показывает. У меня с Golang проблема как раз в этом, прям супер нового и уникального в Rust не много, там просто много вещей, которые хорошо работали в других языках. Что мешало добавить хотя бы часть из них в Golang для меня загадка.
Возможно, но пока (за почти 4 редакции, 2015, 2018, 2021, и скоро будет 2024) такой проблемы нет, изменения не слишком значительны. Справедливости ради и времени не так много прошло, так что посмотрим, что получится.
А еще мне в школе "кто-то сказал" про правила русского языка, математику с геометрией (доказательства теорем, конечно, тоже давали, но что-то мне подсказывает, что никто из учеников не заметил бы ошибки в доказательстве), физику, химию и много чего еще. Жизнь у меня одна и проверить все самостоятельно невозможно. У C есть объективные проблемы, отрицать этот факт бессмысленно.
Мне бы хотелось больше вопросов по существу вопроса, а не по форме. Если я где-то не прав, вы не стесняйтесь, напишите. Если у вас будут хорошие аргументы я вам обещаю, что изменю свое отношение к C и C++.
Так гарантии, которые предоставляет Rust, есть уже с 1.0 (2015 года). От того, что в библиотеке старые подходы она хуже работать не станет.
Тут возможна проблема тогда, когда у библиотеки не обновляются зависимости и в части из них могли найти и исправить баги. Это да, но это относится не ко всем библиотекам, многие из них нет никакого смысла переводить на новую редакцию, от самого этого факта ничего не изменится.
Я бы сказал наоборот, когда начинается что-то сложное появляются
Cell/RefCell/Rc/Arc
. Во многих случаях правильным было бы не добавление счетчиков ссылок и interior mutability, а структурировать программу так, чтобы они не были нужны. Конечно, это не всегда возможно, но не могу сказать, что они нужны часто. Safe варианты деревьев можно так писать, а можно, например, хранить все ноды в векторе и в качестве указателя использовать позицию ноды. И универсальный совет про лекции Алексея Кладова про эту ситуацию. Вообще эти лекции очень универсальны, там можно найти ответ практически на любой вопрос. Думаю смысл жизни тоже там есть.Тут же дело не в "уродливости" кода, а в том, что можно один вариант поменять на другой с гораздо большей уверенностью в том, что код делает тоже самое.
Я частично переписал часть про "Fearless concurrency", надеюсь теперь моя мысль более понятна.
Просто хочется с людьми поделиться, что огромное количество проблем, с которыми им приходится постоянно сталкиваться уже решена и можно больше не мучиться.
Не просто документированное поведение, оно прямо в Golang tour описано. И не в том смысле, что не делайте так никогда, а как просто еще одна возможность языка.
Просто по сравнению с Java у Rust другие преимущества) Писать статью про все достоинства (да и недостатки) Rust на 7 часов непрерывного чтения я пока не готов, так что написал о том, что не представлено так ярко, как мне бы хотелось.
Насколько я понимаю, тех же гарантий, которые дает Rust в плане многопоточности у Java нет. Тут либо Rust, либо языки без мутабельности вообще.
Учасникам Rust Foundation теперь запрещено выступать на конференциях со своими данными?
Ну да. После нескольких переписываний C++ кода на C++. И после этого оказалось, что так же переписать код с C++ на Rust в двое быстрее, чем с C++ на C++.
Как только C++ не будет компилироваться в случае, когда в коде есть гонка данных обязательно попробую.
Счастливый вы человек, раз не знаете. Скорее всего после следующего кода настроение у вас ухудшится, так что готовьтесь.
Чтение слайса после длины
С помощью такой техники можно создавать очень веселые гайзенбаги
Переопределение ключевых слов