Simplify iterate facility for-loop mechanism dev

Sun, 20 Oct 2024 23:53:43 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Sun, 20 Oct 2024 23:53:43 -0500
branch
dev
changeset 41
121cf065e9ed
parent 40
daf0e3a70c79
child 42
b4d369698556

Simplify iterate facility for-loop mechanism

src/iterate.rs file | annotate | diff | comparison | revisions
src/sets.rs file | annotate | diff | comparison | revisions
--- 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<Self::Iter> {
         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<I : AlgIterator> {
-    expected_iter : usize,
-    response : Cell<Step<I::Input, I::State>>,
-}
 pub struct AlgIteratorIterator<I : AlgIterator> {
-    algi : I,
-    result : Rc<AlgIteratorResponse<I>>,
+    algi : Rc<RefCell<I>>,
 }
 
 pub struct AlgIteratorIteration<I : AlgIterator> {
     state : I::State,
-    result : Rc<AlgIteratorResponse<I>>,
-}
-
-impl<I : AlgIterator> AlgIteratorIterator<I> {
-    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<RefCell<I>>,
 }
 
 impl<I : AlgIterator> std::iter::Iterator for AlgIteratorIterator<I> {
     type Item = AlgIteratorIteration<I>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        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<I : AlgIterator> Drop for AlgIteratorIterator<I> {
-    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<I::Input, I::State, std::convert::Infallible>
+                = self.state.if_verbose(calc_objective);
+            algi.poststep(res);
             Ok(())
         }
     }
@@ -1151,4 +1140,44 @@
                              .collect::<Vec<int>>())
         }
     }
+
+    #[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::<Vec<int>>(),
+                      (1..10).map(|i| (2 as int).pow(i))
+                             .skip(2)
+                             .step_by(3)
+                             .collect::<Vec<int>>())
+        }
+    }
+
 }
--- 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.

mercurial