Show HN:val——一款用Rust编写的任意精度计算器语言
Show HN: val – An arbitrary precision calculator language

原始链接: https://github.com/terror/val

Val 是一款使用 Rust 的 chumsky 和 ariadne 库构建的简单、任意精度计算器语言。它可以通过 cargo 安装,也可以通过预编译的二进制文件安装在 Linux、MacOS 和 Windows 上。该语言提供了一个命令行界面 (CLI),可以通过 `val` 命令访问,该命令既可以在 REPL 模式下使用,也可以用来执行文件。 CLI 支持诸如 `-e` 用于直接计算表达式之类的选项,并通过 `-h` 显示帮助信息。Val 语言的特性包括 `if`、`while`、`fn` 等语句,以及算术、逻辑和比较运算符等表达式。它支持数值型(浮点数)、布尔型、字符串型和列表型数据类型。Val 还拥有高阶函数,允许将函数视为值。 Val 具有许多内置函数和常量,包括数学常数(π,e)、三角函数、双曲函数、对数函数、数值函数(sqrt,ceil,floor,abs)以及集合的实用函数(len,sum)。它还提供类型转换函数、I/O 函数(print,println,input)、字符串操作函数(split,join)和程序终止函数(exit,quit)。

Hacker News 上分享了一个名为“val”(github.com/terror)的基于 Rust 的任意精度计算器语言,文章称赞了使用 `chumsky` 解析器组合器、`rustyline` 和 `ariadne` 错误报告板条箱带来的积极的开发者体验。该项目仍在开发中。 “jasonjmcghee” 回复称赞了该项目,并分享了一个类似的项目,该项目专注于使用 Cranelift 进行实时 JIT 编译,并在类似的领域实现。 “occamatl” 指出在计算 `sqrt(10^100)-1` 时计算器出现了一个意外的结果,指出了一个潜在的改进方向。

原文

release crates.io CI docs.rs dependency status

val (eval) is a simple arbitrary precision calculator language built on top of chumsky and ariadne.

Screenshot 2025-04-16 at 1 57 23 AM

val should run on any system, including Linux, MacOS, and the BSDs.

The easiest way to install it is by using cargo, the Rust package manager:

Pre-built binaries for Linux, MacOS, and Windows can be found on the releases page.

The primary way to use val is via the provided command-line interface. There is currently ongoing work on a Rust library and web playground, which will provide a few extra ways to interact with the runtime.

Below is the output of val --help, which describes some of the arguments/options we support:

Usage: val [OPTIONS] [FILENAME]

Arguments:
  [FILENAME]

Options:
  -e, --expression <EXPRESSION>
  -h, --help                     Print help
  -V, --version                  Print version

Running val on its own will spawn a repl (read–eval–print loop) environment, where you can evaluate arbitrary val code and see its output immediately. We use rustyline for its implementation, and we support a few quality of life features:

  • Syntax highlighting (see image above)
  • Persistent command history
  • Emacs-style editing support by default
  • Filename completions
  • Hints (virtual text pulled from history)

The val language supports not only expressions, but quite a few statements as well. You may want to save val programs and execute them later, so the command-line interface provides a way to evaluate entire files.

For instance, lets say you have the following val program at factorial.val:

fn factorial(n) {
  if (n <= 1) {
    return 1
  } else {
    return n * factorial(n - 1)
  }
}

println(factorial(5));

You can execute this program by running val factorial.val, which will write to standard output 120.

Lastly, you may want to evaluate a val expression and use it within another program. The tool supports executing arbitrary expressions inline using the --expression or -e option:

val -e 'sin(2) * e ^ pi * cos(sum([1, 2, 3]))'
16.481455793912883

n.b. The --expression option and filename argument are mutually exclusive.

This section describes some of the language features val implements in detail, and should serve as a guide to anyone wanting to write a val program.

val supports a few statement constructs such as if, while, loop, fn, return, etc. Check out the grammar for all of the various statement types.

Here's an example showcasing most of them in action:

fn fib(n) {
  if (n <= 1) { return n }
  return fib(n - 1) + fib(n - 2)
}

i = 0

while (i < 10) {
  println('fib(' + i + ') = ' + fib(i))
  i = i + 1
}

val supports a variety of expressions that can be combined to form more complex operations:

Category Operation Syntax Example
Arithmetic Addition a + b 1 + 2
Subtraction a - b 5 - 3
Multiplication a * b 4 * 2
Division a / b 10 / 2
Modulo a % b 7 % 3
Exponentiation a ^ b 2 ^ 3
Negation -a -5
Logical And a && b true && false
Or a || b true || false
Not !a !true
Comparison Equal a == b x == 10
Not Equal a != b y != 20
Less Than a < b a < b
Less Than or Equal a <= b i <= 5
Greater Than a > b count > 0
Greater Than or Equal a >= b value >= 100
Other Function Call function(args) sin(x)
List Indexing list[index] numbers[0]
List Creation [item1, item2, ...] [1, 2, 3]
List Concatenation list1 + list2 [1, 2] + [3, 4]
String Concatenation string1 + string2 "Hello, " + name
Variable Reference identifier x

val has several primitive value types:

Numeric values are represented as double-precision floating point numbers:

x = 42
y = 3.14159
z = -5

Boolean values represent truth values:

a = true
b = false
c = a && b
d = a || b
e = !a

Text values enclosed in single or double quotes:

greeting = "Hello"
name = 'World'
message = greeting + ", " + name + "!"

Collections of values of any type:

numbers = [1, 2, 3, 4, 5]
mixed = [1, "two", true, [3, 4]]
empty = []
first = numbers[0]
numbers[0] = 10
combined = numbers + [6, 7]

A function is a value, and can be used in assignments, passed around to other functions, etc.

Check out the higher order functions example for how this works.

fn reduce(l, f, initial) {
  i = 0

  result = initial

  while (i < len(l)) {
    result = f(result, l[i])
    i = i + 1
  }

  return result
}

fn sum(a, b) {
  return a + b
}

l = [1, 2, 3, 4, 5]

println(reduce(l, sum, 0))

val offers a ton of built-in functions and constants. Below documents them:

Category Function/Constant Description Example
Constants pi Mathematical constant π (≈3.14159) area = pi * r^2
e Mathematical constant e (≈2.71828) growth = e^rate
Trigonometric sin(x) Sine of x (radians) sin(pi/2)
cos(x) Cosine of x (radians) cos(0)
tan(x) Tangent of x (radians) tan(pi/4)
csc(x) Cosecant of x (radians) csc(pi/6)
sec(x) Secant of x (radians) sec(0)
cot(x) Cotangent of x (radians) cot(pi/4)
Inverse Trig asin(x) Arc sine (-1≤x≤1) asin(0.5)
acos(x) Arc cosine (-1≤x≤1) acos(0.5)
arc(x) Arc tangent arc(1)
acsc(x) Arc cosecant (abs(x)≥1) acsc(2)
asec(x) Arc secant (abs(x)≥1) asec(2)
acot(x) Arc cotangent acot(1)
Hyperbolic sinh(x) Hyperbolic sine sinh(1)
cosh(x) Hyperbolic cosine cosh(1)
tanh(x) Hyperbolic tangent tanh(1)
Logarithmic ln(x) Natural logarithm ln(e)
log2(x) Base-2 logarithm log2(8)
log10(x) Base-10 logarithm log10(100)
e(x) e raised to power x e(2)
Numeric sqrt(x) Square root (x≥0) sqrt(16)
ceil(x) Round up to integer ceil(4.3)
floor(x) Round down to integer floor(4.7)
abs(x) Absolute value abs(-5)
Collections len(x) Length of list or string len("hello")
sum(list) Sum list elements sum([1,2,3])
Conversion int(x) Convert to integer int("42")
float(x) Convert to float float("3.14")
bool(x) Convert to boolean bool(1)
list(x) Convert to list list("abc")
I/O print(...) Print without newline print("Hello")
println(...) Print with newline println("World")
input([prompt]) Read line from stdin name = input("Name: ")
String split(str, delim) Split string split("a,b,c", ",")
join(list, delim) Join list elements join(["a","b"], "-")
Program exit([code]) Exit program exit(1)
quit([code]) Alias for exit quit(0)

bc(1) - An arbitrary precision calculator language

联系我们 contact @ memedata.com