어떤 프로그램을 fuzz test하려 하는데, 테스트 결과는 Result 타입으로 주어진다. 성공한 결과는 의미가 없으므로 Result 타입이다.
100만개의 케이스를 임의로 생성해서 테스트를 하되, 하나라도 실패하면 중단하고 어떤 케이스였는지 보여줄 것이다.
그런데, 여기서 100만개의 케이스들을 메모리에 미리 올려놓을 필요가 있을까? 그래서 lazy하게 벡터 대신 이터레이터를 줬다. (yield는 언제 안정화됨??)
근데 생각해 보니까, TestCase::test는 self만을 인자로 받고 부작용이 없는 CPU-bound 작업니까 병렬화 해도 될거같아서 rayon도 한번 얹어줬다(ㅈ사기인듯 진짜)
문제는 클로저로 감싸면서 에러가 발생했을 때 return으로 끊을 수 없다는거임. for_each 대신에 안 함수형하게 for loop 쓰면 되긴 하는데 더 좋은게 있더라
https://doc.rust-lang.org/std/result/enum.Result.html#implementations
impl FromIterator<Result> for ResultwhereV: FromIterator,
Result의 이 impl이 Iterator of result를 Result of iterator로 바꿔줌!!
그런데 Result에서 ()는 사실상 의미없는 placeholder 역할인데 Vec<()>으로 결과값을 모아줄 필요가 있을까?
놀랍게도 Rust 개발자 성님들은 이런 고민을 한참전에 끝내심
https://doc.rust-lang.org/std/primitive.unit.html#implementations
impl FromIterator<()> for ()Iterator of ()와 여기서 변환된 타입(Vec<()>, ...)들은 하나의 ()으로 묶일 수 있음(어차피 ()타입이면 다 값이 같으니까)
그래서 최종적으로는 이런 코드가 되었다
100만개의 랜덤 케이스를 만들고, 병렬화해서 테스트하고, 에러가 발생하면 즉시 정지하는 코드
심지어 메모리 낭비도 (내가 아는 선에서는) 전혀 없음
Rust는 진짜 개사기 언어인거 같다
아시발 좆같은 디시서버가 브라켓 다 날려먹어서 타입인자 안보이네
러스트 추
Rust 매럭적입니다. category theory관점에서 위의 코드변환을 분석해보면 Iterator 변환에 Applicative와 () 간소화에 isomorphism이 녹아 있네요. Rust성님들 ++
rayon 먼가하고 찾아밧더니 씹사기네 ㄹㅇ