change loop function so you can write ().loop(() -> do_smth)

This commit is contained in:
Mark 2023-11-08 15:11:28 +01:00
parent cab81059f3
commit 39fca08541
5 changed files with 37 additions and 23 deletions

View File

@ -1,10 +1,10 @@
total := 0.0 total := 0.0
{() -> { ().loop(() -> {
("Total: ", total, ". Type a number to change.").concat.println ("Total: ", total, ". Type a number to change.").concat.println
().read_line.trim.parse_float.try(( ().read_line.trim.parse_float.try((
n -> &total = (total, n).sum, n -> &total = (total, n).sum,
// not a number, so return a 1-tuple to break from the loop // not a number, so return a 1-tuple to break from the loop
() -> (()) () -> (())
)) ))
}}.loop })
"Goodbye.".println "Goodbye.".println

View File

@ -5,7 +5,7 @@
current := 0.0 current := 0.0
{() -> { ().loop(() -> {
("[ ", current, " ]").concat.println ("[ ", current, " ]").concat.println
input := ().read_line.trim input := ().read_line.trim
num := (input, 1).substring.trim.parse_float.try(( num := (input, 1).substring.trim.parse_float.try((
@ -24,4 +24,4 @@ current := 0.0
} else if input.eq("exit") { } else if input.eq("exit") {
(()) (())
} }
}}.loop })

View File

@ -1,5 +1,5 @@
gcd := vals -> { gcd := vals -> {
() -> { ().loop(() -> {
(a, b) := vals (a, b) := vals
if a.eq(b) if a.eq(b)
(a) (a)
@ -7,8 +7,8 @@ gcd := vals -> {
&vals = (a, b.subtract(a)) &vals = (a, b.subtract(a))
else else
&vals = (a.subtract(b), b) &vals = (a.subtract(b), b)
} })
}.loop }
get_num := () -> { get_num := () -> {
line := ().read_line.trim line := ().read_line.trim

View File

@ -17,7 +17,7 @@ split_once := (s, delim) -> {
split_ := (s, delim, require_nonempty) -> { split_ := (s, delim, require_nonempty) -> {
out := (s).as_list out := (s).as_list
&out.pop &out.pop
{ ().loop(
() -> s.split_once(delim).try(( () -> s.split_once(delim).try((
(s1, s2) -> { (s1, s2) -> {
&s = s2 &s = s2
@ -30,7 +30,7 @@ split_ := (s, delim, require_nonempty) -> {
(()) (())
} }
)) ))
}.loop )
out out
} }
@ -62,9 +62,11 @@ read_matrix_line := width -> {
if w.eq(0) { if w.eq(0) {
width = line.len width = line.len
} else { } else {
{() -> if line.len.subtract(w).signum.eq(-1) { ().loop(() ->
&line.push(0.0) if line.len.subtract(w).signum.eq(-1) {
} else (())}.loop &line.push(0.0)
} else (())
)
} }
(line) (line)
} }
@ -87,10 +89,12 @@ matrix_get := (matrix, (line, col)) -> {
leftpad := (str, l) -> { leftpad := (str, l) -> {
str := (str).concat str := (str).concat
d := l.subtract(str.len) d := l.subtract(str.len)
{() -> if d.signum.eq(1) { ().loop(() ->
&str = (" ", str).concat if d.signum.eq(1) {
&d = d.subtract(1) &str = (" ", str).concat
} else {(())}}.loop &d = d.subtract(1)
} else (())
)
str str
} }

View File

@ -13,7 +13,7 @@ use super::Config;
impl Config { impl Config {
/// `deref: fn` clones the value from a reference /// `deref: fn` clones the value from a reference
/// `eq: fn` returns true if all the values are equal, otherwise false. /// `eq: fn` returns true if all the values are equal, otherwise false.
/// `loop: fn` runs a function until it returns (T) instead of (), then returns T. /// `loop: fn` runs a function until it returns (T) instead of (), then returns T. Also works with ((), f) instead of f for ().loop(() -> { ... }) syntax, which may be more readable
/// `try: fn` runs the first valid function with the argument. usage: (arg, (f1, f2, f3)).try /// `try: fn` runs the first valid function with the argument. usage: (arg, (f1, f2, f3)).try
/// NOTE: try's return type may miss some types that can actually happen when using it on tuples, so... don't do ((a, b), (f1, any -> ())).try unless f1 also returns () /// NOTE: try's return type may miss some types that can actually happen when using it on tuples, so... don't do ((a, b), (f1, any -> ())).try unless f1 also returns ()
/// `len: fn` gets the length of strings or tuples /// `len: fn` gets the length of strings or tuples
@ -180,7 +180,11 @@ impl Config {
info_check: Arc::new(Mutex::new(CheckInfo::neverused())), info_check: Arc::new(Mutex::new(CheckInfo::neverused())),
out: Arc::new(|a, _i| { out: Arc::new(|a, _i| {
let mut o = Type::empty(); let mut o = Type::empty();
for t in &a.types { for t in a.types.iter().flat_map(|v| if let Some(t) = v.as_any().downcast_ref::<data::tuple::TupleT>() {
if let Some(t) = t.0.get(1) {
t.types.iter().collect::<Vec<_>>()
} else { [v].into_iter().collect() }
} else { [v].into_iter().collect() }) {
if let Some(t) = t.as_any().downcast_ref::<data::function::FunctionT>() { if let Some(t) = t.as_any().downcast_ref::<data::function::FunctionT>() {
for t in (t.0)(&Type::empty_tuple())?.types { for t in (t.0)(&Type::empty_tuple())?.types {
if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() { if let Some(t) = t.as_any().downcast_ref::<data::tuple::TupleT>() {
@ -200,15 +204,21 @@ impl Config {
Ok(o) Ok(o)
}), }),
run: Arc::new(|a, _i| { run: Arc::new(|a, _i| {
if let Some(r) = a.get().as_any().downcast_ref::<data::function::Function>() { let a = a.get();
let delay_drop;
let function = if let Some(function) = a.as_any().downcast_ref::<data::function::Function>() {
function
} else if let Some(r) = a.as_any().downcast_ref::<data::tuple::Tuple>() {
delay_drop = r.0[1].get();
delay_drop.as_any().downcast_ref::<data::function::Function>().unwrap()
} else {
unreachable!("called loop on non-function")
};
loop { loop {
if let Some(r) = r.run(Data::empty_tuple()).one_tuple_content() { if let Some(r) = function.run(Data::empty_tuple()).one_tuple_content() {
break r; break r;
} }
} }
} else {
unreachable!("called loop on non-function")
}
}), }),
}), }),
) )