knowledge/technology/applications/cli/numbat.md
2024-04-10 08:39:35 +02:00

80 KiB
Raw Blame History

obj repo website
application https://github.com/sharkdp/numbat https://numbat.dev

numbat

Numbat is a statically typed programming language for scientific computations
with first class support for physical dimensions and units.

Number Notation

Numbers in Numbat can be written in the following forms:

  • Integer notation
    • 12345
    • 12_345 — with decimal separators
  • Floating point notation
    • 0.234
    • .234 — without the leading zero
  • Scientific notation
    • 1.234e15
    • 1.234e+15
    • 1e-9
    • 1.0e-9
  • Non-decimal bases notation
    • 0x2A — Hexadecimal
    • 0o52 — Octal
    • 0b101010 — Binary
  • Non-finite numbers
    • NaN — Not a number
    • inf — Infinity

You can use the bin, oct, dec and hex functions to convert numbers to binary, octal, decimal and hexadecimal bases, respectively. You can call those using hex(2^16 - 1), or 2^16 - 1 // hex, but they are also available as targets of the conversion operator ->/to, so you can write expressions like:

Examples:

0xffee to bin
42 ot oct
2^16 - 1 to hex

You can also use base(b) to convert a number to base b:

0xffee to base(2)

Unit Notation

Most units can be entered in the same way that they would appear in textbook calculations. They usually have a long form (meter, degrees, byte, …), a plural form (meters, degrees, bytes), and a short alias (m, °, B).

All SI-accepted units support metric prefixes (mm, cm, km, … or millimeter, centimeter, kilometer, …) and — where sensible — units allow for binary prefixes (MiB, GiB, … or mebibyte, gibibyte, …). Note that the short-form prefixes can only be used with the short version of the unit, and vice versa (that is: kmeter and kilom are not allowed, only km and kilometer).

Units can be combined using mathematical operations such as multiplication, division and exponentiation: kg * m/s^2, km/h, m^2, meter per second.

The following snippet shows various styles of entering units:

2 min + 1 s
150 cm
sin(30°)
50 mph
6 MiB

2 minutes + 1 second
150 centimeters
sin(30 degrees)
50 miles per hour
6 mebibyte

Note that Numbat also allows you to define new units.

Operations and precedence

Numbat operators and other language constructs, ordered by precedence form high to low:

Operation / operator Syntax
square, cube, … , , x⁻¹, …
factorial x!
exponentiation x^y, x**y
multiplication (implicit) x y (whitespace)
unary negation -x
division x per y
division x / y, x ÷ y
multiplication (explicit) x * y, x · y, x × y
subtraction x - y
addition x + y
comparisons x < y, x <= y, x ≤ y, … x == y, x != y
logical negation !x
logical and x && y
logical or x | y
unit conversion x -> y, x → y, x ➞ y, x to y
conditionals if x then y else z
reverse function call x // f

Note that implicit multiplication has a higher precedence than division, i.e. 50 cm / 2 m will be parsed as 50 cm / (2 m).

Also, note that per-division has a higher precedence than /-division. This means 1 / meter per second will be parsed as 1 / (meter per second).

If in doubt, you can always look at the pretty-printing output (second line in the snippet below) to make sure that your input was parsed correctly:

>>> 1 / meter per second

  1 / (meter / second)

    = 1 s/m

Constants

New constants can be introduced with the let keyword:

let pipe_radius = 1 cm
let pipe_length = 10 m
let Δp = 0.1 bar

Definitions may contain a type annotation after the identifier (let Δp: Pressure = 0.1 bar). This annotation will be verified by the type checker. For more complex definitions it can be desirable to add type annotations, as it often improves readability and allows you to catch potential errors early:

let μ_water: DynamicViscosity = 1 mPa·s
let Q: FlowRate = π × pipe_radius^4 × Δp / (8 μ_water × pipe_length)

Unit Conversion

The conversion operator -> attempts to convert the physical quantity on its left hand side to the unit of the expression on its right hand side. This means that you can write an arbitrary expression on the right hand side — but only the unit part will be extracted. For example:

Simple unit conversion:

> 120 km/h -> mph

  = 74.5645 mi/h

Expression on the right hand side:

> 120 m^3 -> km * m^2

  = 0.12 m²·km

Convert x1 to the same unit as x2:

> let x1 = 50 km / h
> let x2 = 3 m/s -> x1

  x2 = 10.8 km/h

Conversion functions

The conversion operator -> (or to) can not just be used for unit conversions, but also for other types of conversions. The way this is set up in Numbat is that you can call x -> f for any function f that takes a single argument of the same type as x.

The following functions are available for this purpose:

# Convert a date and time to a Unix timestamp
now() -> unixtime

# Convert a date and time to a different timezone
now() -> tz("Asia/Kathmandu")

# Convert a duration to days, hours, minutes, seconds
10 million seconds -> human

# Convert a number to its binary representation
42 -> bin

# Convert a number to its octal representation
42 -> oct

# Convert a number to its hexadecimal representation
2^31-1 -> hex

# Convert a number to a custom base
42 -> base(16)

# Convert an ASCII code point number to a character
78 -> chr

# Convert a string to upper/lower case
"numbat is awesome" -> uppercase
"vier bis elf weiße Querbänder" -> lowercase

Note that the tz(…) and base(…) calls above return functions, i.e. the right hand side of the conversion operator is still a function.

Function definitions

Numbat comes with a large number of predefined functions, but it is also possible to add new functions. A function definition is introduced with the fn keyword:

fn max_distance(v: Velocity, θ: Angle) -> Length = v² · sin(2 θ) / g0

This exemplary function computes the maximum distance of a projectile under the influence of Earths gravity. It takes two parameters (The initial velocity v and the launch angle θ), which are both annotated with their corresponding physical dimension (their type). The function returns a distance, and so the return type is specified as Length.

Type inference

The return type annotation may be omitted, but it is often desirable to add it for better readability of the code and in order to catch potential errors.

The parameter types can also (sometimes) be omitted, in which case Numbat tries to infer their type. However, this often leads to overly generic function signatures. For example, consider the following function to compute the kinetic energy of a massive object in motion:

fn kinetic_energy(mass, speed) = 1/2 * mass * speed^2

Without any type annotations, this function has an overly generic type where mass and speed can have arbitrary dimensions (and the return type is type(mass) * type(speed)^2). So for this case, it is probably better to add parameter and return types.

Generic functions

Sometimes however, it is useful to write generic functions. For example, consider max(a, b) — a function that returns the larger of the two arguments. We might want to use that function with dimensionful arguments such as max(1 m, 1 yd). To define such a generic function, you can introduce type parameters in angle brackets:

fn max<T>(a: T, b: T) -> T = if a > b then a else b

This function signature tells us that max takes two arguments of arbitrary type T (but they need to match!), and returns a quantity of the same type T.

Note that you can perform the usual operations with type parameters, such as multiplying/dividing them with other types, or raising to rational powers. For example, consider this cube-root function

fn cube_root<T>(x: T^3) -> T = x^(1/3)

that can be called with a scalar (cube_root(8) == 2) or a dimensionful argument (cube_root(1 liter) == 10 cm).

Note: cube_root can also be defined as fn cube_root<T>(x: T) -> T^(1/3), which is equivalent to the definition above.

Recursive functions

It is also possible to define recursive functions. In order to do so, you currently need to specify the return type — as the type signature can not (yet) be inferred otherwise.

For example, a naive recursive implementation to compute Fibonacci numbers in Numbat looks like this:

fn fib(n: Scalar) -> Scalar =
  if n ≤ 2
    then 1
    else fib(n - 2) + fib(n - 1)

Conditionals

Numbat has if-then-else conditional expressions with the following syntax

if <cond> then <expr1> else <expr2>

where <cond> is a condition that evaluates to a Boolean value, like 3 ft < 3 m. The types of <expr1> and <expr2> need to match.

For example, you can defined a simple step function using

fn step(x: Scalar) -> Scalar = if x < 0 then 0 else 1

Date and time

Numbat supports date and time handling based on the proleptic Gregorian calendar, which is the (usual) Gregorian calendar extended to dates before its introduction in 1582. Julian calendar dates are currently not supported.

A few examples of useful operations that can be performed on dates and times:

# Which date is 40 days from now?
now() + 40 days

# Which date was 1 million seconds ago?
now() - 1 million seconds

# How many days are left until September 1st?
date("2024-11-01") - today() -> days

# What time is it in Nepal right now?
now() -> tz("Asia/Kathmandu")  # use tab completion to find time zone names

# What is the local time when it is 2024-11-01 12:30:00 in Australia?
datetime("2024-11-01 12:30:00 Australia/Sydney") -> local

# What is the current UNIX timestamp?
now() -> unixtime

# What is the date corresponding to the UNIX timestamp 1707568901?
from_unixtime(1707568901)

# How long are one million seconds in days, hours, minutes, seconds
1 million seconds -> human

Date and time arithmetic

The following operations are supported for DateTime objects:

Left Operator Right Result
DateTime - DateTime Duration between the two dates as a Time. In seconds, by default. Use normal conversion for other time units.
DateTime + Time New DateTime by adding the duration to the date
DateTime - Time New DateTime by subtracting the duration from the date
DateTime -> tz("…") Converts the datetime to the specified time zone. Note that you can use tab-completion for time zone names.

Warning

: You can add years or months to a given date (now() + 3 months), but note that the result might not be what you expect. The unit year is defined as the average length of a year (a tropical year, to be precise), and month is defined as the average length of a month (1/12 of a year). So this does not take into account the actual length of the months or the leap years. However, note that adding or subtracting “one year” or “one month” is not a well-defined operation anyway. For example, what should “one month after March 31st” be? April 30th or May 1st? If your answer is April 30th, then what is “one month after March 30th”? If your answer is May 1st, then what is “one month after April 1st”?

Date, time, and duration functions

The following functions are available for date and time handling:

  • now() -> DateTime: Returns the current date and time.
  • today() -> DateTime: Returns the current date at midnight (in the local time).
  • datetime(input: String) -> DateTime: Parses a string (date and time) into a DateTime object.
  • date(input: String) -> DateTime: Parses a string (only date) into a DateTime object.
  • time(input: String) -> DateTime: Parses a string (only time) into a DateTime object.
  • format_datetime(format: String, dt: DateTime) -> String: Formats a DateTime object as a string. See this page for possible format specifiers.
  • tz(tz: String) -> Fn[(DateTime) -> DateTime]: Returns a timezone conversion function, typically used with the conversion operator (datetime -> tz("Europe/Berlin"))
  • local(dt: DateTime) -> DateTime: Timezone conversion function targeting the users local timezone (datetime -> local)
  • get_local_timezone() -> String: Returns the users local timezone
  • unixtime(dt: DateTime) -> Scalar: Converts a DateTime to a UNIX timestamp.
  • from_unixtime(ut: Scalar) -> DateTime: Converts a UNIX timestamp to a DateTime object.
  • human(duration: Time) -> String: Converts a Time to a human-readable string in days, hours, minutes and seconds

Date time formats

The following formats are supported by datetime. UTC offsets are mandatory for the RFC 3339 and RFC 2822 formats. The other formats can optionally include a time zone name or UTC offset. If no time zone is specified, the local time zone is used.

Format Examples
RFC 3339 2024-02-10T12:30:00Z
2024-02-10T06:30:00-06:00
RFC 2822 Sat, 10 Feb 2024 12:30:00 Z
Sat, 10 Feb 2024 06:30:00 -0600
%Y-%m-%d %H:%M:%S%.f 2024-02-10 12:30:00
2024-02-10 06:30:00 -0600
2024-02-10 07:30:00 US/Eastern
2024-02-10 12:30:00.123456
%Y/%m/%d %H:%M:%S%.f same, but with / separator
%Y-%m-%d %H:%M 2024-02-10 12:30
2024-02-10 06:30 -0600
2024-02-10 07:30 US/Eastern
%Y/%m/%d %H:%M same, but with / separator
%Y-%m-%d %I:%M:%S%.f %p 2024-02-10 12:30:00 PM
2024-02-10 06:30:00 AM -0600
2024-02-10 07:30:00 AM US/Eastern
2024-02-10 12:30:00.123456 PM
%Y/%m/%d %I:%M:%S%.f %p same, but with / separator
%Y-%m-%d %I:%M %p 2024-02-10 12:30 PM
2024-02-10 06:30 AM -0600
2024-02-10 07:30 AM US/Eastern
%Y/%m/%d %I:%M %p same, but with / separator

The date function supports the following formats. It returns a DateTime object with the time set to midnight in the specified timezone (or the local timezone if no timezone is specified).

Format Examples
%Y-%m-%d 2024-02-10
2024-02-10 +0100
2024-02-10 Europe/Berlin
%Y/%m/%d 2024/02/10
2024/02/10 +0100
2024/02/10 Europe/Berlin

The time function supports the following formats. It returns a DateTime object with the date set to the current date. If no timezone is specified, the local timezone is used.

Format Examples
%H:%M:%S%.f 12:30:00
06:30:00 -0600
07:30:00 US/Eastern
12:30:00.123456
%H:%M 12:30
06:30 -0600
07:30 US/Eastern
%I:%M:%S%.f %p 12:30:00 PM
06:30:00 AM -0600
07:30:00 AM US/Eastern
12:30:00.123456 PM
%I:%M %p 12:30 PM
06:30 AM -0600
07:30 AM US/Eastern

Printing, testing, debugging

Printing

Numbat has a builtin print procedure that can be used to print the value of an expression:

print(2 km/h)
print(3 ft < 1 m)

You can also print out simple messages as strings. This is particularly useful when combined with string interpolation to print results of a computation:

let radius: Length = sqrt(footballfield / 4 pi) -> meter
print("A football field would fit on a sphere of radius {radius}")

You can use almost every expression inside a string interpolation field. For example:

print("3² + 4² = {hypot2(3, 4)}²")

let speed = 25 km/h
print("Speed of the bicycle: {speed} ({speed -> mph})")

Format specifiers are also supported in interpolations. For instance:

print("{pi:0.2f}") // Prints "3.14"

For more information on supported format specifiers, please see this page.

Testing

The assert_eq procedure can be used to test for (approximate) equality of two quantities. This is often useful to make sure that (intermediate) results in longer calculations have a certain value, e.g. when restructuring the code. The general syntax is

assert_eq(q1, q2)
assert_eq(q1, q2, ε)

where the first version tests for exact equality while the second version tests for approximate equality |{q1}{q2}|<ϵ

with a specified accuracy of ϵ

. For example:

assert_eq(2 + 3, 5)
assert_eq(1 ft × 77 in², 4 gal)

assert_eq(alpha, 1 / 137, 1e-4)
assert_eq(3.3 ft, 1 m, 1 cm)

There is also a plain assert procedure that can test any boolean condition. For example:

assert(1 yard < 1 meter)
assert(π != 3)

A runtime error is thrown if an assertion fails. Otherwise, nothing happens.

Debugging

You can use the builtin type procedure to see the type (or physical dimension) of a quantity:

>>> type(g0)

  Length / Time²

>>> type(2 < 3)

  Bool

Dimension definitions

New (physical) dimensions can be introduced with the dimension keyword. Similar like for units, there are base dimensions (like length, time and mass) and dimensions that are derived from those base dimensions (like momentum, which is mass · length / time). Base dimensions are simply introduced by declaring their name:

dimension Length
dimension Time
dimension Mass

Derived dimensions need to specify their relation to base dimensions (or other derived dimensions). For example:

dimension Velocity = Length / Time
dimension Momentum = Mass * Velocity
dimension Force = Mass * Acceleration = Momentum / Time
dimension Energy = Momentum^2 / Mass = Mass * Velocity^2 = Force * Length

In the definition of Force and Energy, we can see that multiple alternative definitions can be specified. This is entirely optional. When given, the compiler will make sure that all definitions are equivalent.

Unit definitions

New units of measurement can be introduced with the unit keyword. There are two types of units: base units and derived units.

A new base unit can be defined by specifying the physical dimension it represents. For example, in the International System of Units (SI), the second is the base unit for measuring times:

unit second: Time

Here, Time denotes the physical dimension.

Derived units are also introduced with the unit keyword. But unlike base units, they are defined through their relation to other units. For example, a minute can be defined as

unit minute: Time = 60 second

Here, the : Time annotation is optional. If a dimension is specified, it will be used to verify that the right hand side expression (60 second) is indeed of physical dimension Time. This is apparent in this simple example, but can be useful for more complicated unit definitions like

unit farad: Capacitance = ampere^2 second^4 / (kilogram meter^2)

Prefixes

If a unit may be used with metric prefixes such as milli/m, kilo/k or mega/M, we can prepend the unit definition with the @metric_prefixes decorator:

@metric_prefixes
unit second: Time

This allows identifiers such as millisecond to be used in calculations. See the section below how prefixes interact with aliases.

Similarly, if a unit should be prependable with binary (IEC) prefixes such as kibi/Ki, mebi/Mi or gibi/Gi, you can add the @binary_prefixes decorator. A unit might also allow for both metric and binary prefixes, for example:

@binary_prefixes
@metric_prefixes
unit byte = 8 bit

This allows the usage of both mebibyte (1024² byte) as well as megabyte (1000² byte).

Aliases

It is often useful to define alternative names for a unit. For example, we might want to use the plural form seconds or the commonly used short version s. We can use the @aliases decorator to specify them:

@metric_prefixes
@aliases(meters, metre, metres, m: short)
unit meter: Length

In addition to the name, we can also specify how aliases interact with prefixes using : long (the default), : short, : both or : none. The actual unit name (meter) and all long aliases will accept the long version of prefixes (…, milli, kilo, mega, giga, …). All short aliases (m in the example above) will only accept the respective short versions of the prefixes (…, m, k, M, G, …). Aliases annotated with : both or : none accept either both long and short prefixes, or none of them. The unit definition above allows all of following expressions:

millimeter
kilometer

millimeters
kilometers

millimetre
kilometre

millimetres
kilometres

mm
km
...

Ad-hoc units

It is often useful to introduce fictional physical units (and dimensions). This comes up frequently when you want to count things. For example:

unit book

@aliases(pages)
unit page

@aliases(words)
unit word

let words_per_book = 500 words/page × 300 pages/book

Note that those base unit definitions will implicitly create new dimensions which are capitalized versions of the unit names (Book, Page, Word). A definition like unit book is a shorthand for dimension Book; unit book: Book. Those units now allow us to count books, pages and words independently without any risk of mixing them. The words_per_book constant in this examples has a type of Word / Book.

Another example shows how we introduce a dot unit to do calculations with screen resolutions:

@aliases(dots)
unit dot

unit dpi = dots / inch

# Note: a `Dot` dimension was implicitly created for us
fn inter_dot_spacing(resolution: Dot / Length) -> Length = 1 dot / resolution

inter_dot_spacing(72 dpi) -> µm  # 353 µm

Syntax overview

# This is a line comment. It can span over
# multiple lines

# 1. Imports

use prelude        # This is not necessary. The 'prelude'
                   # module will always be loaded upon startup

use units::stoney  # Load a specific module

# 2. Numbers

12345       # integer notation
12_345      # optional decimal separators

0.234       # floating point notation
.234        # without the leading zero

1.234e15    # scientific notation
1.234e+15
1e-9
1.0e-9

0x2A        # hexadecimal
0o52        # octal
0b101010    # binary

NaN         # Not a number
inf         # Infinity

# 3. Simple expressions

3 + (4 - 3)       # Addition and subtraction

1920 / 16 * 9     # Multiplication, division
1920 ÷ 16 × 9     # Unicode-style, '·' is also multiplication
2 pi              # Whitespace is implicit multiplication
meter per second  # 'per' keyword can be used for division

2^3               # Exponentiation
2**3              # Python-style
2³                # Unicode exponents
2^-3              # Negative exponents

mod(17, 4)        # Modulo

3 in -> cm        # Unit conversion, can also be → or ➞
3 in to cm        # Unit conversion with the 'to' keyword

cos(pi/3 + pi)    # Call mathematical functions
pi/3 + pi // cos  # Same, 'arg // f' is equivalent to 'f(arg)'
                  # The '//' operator has the lowest precedence
                  # which makes it very useful for interactive
                  # terminals (press up-arrow, and add '// f')

# 4. Constants

let n = 4                          # Simple numerical constant
let q1 = 2 m/s                     # Right hand side can be any expression
let q2: Velocity = 2 m/s           # With optional type annotation
let q3: Length / Time = 2 m/s      # more complex type annotation

# 5. Function definitions

fn foo(z: Scalar) -> Scalar = 2 * z + 3                   # A simple function
fn speed(len: Length, dur: Time) -> Velocity = len / dur  # Two parameters
fn my_sqrt<T>(q: T^2) -> T = q^(1/2)                      # A generic function
fn is_non_negative(x: Scalar) -> Bool = x ≥ 0             # Returns a bool

# 6. Dimension definitions

dimension Fame                            # A new base dimension
dimension Deceleration = Length / Time^2  # A new derived dimension

# 7. Unit definitions

@aliases(quorks)                 # Optional aliases-decorator
unit quork = 0.35 meter          # A new derived unit

@metric_prefixes                 # Optional decorator to allow 'milliclonk', etc.
@aliases(ck: short)              # short aliases can be used with short prefixes (mck)
unit clonk: Time = 0.2 seconds   # Optional type annotation

@metric_prefixes
@aliases(wh: short)
unit warhol: Fame                # New base unit for the "Fame" dimension

unit thing                       # New base unit with automatically generated
                                 # base dimension "Thing"

# 8. Conditionals

fn bump(x: Scalar) -> Scalar =   # The construct 'if <cond> then <expr> else <expr>'
  if x >= 0 && x <= 1            # is an expression, not a statement. It can span
    then 1                       # multiple lines.
    else 0

# 9. Procedures

print(2 kilowarhol)              # Print the value of an expression
print("hello world")             # Print a message
print("value of pi = {pi}")      # String interpolation
print("sqrt(10) = {sqrt(10)}")   # Expressions in string interpolation
print("value of π ≈ {π:.3}")     # Format specifiers

assert(1 yard < 1 meter)         # Assertion

assert_eq(1 ft, 12 in)           # Assert that two quantities are equal
assert_eq(1 yd, 1 m, 10 cm)      # Assert that two quantities are equal, up to
                                 # the given precision
type(2 m/s)                      # Print the type of an expression

Predefined functions

Utility

fn unit_of<T>(x: T) -> T
fn value_of<T>(x: T) -> Scalar
fn is_nan<T>(x: T) -> Bool
fn is_infinite<T>(x: T) -> Bool

Math

Basics

fn abs<T>(x: T) -> T
fn round<T>(x: T) -> T
fn floor<T>(x: T) -> T
fn ceil<T>(x: T) -> T
fn mod<T>(a: T, b: T) -> T
fn sqrt<D>(x: D^2) -> D
fn sqr<D>(x: D) -> D^2

Exponential and logarithm

fn exp(x: Scalar) -> Scalar
fn ln(x: Scalar) -> Scalar
fn log(x: Scalar) -> Scalar
fn log10(x: Scalar) -> Scalar
fn log2(x: Scalar) -> Scalar

Trigonometry

Basic:

fn cos(x: Scalar) -> Scalar
fn sin(x: Scalar) -> Scalar
fn tan(x: Scalar) -> Scalar
fn asin(x: Scalar) -> Scalar
fn acos(x: Scalar) -> Scalar
fn atan(x: Scalar) -> Scalar
fn atan2<T>(y: T, x: T) -> Scalar

Hyperbolic:

fn sinh(x: Scalar) -> Scalar
fn cosh(x: Scalar) -> Scalar
fn tanh(x: Scalar) -> Scalar
fn asinh(x: Scalar) -> Scalar
fn acosh(x: Scalar) -> Scalar
fn atanh(x: Scalar) -> Scalar

Extra:

fn cot(x: Scalar) -> Scalar
fn acot(x: Scalar) -> Scalar
fn coth(x: Scalar) -> Scalar
fn acoth(x: Scalar) -> Scalar
fn secant(x: Scalar) -> Scalar
fn arcsecant(x: Scalar) -> Scalar
fn cosecant(x: Scalar) -> Scalar
fn csc(x: Scalar) -> Scalar
fn acsc(x: Scalar) -> Scalar
fn sech(x: Scalar) -> Scalar
fn asech(x: Scalar) -> Scalar
fn csch(x: Scalar) -> Scalar
fn acsch(x: Scalar) -> Scalar

Others

fn gamma(x: Scalar) -> Scalar

Statistics

fn mean<D>(xs: D…) -> D
fn maximum<D>(xs: D…) -> D
fn minimum<D>(xs: D…) -> D

Geometry

fn hypot2<T>(x: T, y: T) -> T
fn hypot3<T>(x: T, y: T, z: T) -> T
fn circle_area<L>(radius: L) -> L^2
fn circle_circumference<L>(radius: L) -> L
fn sphere_area<L>(radius: L) -> L^2
fn sphere_volume<L>(radius: L) -> L^3

Algebra

fn quadratic_equation<A2, B2>(a: A2, b: B2, c: B2²/A2) -> String

Date and time

See this page for details.

Physics

Temperature conversion

fn from_celsius(t_celsius: Scalar) -> Temperature
fn celsius(t_kelvin: Temperature) -> Scalar
fn from_fahrenheit(t_fahrenheit: Scalar) -> Temperature
fn fahrenheit(t_kelvin: Temperature) -> Scalar

Strings

fn str_length(s: String) -> Scalar
fn str_slice(s: String, start: Scalar, end: Scalar) -> String
fn str_append(a: String, b: String) -> String
fn str_contains(haystack: String, needle: String) -> Bool
fn str_replace(s: String, pattern: String, replacement: String) -> String
fn str_repeat(a: String, n: Scalar) -> String
fn chr(n: Scalar) -> String
fn hex(n: Scalar) -> String

Constants

Mathematical

  • pi, π
  • τ
  • e
  • golden_ratio, φ

Named numbers

Large numbers:

  • hundred
  • thousand
  • million
  • billion
  • trillion
  • quadrillion
  • quintillion
  • googol

Unicode fractions:

  • ½, , , ¼, ¾, …

Colloquial:

  • quarter
  • half
  • semi
  • double
  • triple
  • dozen

Physics

Description Identifier Dimension
The speed of light in vacuum speed_of_light, c Velocity
The Newtonian constant of gravitation gravitational_constant, G Force × Length^2 / Mass^2
Standard acceleration of gravity on earth gravity, g0 Acceleration
The Planck constant planck_constant, Mass × Length^2 / Time
The reduced Planck constant h_bar, Mass × Length^2 / Time
Mass of the electron electron_mass Mass
Elementary charge (charge of the electron) elementary_charge, electron_charge ElectricCharge
Magnetic constant (vacuum magnetic permeability) magnetic_constant, µ0, mu0 Force / Current^2
Electric constant (vacuum electric permittivity) electric_constant, ε0, eps0 Capacitance / Length
Bohr magneton bohr_magneton, µ_B Energy / MagneticFluxDensity
Fine structure constant fine_structure_constant, alpha, α Scalar
Proton mass proton_mass Mass
Neutron mass neutron_mass Mass
Avogadro constant avogadro_constant, N_A 1 / AmountOfSubstance
Boltzmann constant boltzmann_constant, k_B Energy / Temperature
Stefan-Boltzmann constant stefan_boltzmann_constant Power / (Area × Temperature^4)
Ideal gas constant gas_constant, R Energy / (AmountOfSubstance × Temperature)
Planck length planck_length Length
Planck mass planck_mass Mass
Planck time planck_time Time
Planck temperature planck_temperature Temperature
Planck energy planck_energy Energy
Bohr radius bohr_radius, a0 Length
Rydberg constant rydberg_constant Wavenumber

List of supported units

All SI-accepted units support metric prefixes (mm, cm, km, … or millimeter, centimeter, kilometer, …) and — where sensible — units allow for binary prefixes (MiB, GiB, … or mebibyte, gibibyte, …).

Dimension Unit name Identifier(s)
AbsorbedDose Gray gray, grays, Gy
Activity Becquerel becquerel, becquerels, Bq
AmountOfSubstance Mole mol, mole, moles
Angle Minute of arc arcmin, arcminute, arcminutes
Angle Second of arc arcsec, arcsecond, arcseconds
Angle Degree deg, degree, degrees, °
Angle Gradian gon, gons, grad, grade, grades, gradian, gradians, grads
Angle Radian rad, radian, radians
Angle Revolution rev, revolution, revolutions
Angle Turn turn, turns
Area Acre acre, acres
Area Are are
Area Barn barn, barns
Area Football field footballfield
Area Hectare ha, hectare, hectares
Beat Beat beat, beats
Beat / Time Beats per minute bpm, BPM
Capacitance Farad F, farad, farads
CatalyticActivity Katal kat, katal, katals
Current Ampere A, ampere, amperes
DigitalInformation Bit bit, bits
DigitalInformation Byte B, byte, Byte, bytes, Bytes, octet, Octet, octets, Octets
DigitalInformation / Time Bits per second bps
Dot Dot dot, dots
Dot / Length Dots per inch dpi
DynamicViscosity Poise poise
ElectricCharge Ampere-hour Ah, amperehour
ElectricCharge Coulomb C, coulomb, coulombs
ElectricConductance Siemens S, siemens
ElectricResistance Ohm ohm, ohms, Ω, Ω
Energy British thermal unit BTU, Btu
Energy Calorie cal, calorie, calories
Energy Electron volt electronvolt, electronvolts, eV
Energy Erg erg, ergs
Energy Hartree hartree, hartrees
Energy Joule J, joule, joules
Energy Planck energy planck_energy
Energy Rydberg unit of energy Ry
Energy Watt-hour watthour, Wh
EquivalentDose Sievert sievert, sieverts, Sv
Force Dyne dyn, dyne
Force Kilogram-force kgf, kilogram_force
Force Newton N, newton, newtons
Force Ounce-force ounce_force, ozf
Force Pound-force lbf, pound_force
Force / Volume Mercury Hg
Frame Frame frame, frames
Frame / Time Frames per second fps
Frequency Hertz hertz, Hz
Frequency Revolutions per minute rpm, RPM
Illuminance Foot-candle fc, footcandle, footcandles
Illuminance Lux lux, lx
Inductance Henry H, henries, henry, henrys
KinematicViscosity Stokes St, stokes
Length Ångström angstrom, angstroms, Å, Å
Length Astronomical unit astronomicalunit, astronomicalunits, au, AU
Length Bohr bohr
Length Fathom fathom, fathoms
Length Fermi fermi
Length Foot feet, foot, ft
Length Furlong furlong, furlongs
Length Inch in, inch, inches
Length League league, leagues
Length Light-year lightyear, lightyears, ly
Length Metre m, meter, meters, metre, metres
Length Micron micron
Length Mile mi, mile, miles
Length Nautical Mile nautical_mile, nautical_miles, NM, nmi
Length Parsec parsec, parsecs, pc
Length Planck length planck_length
Length Rack unit rackunit, rackunits, RU, U
Length US rod perch, rod, rods
Length Smoot smoot
Length Stoney length stoney_length
Length Thousandth of an inch mil, mils, thou
Length Yard yard, yards, yd
Length / Volume Miles per gallon mpg
Length^2 darcy darcies, darcy, darcys
LuminousFlux Lumen lm, lumen, lumens
LuminousIntensity Candela candela, candelas, cd
MagneticFieldStrength Oersted Oe, oersted
MagneticFlux Maxwell maxwell, Mx
MagneticFlux Weber Wb, weber, webers
MagneticFluxDensity Gauss gauss
MagneticFluxDensity Tesla T, tesla, teslas
Mass Dalton Da, dalton, daltons
Mass Firkin firkin, firkins
Mass Grain grain, grains
Mass Gram g, gram, gramme, grammes, grams
Mass Hundredweight cwt, long_hundredweight
Mass Long ton long_ton, long_tons
Mass Ounce ounce, ounces, oz
Mass Planck mass planck_mass
Mass Pound lb, lbs, pound, pounds
Mass Stone stone
Mass Stoney mass stoney_mass
Mass Tonne metricton, ton, tonne, tonnes, tons
Molality Molal molal
Molarity Molar molar
Money Australian dollar A$, AUD, australian_dollar, australian_dollars
Money Brazilian real brazilian_real, brazilian_reals, BRL, R$
Money Pound sterling british_pound, GBP, pound_sterling, £
Money Bulgarian lev BGN, bulgarian_lev, bulgarian_leva
Money Canadian dollar C$, CAD, canadian_dollar, canadian_dollars
Money Czech koruna czech_koruna, czech_korunas, CZK,
Money Danish krone danish_krone, danish_kroner, DKK
Money US dollar $, dollar, dollars, USD
Money Euro EUR, euro, euros,
Money Hong Kong dollar HK$, HKD, hong_kong_dollar, hong_kong_dollars
Money Hungarian forint Ft, HUF, hungarian_forint, hungarian_forints
Money Icelandic króna icelandic_krona, icelandic_kronur, icelandic_króna, icelandic_krónur, ISK
Money Indian rupee indian_rupee, indian_rupees, INR,
Money Indonesian rupiah IDR, indonesian_rupiah, indonesian_rupiahs, Rp
Money Israeli new shekel ILS, israeli_new_shekel, israeli_new_shekels, NIS,
Money Malaysian ringgit malaysian_ringgit, malaysian_ringgits, MYR, RM
Money New Zealand dollar new_zealand_dollar, new_zealand_dollars, NZ$, NZD
Money Norwegian krone NOK, norwegian_krone, norwegian_kroner
Money Philippine peso philippine_peso, philippine_pesos, PHP,
Money Polish złoty PLN, polish_zloty, polish_zlotys,
Money Chinese yuan CNY, renminbi, yuan,
Money Romanian leu lei, romanian_leu, romanian_leus, RON
Money Singapore dollar S$, SGD, singapore_dollar, singapore_dollars
Money South African rand south_african_rand, ZAR
Money South Korean won KRW, south_korean_won, south_korean_wons,
Money Swedish krona SEK, swedish_krona, swedish_kronor
Money Swiss franc CHF, swiss_franc, swiss_francs
Money Thai baht thai_baht, thai_bahts, THB, ฿
Money Turkish lira TRY, turkish_lira, turkish_liras,
Money Japanese yen JPY, yen, ¥,
Person Person capita, people, person, persons
Piece Piece piece, pieces
Pixel Pixel pixel, pixels, px
Pixel / Length Pixels per inch ppi
Power Metric horsepower horsepower, hp
Power Watt W, watt, watts
Pressure Standard atmosphere atm, atmosphere, atmospheres
Pressure Bar bar, bars
Pressure Inch of mercury inHg
Pressure Kilopound-force per square inch ksi, KSI
Pressure Millimeter of mercury mmHg
Pressure Megapound-force per square inch mpsi, MPSI
Pressure Pascal Pa, pascal, pascals
Pressure Pound-force per square inch psi, PSI
Pressure Torr torr
Scalar Billion billion
Scalar Dozen dozen
Scalar Hundred hundred
Scalar Million million
Scalar Parts per billion partsperbillion, ppb
Scalar Parts per million partspermillion, ppm
Scalar Parts per quadrillion partsperquadrillion, ppq
Scalar Parts per trillion partspertrillion, ppt
Scalar Percent %, pct, percent
Scalar Quadrillion quadrillion
Scalar Quintillion quintillion
Scalar Thousand thousand
Scalar Trillion trillion
SolidAngle Steradian sr, steradian, steradians
Temperature Kelvin K, kelvin, kelvins
Temperature Planck temperature planck_temperature
Time Century centuries, century
Time Day d, day, days
Time Decade decade, decades
Time Fortnight fortnight, fortnights
Time Gregorian year gregorian_year, gregorian_years
Time Hour h, hour, hours, hr
Time Julian year julian_year, julian_years
Time Millennium millennia, millennium
Time Minute min, minute, minutes
Time Month month, months
Time Planck time planck_time
Time Second s, sec, second, seconds
Time Sidereal day sidereal_day, sidereal_days
Time Stoney time stoney_time
Time Week week, weeks
Time Tropical year tropical_year, tropical_years, year, years, yr
Velocity Knot kn, knot, knots, kt
Velocity Kilometres per hour kph
Velocity Miles per hour mph
Voltage Volt V, volt, volts
Volume Cubic centimetre cc, ccm
Volume US cup cup, cups
Volume US fluid ounce floz, fluidounce, fluidounces
Volume US liquid gallon gal, gallon, gallons
Volume US hogshead hogshead, hogsheads
Volume Imperial Bushel imperial_bushel, imperial_bushels, UK_bu
Volume Imperial Fluid Drachm imperial_fluid_drachm, imperial_fluid_drachms, UK_fldr
Volume Imperial Fluid Ounce imperial_fluidounce, imperial_fluidounces, UK_floz
Volume Imperial Gallon imperial_gallon, imperial_gallons, UK_gal
Volume Imperial Gill imperial_gill, imperial_gills, UK_gi
Volume Imperial Pint imperial_pint, imperial_pints, UK_pt
Volume Imperial Quart imperial_quart, imperial_quarts, UK_qt
Volume Litre l, L, liter, liters, litre, litres
Volume US liquid pint pint, pints
Volume Swimming pool swimmingpool
Volume US tablespoon tablespoon, tablespoons, tbsp
Volume US teaspoon teaspoon, teaspoons, tsp

Usage

Modes

You can run the Numbat command-line application in three different modes:

Mode Command to run
Start an interactive session (REPL) numbat
Run a Numbat program numbat script.nbt
Evaluate a single expression numbat -e '30 km/h -> mi/h'

Command-line options

Usage: numbat [OPTIONS] [FILE]

Option Description
-e, --expression <CODE> Evaluate a single expression. Can be specified multiple times to evaluate several expressions in sequence
-i, --inspect-interactively Enter interactive session after running a numbat script or expression
--pretty-print <WHEN> Whether or not to pretty-print every input expression [possible values: always, never, auto]
--intro-banner <MODE> What kind of intro banner to show (if any) [possible values: long, short, off]

Interactive sessions

Interactive sessions allow you to perform a sequence of calculations. You can use the special identifiers ans or _ to refer to the result of the last calculation. For example:

>>> 60 kW h / 150 kW

    = 0.4 h

>>> ans -> minutes

    = 24 min

Commands

There is a set of special commands that only work in interactive mode:

Command Action
list, ls List all functions, dimensions, variables and units
list <what> Where <what> can be functions, dimensions, variables, units
info <identifier> Get more information about units and variables
clear Clear screen
help, ? View short help text
quit, exit Quit the session

Key bindings

In interactive command-line mode, you can use the following key bindings. Most importantly, Tab for auto-completion, arrow keys and Ctrl-R for browsing the command history, and Ctrl-D for exiting the interactive session.

Key sequence Action
Tab, Ctrl-I Auto-completion
Ctrl-D Quit
Ctrl-L Clear screen
Up, Down Browse command history
Ctrl-R Search command history
Ctrl-C Clear the current line
Alt-Enter Insert newline
Home, Ctrl-A Move cursor to the beginning of the line
End, Ctrl-E Move cursor to the end of the line
Ctrl-W Delete word leading up to cursor