calc
Package calc provides advanced parsers for floats, ints, ..., based on Go constants calculator.
Introduction
When it comes to manually writing numbers, the usual literal format are not always the easiest.
How do you write the equivalent of 1 day but in seconds? 24*60*60 is probably easier than
figuring out it is 86400. Why, then asking your users to provide CLI arguments (or inputs in a textfield)
as a number, when you could easily ask them to enter it as a basic formula?
Go has figure that out, and has created a powerful constants systems that can be
used to higly improve parsing basic types.
Functions
func Bool(expr string) (bool, error)
Bool computes the bool expression.
func Complex128(expr string) (c complex128, err error)
Complex128 computes the complex expression.
func Complex64(expr string) (c complex64, err error)
Complex64 computes the complex expression.
func Float32(expr string) (float32, error)
Float32 computes the float expression.
func Float64(expr string) (float64, error)
Float64 computes the float expression.
func Int(expr string) (int64, error)
Int computes the int expression.
Using [calc.Int] you can parse basic literals,
exactly as [strconv.ParseInt] can do, and evaluate more advanced
expressions.
The example below showcases some more posibilities.
package main
import (
"fmt"
"strconv"
"github.com/etnz/calc"
)
func main() {
exp := "2"
v, _ := calc.Int(exp)
fmt.Println("Literal:", exp, "=", v)
v, _ = strconv.ParseInt(exp, 10, 64)
fmt.Println("Package strconv:", exp, "=", v)
exp = "2+2"
v, _ = calc.Int(exp)
fmt.Println("Algebra:", exp, "=", v)
exp = "1<<100 + 2 - 1<<100"
v, _ = calc.Int(exp)
fmt.Println("Safe overflow:", exp, "=", v)
exp = "0777"
v, _ = calc.Int(exp)
fmt.Println("Octal:", exp, "=", v)
exp = "0xFF"
v, _ = calc.Int(exp)
fmt.Println("Hex:", exp, "=", v)
exp = "0b1010 ^ 0b0101"
v, _ = calc.Int(exp)
fmt.Println("Binary:", exp, "=", v)
exp = "0xFF - 0b11111110"
v, _ = calc.Int(exp)
fmt.Println("Mixed:", exp, "=", v)
}
Output:
Literal: 2 = 2
Package strconv: 2 = 2
Algebra: 2+2 = 4
Safe overflow: 1<<100 + 2 - 1<<100 = 2
Octal: 0777 = 511
Hex: 0xFF = 255
Binary: 0b1010 ^ 0b0101 = 15
Mixed: 0xFF - 0b11111110 = 1
func String(expr string) (string, error)
String computes the string expression.
func Uint(expr string) (uint64, error)
Uint computes the int expression.
Types
type Scope struct { ... }
Scope contains a set of [constant.Value] that can be referenced by their name.
zero type is valid.
func (*Scope) Assign
func (s *Scope) Assign(name, expr string) error
Assign evaluates 'expr' and assign its value to the variable 'name'.
If the variable 'name' already exists, its value is not changed.
When writing expressions it can be handy to use predefined constants.
It is possible to prepare a [calc.Scope] with predefined variables.
package main
import (
"fmt"
"github.com/etnz/calc"
)
func main() {
var (
exp string
v int64
c calc.Scope
)
c.Assign("s", "1")
c.Assign("m", "60*s")
c.Assign("h", "60*m")
c.Assign("d", "24*h")
c.Assign("w", "7*d")
exp = "2.5*d"
v, _ = c.Int(exp)
fmt.Println("Time:", exp, "=", v)
exp = "2*d + 4*h"
v, _ = c.Int(exp)
fmt.Println("Time:", exp, "=", v)
exp = "2.5*s"
f, _ := c.Float64(exp)
fmt.Println("Float:", exp, "=", f)
}
Output:
Time: 2.5*d = 216000
Time: 2*d + 4*h = 187200
Float: 2.5*s = 2.5
func (s *Scope) AssignValue(name string, v any)
AssignValue directly assign the runtime value 'v' to the variable 'name'.
'v' must be one of:
float64
float32
complex128
complex64
int64
int32
int16
int8
int
uint64
uint32
uint16
uint8
uint
bool
string
If the variable 'name' already exists, its value is not changed.
func (Scope) Bool
func (s Scope) Bool(expr string) (bool, error)
Bool evaluates 'expr' as a bool.
func (s Scope) Complex128(expr string) (cplx complex128, err error)
Complex128 evaluates 'expr' as a complex128.
func (s Scope) Complex64(expr string) (cplx complex64, err error)
Complex64 evaluates 'expr' as a complex64.
func (s Scope) Float32(expr string) (float32, error)
Float32 evaluates 'expr' as a float32.
func (s Scope) Float64(expr string) (float64, error)
Float64 evaluates 'expr' as a float64.
func (*Scope) Import
func (s *Scope) Import(name string, lib *Scope)
Import another [Scope] inside this one.
Exposed variables in 'lib' can be referenced as <name>.<var>.
Following the rules of Go, only Capitalized variables are exposed.
Nesting Scopes is not supported (by Go).
When writing expressions using variables, it is possible
to "pack" them in their own namespace to avoid conflicts.
package main
import (
"fmt"
"github.com/etnz/calc"
)
func main() {
var (
exp string
v int64
c, lib calc.Scope
)
lib.Assign("S", "1")
lib.Assign("M", "60*S")
lib.Assign("H", "60*M")
lib.Assign("D", "24*H")
c.Import("time", &lib)
exp = "2*time.D + 4*time.H"
v, _ = c.Int(exp)
fmt.Println("Time:", exp, "=", v)
}
Output:
Time: 2*time.D + 4*time.H = 187200
func (Scope) Int
func (s Scope) Int(expr string) (int64, error)
Int evaluates 'expr' as a int64.
func (Scope) String
func (s Scope) String(expr string) (string, error)
String evaluates 'expr' as a string.
func (Scope) Uint
func (s Scope) Uint(expr string) (uint64, error)
Uint evaluates 'expr' as an int64.
Readme created from Go doc with goreadme