โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
โข Option
โข Result
โข The ? operator propagates errors up the call stack concisely
โข Combinators like .map(), .and_then(), .unwrap_or() chain fallible operations
โข The compiler forces you to handle every error case โ no silent failures
fn split<T: Clone>(lst: &[T], n: usize) -> (Vec<T>, Vec<T>) {
let n = n.min(lst.len()); // clamp: never go past end
(lst[..n].to_vec(), lst[n..].to_vec())
}
| Concept | OCaml | Rust |
|---|---|---|
| Slice syntax | `List.filteri` / recursive take+drop | `lst[..n]` and `lst[n..]` |
| Bounds safety | Runtime exception on bad index | `.min(lst.len())` clamp, then safe slice |
| Return type | `'a list * 'a list` (tuple) | `(Vec<T>, Vec<T>)` (tuple) |
| Copying elements | `List.map` with identity | `.to_vec()` โ clones the slice |
| Destructuring | `let (l, r) = split ...` | `let (left, right) = split(...)` |
// Split List โ 99 Problems #17
// Split a list into two parts at position n.
// split ['a','b','c','d','e','f','g','h','i','k'] 3
// โ (['a','b','c'], ['d','e','f','g','h','i','k'])
fn split<T: Clone>(lst: &[T], n: usize) -> (Vec<T>, Vec<T>) {
let n = n.min(lst.len());
(lst[..n].to_vec(), lst[n..].to_vec())
}
/// Recursive version.
fn split_rec<T: Clone>(lst: &[T], n: usize) -> (Vec<T>, Vec<T>) {
fn aux<T: Clone>(lst: &[T], n: usize, acc: Vec<T>) -> (Vec<T>, Vec<T>) {
match (lst, n) {
([], _) => (acc, vec![]),
(rest, 0) => (acc, rest.to_vec()),
([head, tail @ ..], k) => {
let mut new_acc = acc;
new_acc.push(head.clone());
aux(tail, k - 1, new_acc)
}
}
}
aux(lst, n, vec![])
}
fn main() {
let input = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k'];
let (left, right) = split(&input, 3);
println!("Input: {:?}", input);
println!("Left: {:?}", left);
println!("Right: {:?}", right);
let (l2, r2) = split(&input, 0);
println!("Split at 0: {:?}, {:?}", l2, r2);
let (l3, r3) = split(&input, 100);
println!("Split at 100 (> len): {:?}, {:?}", l3, r3);
let (lr, rr) = split_rec(&input, 3);
println!("Rec split: {:?}, {:?}", lr, rr);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_split_basic() {
let input = vec!['a', 'b', 'c', 'd', 'e'];
assert_eq!(
split(&input, 3),
(vec!['a', 'b', 'c'], vec!['d', 'e'])
);
}
#[test]
fn test_split_at_zero() {
let input = vec![1, 2, 3];
assert_eq!(split(&input, 0), (vec![], vec![1, 2, 3]));
}
#[test]
fn test_split_beyond_length() {
let input = vec![1, 2, 3];
assert_eq!(split(&input, 10), (vec![1, 2, 3], vec![]));
}
#[test]
fn test_split_rec_matches() {
let input = vec!['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k'];
assert_eq!(split(&input, 3), split_rec(&input, 3));
}
}
(* Split List *)
(* OCaml 99 Problems #17 *)
(* Implementation for example 17 *)
(* Tests *)
let () =
(* Add tests *)
print_endline "โ OCaml tests passed"