Skip to content

Instantly share code, notes, and snippets.

@Mroik
Last active February 9, 2024 05:29
Show Gist options
  • Save Mroik/28adfff5fdcebdb050dea06a8bc09da1 to your computer and use it in GitHub Desktop.
Save Mroik/28adfff5fdcebdb050dea06a8bc09da1 to your computer and use it in GitHub Desktop.
Seq generator
use std::{env::args, fmt::Debug};
struct Seq<'a, T> {
items: Vec<T>,
func: &'a dyn Fn(T) -> Option<T>,
place: usize,
}
impl<'a, T> Debug for Seq<'a, T> where T: Debug {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Seq").field("items", &self.items).field("place", &self.place).finish()
}
}
impl<'a, T> Seq<'a, T> {
fn new(f: &'a dyn Fn(T) -> Option<T>, init: T) -> Self where T: Copy {
Seq {
items: vec![init],
func: f,
place: 0,
}
}
fn iter(&'a mut self) -> Iter<'a, T> {
Iter::new(self)
}
}
struct Iter<'a, T> {
items: &'a mut Vec<T>,
func: &'a dyn Fn(T) -> Option<T>,
place: usize,
}
// Unsafe might be required to resolve borrow checks
impl<'a, 'b, T> Iter<'a, T> {
fn new(seq: &'a mut Seq<'b, T>) -> Self {
Self {
items: &mut seq.items,
func: seq.func,
place: 0,
}
}
}
impl<'a, T> Iterator for Iter<'a, T> where T: Copy {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.place += 1;
let ris = match self.items.get(self.place - 1).copied() {
Some(x) => Some(x),
None => {
let last = self.items.last().copied().unwrap();
match (self.func)(last) {
None => {
self.place = 0;
None
},
Some(y) => {
self.items.push(y);
Some(y)
},
}
},
};
ris
}
}
fn collatz(n: u64) -> Option<u64> {
if n == 1 {
return None;
}
let ris = if n % 2 == 1 {
3 * n + 1
} else {
n / 2
};
Some(ris)
}
fn main() {
if args().len() <= 1 {
return;
}
let args: Vec<String> = args().collect();
let mut s = Seq::new(&collatz, args[1].parse().unwrap());
// TODO properly impleemnt iter()
// Vec implements it using unsafe...
for x in s.iter() {
println!("{}", x);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment