# HG changeset patch # User Tuomo Valkonen # Date 1729486423 18000 # Node ID 121cf065e9ede36f4eb71028cac95866406750e3 # Parent daf0e3a70c79b4831093bdc61b88ae4c3d68584c Simplify iterate facility for-loop mechanism diff -r daf0e3a70c79 -r 121cf065e9ed src/iterate.rs --- a/src/iterate.rs Sun Oct 20 23:28:16 2024 -0500 +++ b/src/iterate.rs Sun Oct 20 23:53:43 2024 -0500 @@ -19,6 +19,7 @@ .. Default::default() }; let mut x = 1 as float; +# let mut iter_clone = iter.clone(); iter.iterate(|state|{ // This is our computational step x = x + x.sqrt(); @@ -26,7 +27,17 @@ // return current value when requested return x }) -}) +}); +// or alternatively (avoiding problems with moves) +# iter = iter_clone; +for state in iter.iter() { + // This is our computational step + x = x + x.sqrt(); + state.if_verbose(||{ + // return current value when requested + return x + }) +} ``` There is no colon after `state.if_verbose`, because we need to return its value. If you do something after the step, you need to store the result in a variable and return it from the main computational step afterwards. @@ -52,8 +63,8 @@ use std::marker::PhantomData; use std::time::Duration; use std::error::Error; +use std::cell::RefCell; use std::rc::Rc; -use std::cell::Cell; use crate::types::*; use crate::logger::*; @@ -392,11 +403,7 @@ /// Returns an an [`std::iter::Iterator`] that can be used in a `for`-loop. fn iter(self) -> AlgIteratorIterator { AlgIteratorIterator { - algi : self.prepare(), - result : Rc::new(AlgIteratorResponse{ - expected_iter : 0, - response : Cell::new(Step::Quiet) - }) + algi : Rc::new(RefCell::new(self.prepare())), } } } @@ -1015,50 +1022,27 @@ // New for-loop interface // -struct AlgIteratorResponse { - expected_iter : usize, - response : Cell>, -} pub struct AlgIteratorIterator { - algi : I, - result : Rc>, + algi : Rc>, } pub struct AlgIteratorIteration { state : I::State, - result : Rc>, -} - -impl AlgIteratorIterator { - fn poststep(&mut self, even_if_quiet : bool) { - let res = self.result.response.take(); - if !even_if_quiet { - if let Step::Quiet = res { - return - } - } - self.algi.poststep(res); - } + algi : Rc>, } impl std::iter::Iterator for AlgIteratorIterator { type Item = AlgIteratorIteration; fn next(&mut self) -> Option { - self.poststep(true); - self.algi.prestep().map(|state| AlgIteratorIteration { + let algi = self.algi.clone(); + RefCell::borrow_mut(&self.algi).prestep().map(|state| AlgIteratorIteration { state, - result : self.result.clone(), + algi, }) } } -impl Drop for AlgIteratorIterator { - fn drop(&mut self) { - self.poststep(false) - } -} - /// Types of errors that may occur #[derive(Debug,PartialEq,Eq)] pub enum IterationError { @@ -1083,13 +1067,18 @@ } /// Version of [`Self::if_verbose`] that propagates errors instead of panicking. - pub fn if_verbose_check(self, mut calc_objective : impl FnMut() -> I::Input) + pub fn if_verbose_check(self, calc_objective : impl FnMut() -> I::Input) -> Result<(), IterationError> { - if self.result.expected_iter != self.state.iteration() { + let mut algi = match RefCell::try_borrow_mut(&self.algi) { + Err(_) => return Err(IterationError::ReportingOrderingError), + Ok(algi) => algi + }; + if self.state.iteration() != algi.iteration() { Err(IterationError::ReportingOrderingError) } else { - let res = calc_objective(); - self.result.response.replace(Step::Result(res, self.state)); + let res : Step + = self.state.if_verbose(calc_objective); + algi.poststep(res); Ok(()) } } @@ -1151,4 +1140,44 @@ .collect::>()) } } + + #[test] + fn iteration_for_loop() { + let options = AlgIteratorOptions{ + max_iter : 10, + verbose_iter : Verbose::Every(3), + .. Default::default() + }; + + { + let mut start = 1 as int; + for state in options.iter() { + start = start * 2; + state.if_verbose(|| start) + } + assert_eq!(start, (2 as int).pow(10)); + } + + { + let mut start = 1 as int; + let mut log = Logger::new(); + let factory = options.instantiate() + .with_iteration_number() + .into_log(&mut log); + for state in factory.iter() { + start = start * 2; + state.if_verbose(|| start) + } + assert_eq!(start, (2 as int).pow(10)); + assert_eq!(log.data() + .iter() + .map(|LogItem{ data : v, iter : _ }| v.clone()) + .collect::>(), + (1..10).map(|i| (2 as int).pow(i)) + .skip(2) + .step_by(3) + .collect::>()) + } + } + } diff -r daf0e3a70c79 -r 121cf065e9ed src/sets.rs --- a/src/sets.rs Sun Oct 20 23:28:16 2024 -0500 +++ b/src/sets.rs Sun Oct 20 23:53:43 2024 -0500 @@ -9,7 +9,7 @@ use crate::euclidean::Dot; use serde::Serialize; -mod cube; +pub mod cube; pub use cube::Cube; /// Trait for arbitrary sets. The parameter `U` is the element type.