#Control flow - partially shared functionality (before/after)?

18 messages · Page 1 of 1 (latest)

winged sphinx
#

Just curious, is there a more idiomatic way to do something like this?

match action {
  // ...

  "Import" | "Execute" => {
    // a bunch of code that should be run either way...

    if action == "Import" {
      // some stuff for Import
    } else {
      // some other stuff for Execute
    }
  }
  
  // ...
}

and also is there better way to do something like this? (same thing but the "different code" part is before the shared code instead of after

match action {
  // ...
}

if let "Import" | "Execute" = action {
  // stuff to do after
}
#

besides just moving it to a function i guess

#

Control flow - partially shared functionality (before/after)?

fierce pumice
#

You could create a lamba that has the common code inside of it, then just match for import and execute individually and call the lambda on each branch.

winged sphinx
fierce pumice
winged sphinx
#

oh bruh :o

#

gonna try putting something together, thanks

#

o o f ;---;

#

on one branch i'm still using the iterator directly so it won't let me unless i make the closure take it as a parameter

fierce pumice
#

F, I guess if statements for you :P

#

Or, you could make the closure take the iterator as an argument

#

Then call ir with the iterator:

let args = |spl| spl.collect,...

winged sphinx
#

yeah that's what fixed the errors from the last pic except it requires type annotations 😭

fierce pumice
#

👍

winged sphinx
#

this is a shorter version of what i have so far... should probably be broken up more but yeah

/// returns the new state (`None` = no change)
fn execute_normal(
    &self,
    line: &str,
    out: &mut Vec<String>,
    links: &mut Vec<Link>,
) -> Result<Option<ComptimeState>> {
    if line.starts_with(COMMENT_PREFIX) {
        return Ok(None);
    }

    // split into command and arguments, but the arguments are optional
    let mut split = line.split_whitespace();
    let Some(command) = split.next() else {
        return Ok(None);
    };

    fn join(split: SplitWhitespace) -> String {
        split.collect::<Vec<_>>().join(" ")
    }

    fn resolve_script(split: SplitWhitespace) -> Result<Script> {
        let path = PathBuf::from(join(split));

        let contents = ScriptPath(path).resolve()?;
        Ok(Script::from(contents))
    }

    match command {
        "Echo" => {
            out.push(join(split));
        }
        // ...

        "Import" => {
            resolve_script()?.execute(&mut vec![], links)?;
        }

        "Execute" => {
            resolve_script()?.execute(out, links)?;
        }

        // ...
        "Quit" => return Ok(Some(ComptimeState::Quit)),

        _ => {
            return Err(ScriptError::NoSuchCommand);
        }
    };

    Ok(None)
}
#

tbh could just move those nested functions outside to make it less complicated to read through

#

or write a generic one that works on any iterator over strings but at that point why not just .collect::<Vec<_>>().join(" ") instead of importing that :P