Liam Watts's Avatar

Liam Watts

@liam271.bsky.social

Software engineer and language leaner I do backend, data engineering, some frontend, some AI. Love learning new things and so I've picked up languages like C#, Haskell, Rust, and Japanese https://github.com/Wattsy2020

26 Followers  |  166 Following  |  7 Posts  |  Joined: 19.11.2023  |  1.8238

Latest posts by liam271.bsky.social on Bluesky


So for now I'll rest easy knowing Gemini 2 won't take my job. Fingers crossed for o3...

21.12.2024 13:07 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
impl<T, I: Iterator<Item = T>> Iterator for PairwiseResults<T, I> {
    type Item = Pair<T>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.iterator.next() {
            None => self.prev.take().map(Last),
            Some(next) => {
                match self.prev.take() {
                    None => {
                        self.prev = Some(next);
                        match self.prev.take() {
                            Some(val) => Some(First(val)),
                            None => unreachable!(), // This should not happen
                        }
                    }
                    Some(prev) => {
                        self.prev = Some(next);
                        match self.prev.take() {
                            Some(val) => Some(Middle(prev, val)),
                            None => unreachable!(), // This should not happen
                        }
                    }
                }
            }
        }
    }
}

impl<T, I: Iterator<Item = T>> Iterator for PairwiseResults<T, I> { type Item = Pair<T>; fn next(&mut self) -> Option<Self::Item> { match self.iterator.next() { None => self.prev.take().map(Last), Some(next) => { match self.prev.take() { None => { self.prev = Some(next); match self.prev.take() { Some(val) => Some(First(val)), None => unreachable!(), // This should not happen } } Some(prev) => { self.prev = Some(next); match self.prev.take() { Some(val) => Some(Middle(prev, val)), None => unreachable!(), // This should not happen } } } } } } }

I then asked it if it's possible to do this without cloning, it was too suggestible and said yes. The first attempt removed the clone calls and change nothing else (causing compiler errors for moving a value twice). After providing the compiler output it failed to fix the errors with this oddity

21.12.2024 13:07 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
impl<T, I: Iterator<Item = T>> Iterator for PairwiseResults<T, I>
where
    T: Clone, // Add Clone bound if you need to clone the values
{
    type Item = Pair<T>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.iterator.next() {
            None => {
                let result = self.prev.take().map(Last);
                result
            },
            Some(next) => {
                let temp = self.prev.take();
                self.prev = Some(next.clone()); // Clone here if needed, otherwise move
                match temp {
                    None => Some(First(next)),
                    Some(prev) => Some(Middle(prev, next))
                }
            }
        }
    }
}

impl<T, I: Iterator<Item = T>> Iterator for PairwiseResults<T, I> where T: Clone, // Add Clone bound if you need to clone the values { type Item = Pair<T>; fn next(&mut self) -> Option<Self::Item> { match self.iterator.next() { None => { let result = self.prev.take().map(Last); result }, Some(next) => { let temp = self.prev.take(); self.prev = Some(next.clone()); // Clone here if needed, otherwise move match temp { None => Some(First(next)), Some(prev) => Some(Middle(prev, next)) } } } } }

It gave the following code, which at first looks good. It's an improvement over Claude Sonnet (which forgot the T: Clone bound, and thought Clone returned a Result<> for some reason).

However on closer look it removed the crucial `self.prev = None` line which means the iterator continues infinitely

21.12.2024 13:07 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
impl<'a, T, I: Iterator<Item = &'a T>> Iterator for PairwiseResults<'a, T, I> {
    type Item = Pair<&'a T>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.iterator.next() {
            None => {
                let result = self.prev.map(Last);
                self.prev = None;
                result
            },
            Some(next) => {
                let temp = self.prev;
                self.prev = Some(next);
                match temp {
                    None => Some(First(next)),
                    Some(prev) => Some(Middle(prev, next))
                }
            }
        }
    }
}

impl<'a, T, I: Iterator<Item = &'a T>> Iterator for PairwiseResults<'a, T, I> { type Item = Pair<&'a T>; fn next(&mut self) -> Option<Self::Item> { match self.iterator.next() { None => { let result = self.prev.map(Last); self.prev = None; result }, Some(next) => { let temp = self.prev; self.prev = Some(next); match temp { None => Some(First(next)), Some(prev) => Some(Middle(prev, next)) } } } } }

Tried out the new Gemini 2.0 Flash Thinking Model and it's an improvement but still has hallucination issues.
I gave it the challenge to rewrite this code to not have references (and provided the full code with tests)

21.12.2024 13:07 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Preview
Introducing Limbo: A complete rewrite of SQLite in Rust we forked SQLite with the libSQL project. What would it be like if we just rewrote it?

It seems it's not just a rewrite, they want to add features to SQLite and make it Async turso.tech/blog/introdu.... In that case it makes sense why they'd want Rust's safety for the new features they're adding

10.12.2024 23:36 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
Implementing a trait for all Vectors of a type that implements that trait.

impl<T: ToKafkaBytes> ToKafkaBytes for Vec<T> {
    // write the length of the array, then each item in the array
    fn to_kafka_bytes(self) -> impl IntoIterator<Item = u8> {
        let length = VarInt::new((self.len() + 1) as u32);
        let vec_as_bytes = self.into_iter().flat_map(|item| item.to_kafka_bytes());
        length.to_kafka_bytes().into_iter().chain(vec_as_bytes)
    }
}

Implementing a trait for all Vectors of a type that implements that trait. impl<T: ToKafkaBytes> ToKafkaBytes for Vec<T> { // write the length of the array, then each item in the array fn to_kafka_bytes(self) -> impl IntoIterator<Item = u8> { let length = VarInt::new((self.len() + 1) as u32); let vec_as_bytes = self.into_iter().flat_map(|item| item.to_kafka_bytes()); length.to_kafka_bytes().into_iter().chain(vec_as_bytes) } }

This year, instead of Advent of Code I’m doing CodeCrafters and building a mini Kafka github.com/Wattsy2020/r...
It’s quite interesting, so far I’ve learnt that the Kafka Protocol is a bit janky
Also I’m liking the trait system in Rust, it’s handy to implement a trait for a whole group of types

09.12.2024 03:09 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

Good article! I liked it because I've dabbled in Haskell but never used it for anything practical. Would be interesting to learn how it is to say, write a microservice with FP. Is it that much better than imperative code despite the less mature ecosystem?

05.12.2024 11:03 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

@liam271 is following 20 prominent accounts