Prechádzať zdrojové kódy

Refactor argument order of string module functions

Mads Møller Jensen 1 rok pred
rodič
commit
838dc02a45

+ 13 - 12
examples/tests/strings.nbt

@@ -1,10 +1,10 @@
 assert_eq(str_length(""), 0)
 assert_eq(str_length("foo"), 3)
 
-assert_eq(str_slice("hello world", 0, 5), "hello")
-assert_eq(str_slice("hello world", 6, 11), "world")
-assert_eq(str_slice("hello world", 0, 0), "")
-assert_eq(str_slice("hello world", 0, 100), "")
+assert_eq(str_slice(0, 5, "hello world"), "hello")
+assert_eq(str_slice(6, 11, "hello world"), "world")
+assert_eq(str_slice(0, 0, "hello world"), "")
+assert_eq(str_slice(0, 100, "hello world"), "")
 
 assert_eq(chr(65), "A")
 assert_eq(chr(97), "a")
@@ -14,14 +14,15 @@ assert_eq(ord("A"), 65)
 assert_eq(ord("a"), 97)
 assert_eq(ord("❤"), 0x2764)
 
-assert_eq(str_append("foo", "bar"), "foobar")
+assert_eq(str_append("bar", "foo"), "foobar")
+assert_eq(str_prepend("foo", "bar"), "foobar")
 
-assert(str_contains("hello world", "hello"))
-assert(str_contains("hello world", "world"))
-assert_eq(str_contains("hello world", "HELLO"), false)
+assert(str_contains("hello", "hello world"))
+assert(str_contains("world", "hello world"))
+assert_eq(str_contains("HELLO", "hello world"), false)
 
-assert_eq(str_replace("hello world", "hello", "HEY"), "HEY world")
-assert_eq(str_replace("xxx", "x", "yY"), "yYyYyY")
-assert_eq(str_replace("a b", " ", "   "), "a   b")
+assert_eq(str_replace("hello", "HEY", "hello world"), "HEY world")
+assert_eq(str_replace("x", "yY", "xxx"), "yYyYyY")
+assert_eq(str_replace(" ", "   ", "a b"), "a   b")
 
-assert_eq(str_repeat("xy", 3), "xyxyxy")
+assert_eq(str_repeat(3, "xy"), "xyxyxy")

+ 4 - 4
numbat/modules/core/lists.nbt

@@ -182,9 +182,9 @@ fn join(xs: List<String>, sep: String) =
 fn split(input: String, separator: String) -> List<String> =
   if input == ""
     then []
-    else if !str_contains(input, separator)
+    else if !str_contains(separator, input)
       then [input]
-      else cons(str_slice(input, 0, idx_separator),
-                split(str_slice(input, idx_separator + str_length(separator), str_length(input)), separator))
+      else cons(str_slice(0, idx_separator, input),
+                split(str_slice(idx_separator + str_length(separator), str_length(input), input), separator))
   where
-    idx_separator = str_find(input, separator)
+    idx_separator = str_find(separator, input)

+ 30 - 24
numbat/modules/core/strings.nbt

@@ -7,8 +7,8 @@ use core::error
 fn str_length(s: String) -> Scalar
 
 @description("Subslice of a string")
-@example("str_slice(\"Numbat\", 3, 6)")
-fn str_slice(s: String, start: Scalar, end: Scalar) -> String
+@example("str_slice(3, 6, \"Numbat\")")
+fn str_slice(start: Scalar, end: Scalar, s: String) -> String
 
 @description("Get a single-character string from a Unicode code point.")
 @example("0x2764 -> chr")
@@ -27,43 +27,49 @@ fn lowercase(s: String) -> String
 fn uppercase(s: String) -> String
 
 @description("Concatenate two strings")
-@example("str_append(\"Numbat\", \"!\")")
-fn str_append(a: String, b: String) -> String = "{a}{b}"
+@example("str_append(\"!\", \"Numbat\")")
+fn str_append(a: String, str: String) -> String = "{str}{a}"
+
+@description("Concatenate two strings")
+@example("str_prepend(\"Numbat\", \"!\")")
+fn str_prepend(a: String, str: String) -> String = "{a}{str}"
 
 @description("Find the first occurrence of a substring in a string")
-@example("str_find(\"Numbat is a statically typed programming language.\", \"typed\")")
-fn str_find(haystack: String, needle: String) -> Scalar =
+@example("str_find(\"typed\", \"Numbat is a statically typed programming language.\")")
+fn str_find(needle: String, haystack: String) -> Scalar =
   if len_haystack == 0
     then -1
-    else if str_slice(haystack, 0, str_length(needle)) == needle
+    else if str_slice(0, str_length(needle), haystack) == needle
       then 0
-      else if str_find(tail_haystack, needle) == -1
+      else if str_find(needle, tail_haystack) == -1
         then -1
-        else 1 + str_find(tail_haystack, needle)
+        else 1 + str_find(needle, tail_haystack)
   where len_haystack = str_length(haystack)
-    and tail_haystack = str_slice(haystack, 1, len_haystack)
+    and tail_haystack = str_slice(1, len_haystack, haystack)
 
 @description("Check if a string contains a substring")
-@example("str_contains(\"Numbat is a statically typed programming language.\", \"typed\")")
-fn str_contains(haystack: String, needle: String) -> Bool =
-  str_find(haystack, needle) != -1
+@example("str_contains(\"typed\", \"Numbat is a statically typed programming language.\")")
+fn str_contains(needle: String, haystack: String) -> Bool =
+  str_find(needle, haystack) != -1
 
 @description("Replace all occurrences of a substring in a string")
-@example("str_replace(\"Numbat is a statically typed programming language.\", \"statically typed programming language\", \"scientific calculator\")")
-fn str_replace(s: String, pattern: String, replacement: String) -> String =
+@example("str_replace(\"statically typed programming language\", \"scientific calculator\", \"Numbat is a statically typed programming language.\")")
+fn str_replace(pattern: String, replacement: String, s: String) -> String =
   if pattern == ""
     then s
-    else if str_contains(s, pattern)
-           then if str_slice(s, 0, str_length(pattern)) == pattern
-               then str_append(replacement, str_replace(str_slice(s, str_length(pattern), str_length(s)), pattern, replacement))
-               else str_append(str_slice(s, 0, 1), str_replace(str_slice(s, 1, str_length(s)), pattern, replacement))
-           else s
+    else if str_contains(pattern, s)
+      then if str_slice(0, pattern_length, s) == pattern
+          then (s |> str_slice(pattern_length, s_length) |> str_replace(pattern, replacement) |> str_prepend(replacement))
+          else (s |> str_slice(             1, s_length) |> str_replace(pattern, replacement) |> str_prepend(str_slice(0, 1, s)))
+      else s
+  where s_length = str_length(s)
+    and pattern_length = str_length(pattern)
 
 @description("Repeat the input string `n` times")
-@example("str_repeat(\"abc\", 4)")
-fn str_repeat(a: String, n: Scalar) -> String =
+@example("str_repeat(4, \"abc\")")
+fn str_repeat(n: Scalar, a: String) -> String =
   if n > 0
-    then str_append(a, str_repeat(a, n - 1))
+    then str_prepend(a, str_repeat(n - 1, a))
     else ""
 
 fn _bin_digit(x: Scalar) -> String =
@@ -94,7 +100,7 @@ fn base(b: Scalar, x: Scalar) -> String =
     then "-{base(b, -x)}"
     else if x < b
       then _digit_in_base(b, x)
-      else str_append(base(b, floor(x / b)), _digit_in_base(b, mod(x, b)))
+      else str_prepend(base(b, floor(x / b)), _digit_in_base(b, mod(x, b)))
 
 @description("Get a binary representation of a number.")
 @example("42 -> bin")

+ 2 - 2
numbat/modules/datetime/functions.nbt

@@ -47,8 +47,8 @@ fn today() -> DateTime = datetime("{_today_str()} 00:00:00")
 @description("Parses a string (only date) into a `DateTime` object.")
 @example("date(\"2022-07-20\")")
 fn date(input: String) -> DateTime =
-  if str_contains(input, " ")
-    then datetime(str_replace(input, " ", " 00:00:00 "))
+  if str_contains(" ", input)
+    then datetime(str_replace(" ", " 00:00:00 ", input))
     else datetime("{input} 00:00:00")
 
 @description("Parses a string (time only) into a `DateTime` object.")

+ 4 - 4
numbat/modules/datetime/human.nbt

@@ -8,10 +8,10 @@ fn _human_join(a: String, b: String) -> String =
   if a == "" then b else if b == "" then a else "{a} + {b}"
 
 fn _prettier(str: String) -> String =
-    if str_slice(clean_str, 0, 2) == "0 " then ""
-    else if str_slice(clean_str, 0, 2) == "1 " then str_slice(clean_str, 0, str_length(clean_str) - 1)
+    if str_slice(0, 2, clean_str) == "0 " then ""
+    else if str_slice(0, 2, clean_str) == "1 " then str_slice( 0, str_length(clean_str) - 1, clean_str)
     else clean_str
-  where clean_str = str_replace(str, ".0 ", " ")
+  where clean_str = str_replace(".0 ", " ", str)
 
 fn _human_years(time: Time)   -> String = "{(time -> years)   /  year   |> floor} years"   -> _prettier
 fn _human_months(time: Time)  -> String = "{(time -> months)  /  month  |> round} months"  -> _prettier
@@ -36,7 +36,7 @@ fn _human_recurse(t: Time, result: String, time_unit: String) -> String =
 fn _year_month_approx(t: Time) -> String = _human_join(the_years -> _human_years, t - the_years -> _human_months)
   where the_years = t |> floor_in(year)
 
-fn _human_manage_past(str: String, time: Time) = str_append(str, if time < 0 s then " ago" else "")
+fn _human_manage_past(str: String, time: Time) = str_prepend(str, if time < 0 s then " ago" else "")
 
 fn _human_for_long_duration(human_days: String, human_years: String) -> String =
   "{human_days} (approx. {human_years})"

+ 1 - 1
numbat/modules/extra/color.nbt

@@ -37,7 +37,7 @@ fn color_rgb_float(color: Color) -> String =
 @description("Convert a color to its hexadecimal representation.")
 @example("rgb(225, 36, 143) -> color_hex")
 fn color_hex(color: Color) -> String =
-  str_append("#", str_replace(str_replace("{color -> _color_to_scalar -> hex:>8}", "0x", ""), " ", "0"))
+  str_prepend("#", str_replace(" ", "0", str_replace("0x", "", "{color -> _color_to_scalar -> hex:>8}")))
 
 let black: Color = rgb(0, 0, 0)
 let white: Color = rgb(255, 255, 255)

+ 1 - 1
numbat/modules/plot/common.nbt

@@ -1,7 +1,7 @@
 use core::quantities
 use core::strings
 
-fn _unit_name<A: Dim>(x: A) -> String = str_replace("{unit_of(x)}", "1 ", "")
+fn _unit_name<A: Dim>(x: A) -> String = str_replace("1 ", "", "{unit_of(x)}")
 
 fn _is_scalar<A: Dim>(x: A) -> Bool = "{unit_of(x)}" == "1"
 

+ 1 - 1
numbat/src/ffi/strings.rs

@@ -19,9 +19,9 @@ pub fn uppercase(mut args: Args) -> Result<Value> {
 }
 
 pub fn str_slice(mut args: Args) -> Result<Value> {
-    let input = string_arg!(args);
     let start = quantity_arg!(args).unsafe_value().to_f64() as usize;
     let end = quantity_arg!(args).unsafe_value().to_f64() as usize;
+    let input = string_arg!(args);
 
     let output = input.get(start..end).unwrap_or_default();