diff --git a/src/ast/ast.rs b/src/ast/ast.rs
index b18fb6070692a9a4fe2cec834a4a4995aaa12147..9daa62ab72963ca4ff3e6fd4258579bcd6df589b 100644
--- a/src/ast/ast.rs
+++ b/src/ast/ast.rs
@@ -5,7 +5,7 @@ use std::fmt;
 pub type Id = String;
 
 // println!("{:?}", ..)
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub enum NumOrId {
     Num(i32),
     Id(Id),
@@ -24,7 +24,7 @@ impl fmt::Display for NumOrId {
 
 pub type Stmts = Vec<Stmt>;
 
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub enum Stmt {
     Let(Id, NumOrId),
     If(Id, Stmts, Option<Stmts>),
diff --git a/src/ast/main.rs b/src/ast/main.rs
index 825a7ff3e4a83504fcc4fdcebde9ba51fc0b3ec5..a669a9b140452b948a7a82bf49cb4bf816c12b97 100644
--- a/src/ast/main.rs
+++ b/src/ast/main.rs
@@ -30,20 +30,73 @@ fn parse_num_or_id() {
 
 type Error = String;
 
-fn type_check(stmts: &Stmts) -> Result<(), Error> {
-    let r: Result<(), Error> = stmts.iter().try_for_each(|i| match i {
-        Stmt::Let(_, _) => {
-            println!("let");
-            Ok(())
+fn type_check(stmts: &Stmts) -> Result<Id, Error> {
+    let mut last_id = "".to_string();
+    let mut err: Option<Stmt> = None;
+    stmts.iter().for_each(|stmt| match stmt {
+        Stmt::Let(id, _) => {
+            println!("let {} ...", id);
+            last_id = id.to_string();
         }
         Stmt::If(_, _, __) => {
-            println!("if");
-            Err("error in if".to_string())?
+            println!("if has an error");
+            err = Some(stmt.clone());
         }
     });
     println!("here we can do something before returning");
-    r
+    match err {
+        Some(stmt) => Err(format!("error found in statement {:?}", stmt)),
+        None => Ok(last_id),
+    }
 }
+// the above is not ideal, since we have to do a lot of book keeping,
+// also we cannot easily "abort", and thus we cont. even after spotting the error we want to return
+
+fn type_check2(stmts: &Stmts) -> Result<Id, Error> {
+    let mut last_id = "".to_string();
+    let res: Result<Id, Error> = stmts
+        .iter()
+        .try_for_each(|stmt| match stmt {
+            Stmt::Let(id, _) => {
+                println!("let {} ...", id);
+                last_id = id.to_string();
+                Ok(())
+            }
+            Stmt::If(_, _, __) => {
+                println!("if has an error");
+                Err(format!("error found in statement {:?}", stmt))
+            }
+        })
+        .map(|_| Ok(last_id))?;
+    println!("here we can do something before returning");
+    res
+}
+// this is quite good, we can get rid of some book keeping, and we iterate only up to the point where an error occurs.
+// we have to convert the Ok(()) into the last Id (using Result::map)
+// IMHO Result::map should have been named map_ok, since that is what is does, and symmetric to map_err.
+
+fn type_check3(stmts: &Stmts) -> Result<Id, Error> {
+    let res =
+        stmts
+            .iter()
+            .try_fold::<_, _, Result<Id, Error>>("".to_string(), |_, stmt| match stmt {
+                Stmt::Let(id, _) => {
+                    println!("let {} ...", id);
+                    id.to_string();
+                    Ok(id.to_string())
+                }
+                Stmt::If(_, _, __) => {
+                    println!("if has an error");
+                    Err(format!("error found in statement {:?}", stmt))
+                }
+            });
+
+    println!("here we can do something before returning");
+    res
+}
+// this is quite good, we can get rid of some book keeping, and we iterate only up to the point where an error occurs.
+// we have to convert the Ok(()) into the last Id (using Result::map)
+// IMHO Result::map should have been named map_ok, since that is what is does, and symmetric to map_err.
 
 #[test]
 fn test_stmts() {
@@ -53,5 +106,7 @@ fn test_stmts() {
         Stmt::If("b".to_string(), Stmts::new(), None),
         Stmt::Let("c".to_string(), NumOrId::Num(3)),
     ];
-    type_check(&stmts).unwrap();
+    println!("type_check {:?}", type_check(&stmts));
+    println!("type_check2 {:?}", type_check2(&stmts));
+    println!("type_check3 {:?}", type_check2(&stmts));
 }