GoTron Documentation

This guide still mentions several features/examples for `Jeff` (jf), which is short for `Json Formulas`, a previous tool which has its own custom source-code parser. Ignore those examples.

Here are several examples of GoTron expressions and their results, along with some complete scripts and commands you can run as given.

GoTron/gt (GO TRansform jsON) is just a command-line app which lets you view, transform, and JSON data. Input data come from standard input by default, unless named filepaths/URIs are given to load valid JSON from.

GoTron uses golang-syntax formulas/expressions to transform data, which are run using a surprisingly capable scripting engine. If the command is a dot, it means keep input data as they are. Scripts give you all sorts of conveniences you may have come to expect from other popular tools, such as negative indexing, but that's barely scratching the surface: `gt` gives you many other handy features, such as automatic depth-first recursion for most operators and functions.

Scripts can use 100+ predefined funcs, not counting aliases; plenty of global variables with all sorts of data are also available. Some of these predefined functions/values are documented on this help page. Many names/aliases should be familiar if you know JavaScript, Go, or Python: just avoid package names, avoid underscores, keep all letters lowercase, and you'll often get the right GoTron names for what you need.

As frequently shown here, the most convenient way to call 1-input funcs on non-objects is to use them as fake-properties of their input. Since objects have real properties, you have to use parentheses to call funcs explicitly on them, as many examples show.

Types

Here are all value-types supported.

null null value
boolean true or false
number 64-bit floating-point number, with NaN, +inf, and -inf
string plain-text encoded as UTF-8
array arbitrary-length list of values; also called `list`
object ordered associative array with string keys

Examples of Various Syntax

value . func (args...) fake-method function call
`abc`.upper() "ABC"
10.0.log10() 1
10..log10() 1
10i.log10() 1
10i.sqrt().log10() 0.5
(1 ^ 3).sqrt().tofixed(3) ["1.000", "1.414", "1.732"]
nonobject . function fake-property function call
`abc`.upper "ABC"
10.0.log10 1
10..log10 1
10i.log10 1
10i.sqrt.log10 0.5
(1 ^ 3).sqrt.fix3 ["1.000", "1.414", "1.732"]
object . property object-property access
monthlen . January 31
[:] exclusive slice syntax
"abc😁def"[2:5] "c😁d"
"a😁bc"[:1^3] ["a", "a😁", "a😁b"]
monthlen[`February`:`March`] {"February": 28}
monthlen[:`March`] {"January": 31, "February": 28}

Examples of Unary Operators

! boolean negation
!false true
!true false
!0 true
!-1.5 false
!nan false
+ convert to number
+false 0
+true 1
+123.456 123.456
+nan NaN
+"abc" NaN
+"123.456" 123.456
- negate number(s)
-(-1.5) 1.5
-nan NaN
-a(1, 2, 3) [-1, -2, -3]
-_{a: 1, b: 2} {"a": -1, "b": -2}

Examples of Binary Operators

+ addition, or string concatenation
3 + 4.5 7.5
4.5 + "abc" "4.5abc"
"abc" + 4.5 "abc4.5"
"some" + "text" "sometext"
3 + a(4.5, "abc") [7.5, "3abc"]
a(4.5, "abc") + 3 [7.5, "abc3"]
3 + _{a: 4.5, b: "abc"} {"a": 7.5, "b": "3abc"}
_{a: 4.5, b: "abc"} + 100 {"a": 104.5, "b": "abc100"}
- subtraction, or substring removal
3 - 4.5 -1.5
"sassy" - "ss" "say"
"something" - "methi" "song"
"excellent" - "e" "xcllnt"
3 - a(4.5, 1) [-1.5, 1]
3 - _{a: 4.5, b: 1} {"a": -1.5, "b": 2}
* multiplication, or string repetition
3 * 4.5 13.5
3.9 * "-" "---"
"abc" * 3.9 "abcabcabc"
3 * a(4.5, 1) [13.5, 3]
_{a: 4.5, b: 1} * 3 {"a": 13.5, "b": 3}
3 * _{a: 4.5, b: 1} {"a": 13.5, "b": 3}
_{a: 4.5, b: 1} * 3 {"a": 13.5, "b": 3}
/ division, chunking strings, or splitting strings
4.5 / 3 1.5
"abcdef" / 3 ["ab", "cd", "ef"]
"abcdef" / 2 ["abc", "def"]
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„" / 2 ["πŸ˜€πŸ˜πŸ˜‚", "πŸ˜ƒπŸ˜„"]
2 / "πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„" ["πŸ˜€πŸ˜", "πŸ˜‚πŸ˜ƒ", "πŸ˜„"]
2 / "abcdef" ["ab", "cd", "ef"]
"abc,def,xyz" / "," ["abc", "def", "xyz"]
"," / "abc,def,xyz" [","]
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„" / "" ["πŸ˜€", "😁", "πŸ˜‚", "πŸ˜ƒ", "πŸ˜„"]
3 / a(4.5, 1) [0.6666666666666666, 3]
a(4.5, 1) / 3 [1.5, 0.3333333333333333]
3 / _{a: 4.5, b: 1} {"a": 0.6666666666666666, "b": 3}
_{a: 4.5, b: 1} / 3 {"a": 1.5, "b": 0.3333333333333333}
^ number sequencing, array joining, or object flattening
-3 ^ -3 [-3]
3 ^ 6.2 [3, 4, 5, 6]
3.25 ^ -2.2 [3.25, 2.25, 1.25, 0.25, -0.75, -1.75]
a("a", "b", "c") ^ "" "abc"
"" ^ a("a", "b", "c") "abc"
"; " ^ a("a", "b", -7, "c") "a; b; -7; c"
a("a", "b", "c") ^ a(1, 2, 3) {"a": 1, "b": 2, "c": 3}
a(-20, 12.75, "hey, hi!") ^ a(1, 2) {"-20": 1, "12.75": 2, "hey, hi!": null}
_{"data": {"abc.json": 1024},
"info.txt": 321}
^ "/"
{"data/abc.json": 1024, "info.txt": 321}
_{"a": {"b": 1, "c": 2}, "d": 3} ^ "/" {"a/b": 1, "a/c": 2, "d": 3}
&& boolean and
true && false false
|| boolean or
true || false true
| fail-pipes
4 | 7 4
2i.abc | 4 4
& ok-pipes
4 & 7 4
mixing operators
"a b c" / " " ^ "," "a,b,c"
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„" / 3 ^ "\n" "πŸ˜€πŸ˜\nπŸ˜‚πŸ˜ƒ\nπŸ˜„"

Examples of Other Operators

[index/slice] 0-based indexing
"abc"[1] "b"
"abc"[-1] "c"
a(1, 2, 3)[1] 2
a(1, 2, 3)[-1] 3
_{a: 1, b: 2, c: 3}[2] 3
_{a: 1, b: 2, c: 3}[-1] 3
_{a: 1, b: 2, c: 3}["a"] 1
_{a: 1, b: 2, c: 3}["d"] null
: 0-based exclusive slicing
a(1, 2, 3)[:2] [1, 2]
a(1, 2, 3)[0:2] [1, 2]
a(1, 2, 3)[:] [1, 2, 3]
_{a: 1, b: 2, c: 3}[:] [1, 2, 3]
_{a: 1, b: 2, c: 3}[:2] {"a": 1, "b": 2}
_{a: 1, b: 2, c: 3}[:-1] {"a": 1, "b": 2}
_{a: 1, b: 2, c: 3}[:-2] {"a": 1}
_{a: 1, b: 2, c: 3}[:"b"] {"a": 1}
_{a: 1, b: 2, c: 3}[:"c"] {"a": 1, "b": 2}
^ sequencing
3^5 [3, 4, 5]
4.25 ^ 0.9 [4.25, 3.25, 2.25, 1.25]

Examples of Normal Functions

abs absolute value
false.abs 0
true.abs 1
(-4.234).abs 4.234
acos arc cosine, inverse cosine
acosh hyperbolic arc cosine
array make an array/list of values
array() []
array(null, -3, "hi") [null, -3, "hi"]
array(-3.2, ["abc", null]) [-3.2, ["abc", null]]
array(-3.2, ["abc", null], _{a: 34, b: nan}) [-3.2, ["abc", null], {"a": 34, "b": nan}]
array(4, 5, 6, 7, 8) [4, 5, 6, 7, 8]
asin arc sine, inverse sine
asinh hyperbolic arc sine
assign, update update/override object key-value pairs
_{a: 2, b: 3}.assign(_{a: 1, c: 9}) {"a": 1, "b": 3, "c": 9}
_{a: 2, b: 3}.assign(_{a: 1, c: 9}, _{c: null}) {"a": 1, "b": 3, "c": null}
atan arc tangent, inverse tangent
atanh hyperbolic arc tangent
basename get filename without preceding folders
"folder/file.txt".basename "file.txt"
beta beta function
beta(1, 2) 0.5
bin convert number into string of binary digits
333.bin "101001101"
bool, boolean make a boolean
null.bool false
false.bool false
0.bool false
"".bool false
a().bool false
_{}.bool false
true.bool true
(-3).bool true
123.456.bool true
nan.bool true
"abc".bool true
[false].bool true
_{a: false}.bool true
break break a container into n parts, or fewer
"abcdefghi".break(2) ["abcde", "fghi"]
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„".break(2) ["πŸ˜€πŸ˜πŸ˜‚", "πŸ˜ƒπŸ˜„"]
a(1, 2, 3, 4, 5).break(3) [[1, 2], [3, 4], [5]]
monthlen.break(2) [ {"January": 31, "February": 28, "March": 31, "April": 30, "May": 31, "June": 30}, {"July": 31, "August": 31, "September": 30, "October": 31, "November": 30, "December": 31} ]
cbrt cube root
27.cbrt 3
ceil, ceiling round numbers up
3.3.ceil 4
century round down by 100s
1995.century 1,900
chars, runes split a string into an array of 1-item strings
"".chars []
"abcdef".chars ["a", "b", "c", "d", "e", "f"]
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„".chars ["πŸ˜€", "😁", "πŸ˜‚", "πŸ˜ƒ", "πŸ˜„"]
"πŸ˜€πŸ˜\nπŸ˜‚\nπŸ˜ƒπŸ˜„".chars ["πŸ˜€", "😁", "\n", "πŸ˜‚", "\n", "πŸ˜ƒ", "πŸ˜„"]
chr
65.chr "A"
chunk break a container into parts, each up to the length given
"abcdef".chunk(3.8) ["abc", "def"]
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„".chunk(2) ["πŸ˜€πŸ˜", "πŸ˜‚πŸ˜ƒ", "πŸ˜„"]
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„".chunk(3) ["πŸ˜€πŸ˜πŸ˜‚", "πŸ˜ƒπŸ˜„"]
a(1, 2, 3, 4, 5, 6, 7, 8).chunk(2) [[1, 2] [3, 4], [5, 6], [7, 8]]
a(1, 2, 3, 4, 5, 6, 7, 8).chunk(3) [[1, 2, 3], [4, 5, 6], [7, 8]]
monthlen.chunk(3) [ {"January": 31, "February": 28, "March": 31}, {"April": 30, "May": 31, "June": 30}, {"July": 31, "August": 31, "September": 30}, {"October": 31, "November": 30, "December": 31} ]
concat, concatenate concatenate into a string
contains does a string contain the substring given?
"abc # 123".contains("# ") true
cos cosine
(pi / 2).cos 0
cosh hyperbolic cosine
(pi / 2).cosh 2.5091784786580567
decade round down by 10s
1995.decade 1,990
dedup, set, unique ignore repeating array items
a(3, 2, "3", 1, 3, "hi!").dedup [3, 2, "3", 1, "hi!"]
deg, degrees turn radians into angular degrees
(pi / 4).degrees 45
pi.degrees 180
dehtml, unhtml unescape/decode HTML symbol-aliases
"Tom & Jerry".dehtml "Tom & Jerry"
deinf replace either number infinity with any alternative
null.deinf(0) null
false.deinf(null) false
0.deinf(null) 0
(-inf).deinf(null) null
inf.deinf(null) null
"".deinf(null) ""
a().deinf(null) []
_{}.deinf(null) {}
del, delete, drop remove keys from object
_{a: 123, b: 456}.del("a") {"b": 456}
_{a: 123, b: 456}.del("a", "b", "c") {}
dirname get directory/folder name
"folder/file.txt".dirname "folder"
dumps, json, stringify turn any supported value into a JSON string
a(1, 2, "abc").json "[1, 2, \"abc\"]"
dup
null.dup(5) [null, null, null, null, null]
false.dup(5) [false, false, false, false, false]
4.dup(10) [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
a("~").dup(5) ["~", "~", "~", "~", "~"]
a().dup(10) []
[4].dup(10) [4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
a(1, 2).dup(4) [1, 2, 1, 2, 1, 2, 1, 2]
a(1, 2).dup(-43) []
endswith, hassuffix check if a string ends as indicated
"line\r".endswith("\r") true
"line".endswith("\r") false
equalfold are 2 strings equal when ignoring unicode-casing?
"TeXt".equalfold("text") true
erf error function
erfc complementary error function
err, error, fail raise an error using the string given
exp exponential function
0.exp 1
1.exp 2.718281828459045
ext get the file extension from a path
"folder/file.txt".ext ".txt"
exp2, pow2 2**x
2.pow2 8
exp10, pow10 10**x
3.pow10 1,000
expm1 e**x - 1, more accurately
1.expm1 1.7182818284590451
fields, words trim a string, then split it on runs of 1 or more spaces
"  abc  123 xy ".fields ["abc", "123", "xy"]
" 123 abc   def".fields ["123", "abc", "def"]
fix, fixed, tofixed turn number into a string rounded to n decimals
123_456.7890123.fix(4) "123456.7890"
fix0, ..., fix9 turn number into a string rounded to n decimals
123_456.7890123.fix0 "123457"
123_456.7890123.fix1 "123456.8"
123_456.7890123.fix2 "123456.79"
123_456.7890123.fix3 "123456.789"
123_456.7890123.fix4 "123456.7890"
123_456.7890123.fix5 "123456.78901"
123_456.7890123.fix6 "123456.789012"
flat, flatten turn array into a shallow one
a(3, a(4, 5), a("abc")).flat [3, 4, 5, "abc"]
float, n, number turn value into a (float64) number
false.n 0
true.n 1
123.456.n 123.456
nan.n NaN
"abc".n NaN
"123.456".n 123.456
floor round numbers down
folds, foldstr, foldstring wrap string into lines using the (optional) max width given
gamma gamma function
pi.gamma 2.288037795340032
1.gamma 1
2.gamma 1
3.gamma 2
4.gamma 6
5.gamma 24
getattr get attribute, or null, or the fallback value given
_{"a": 123}.getattr("abc") null
_{"a": 123}.getattr("abc", nan) NaN
hasattr, hasattrs, haskey, haskeys check if object has all the keys given, or any keys
_{}.hasattrs() false
_{a: 123}.hasattrs() true
_{a: 123}.hasattrs("abc") false
_{a: 123, b: null}.hasattrs("a", "b") true
hasprefix, startswith check if a string starts as indicated
"# comment".hasprefix("# ") true
"abc # 123".hasprefix("# ") false
hex convert number into string of hexadecimal digits
333.hex "14d"
hms2s parse time-duration strings into seconds
"1:23:45:56.23".hms2s 171,956.23
hypot multi-dimensional hypothenuse
hypot(3, 4) 5
hypot(3, 4, 52.8) 53.03621404285943
in is a value in a container?
indexes, indices make an array with numbers 0 .. n-1
-3.1.indices []
0.9.indices []
3.99.indices [0, 1, 2]
a(inf, nan).indices [0, 1]
_{a: 4.5, b: 1}.indices() [0, 1]
isinf check for either infinity
null.isinf false
false.isinf false
nan.isinf false
"abc".isinf false
a(inf, nan).isinf false
_{a: inf, b: nan}.isinf false
inf.isinf true
(-inf).isinf true
isnan check for NaN
null.isnan false
false.isnan false
inf.isnan false
(-inf).isnan false
"abc".isnan false
a(inf, nan).isnan false
_{a: inf, b: nan}.isnan false
nan.isnan true
join join array items using a separator string
a("a", "b", "c", 1, 2, 3).join "abc123"
a("a", "b", "c").join("") "abc"
"".join(a("a", "b", "c")) "abc"
"; ".join(a("a", "b", -7, "c")) "a; b; -7; c"
j0 0th-order bessel j function
j1 1st-order bessel j function
jn(n, x) nth-order bessel j function
lbeta log-beta function
lbeta(1, 2) -0.6931471805599453
len, length count number of items
"abcdef".len 6
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„".len 5
a(1, 2, 3, 550, -2).len 5
_{a: null, b: "hi!"}.len 2
lgamma log-gamma function
ln, log natural logarithm
1.ln 0
e.ln 1
e.log 1
loads, parse, parsejson parse a JSON string
"{\"a\": 1, \"b\": 2}".parse {"a": 1, "b": 2}
log(base, x) logarithm in the base given
log(2, 8) 3
log1p ln(1 + x), to calculate interest more accurately
0.05.log1p 0.0487901641694320
log2 logarithm in base 2
1_024.log2 10
log10 logarithm in base 10
1_000_000.log10 6
logistic logistic function
(-inf).logistic 0
0.logistic 0.5
inf.logistic 1
lower, tolower, tolowercase unicode-lowercase string
"AbCdE".lower "abcde"
"NO SHOUTING, PLEASE!".lower "no shouting, please!"
lstrip, ltrim remove leading whitespace in a string
"    abc".lstrip "abc"
match, matches match strings to RE2-style regular expressions
" xyyyz".matches("xy*z") true
" xyyyz".matches("^xy*z") false
max maximum function, accepts any # of args
max(-3.4) -3.4
max(-3.4, -1_000) -3.4
max(-3.4, -34, 49.4) 49.4
min minimum function, accepts any # of args
min(-3.4, -3453, 49.4, 30) -3453
mod modulus function
3.5.mod(2) 1.5
name2mime guess MIME type from a filepath
"folder/file.mp3".name2mime "audio/mpeg"
"folder/file.mp4".name2mime "video/mp4"
"folder/file.JPG".name2mime "image/jpeg"
neg, negate negate number(s)
(-1.5).neg 1.5
nan.neg NaN
a(1, 2, 3).neg [-1, -2, -3]
_{a: 1, b: 2}.neg() {"a": -1, "b": -2}
not negate boolean
false.not true
true.not false
0.not false
-3.542.not false
nan.not false
pow, power x**y, the power function
2.5.pow(-1.5) 0.2529822128134703
3.pow(a(4.5, 1)) [140.29611541307906, 3]
a(4.5, 1).pow(3) [91.125, 1]
3.pow(_{a: 4.5, b: 1}) {"a": 140.29611541307906, "b": 3}
_{a: 4.5, b: 1}.pow(3) {"a": 91.125, "b": 3}
r0, .., r9, round0, .., round9 round number to n decimal digits
123_456.7890123.r0 123,457
123_456.7890123.r1 123,456.8
123_456.7890123.r2 123,456.79000000001
123_456.7890123.r3 123,456.78900000000
123_456.7890123.r4 123,456.78900000000
123_456.7890123.r5 123,456.78901000001
123_456.7890123.r6 123,456.78901199999
rad, radians turn angular degrees into radians
90.rad 1.570796326794897
rep, repeat
"~".rep(-40) ""
"~".rep(5) "~~~~~"
"~".rep(5, "-") "~-~-~-~-~"
replace, replaceall substitute all substring occurrences
"a b c".replace(" ") "abc"
rev, reverse reverse items
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„".reverse "πŸ˜„πŸ˜ƒπŸ˜‚πŸ˜πŸ˜€"
a(1, 2, 3).reverse [3, 2, 1]
_{a: 1, b: 2}.reverse() {b: 2, a: 1}
round round numbers
21.3.round 21
21.8.round 22
round round to the number of decimals given
21.25.round(0) 21
21.25.round(1) 21.3
21.25.round(2) 21.25
rstrip, rtrim remove trailing whitespace in a string
"123 e \r".rstrip "123 e"
sin sine
pi.sin 0
(pi / 2).sin 1
sinh hyperbolic sine
(pi / 2).sinh 2.301298902307295
split split a string on the separator given
"abc,def,xyz".split(",") ["abc", "def", "xyz"]
"abcdef".split("") ["a", "b", "c", "d", "e", "f"]
"πŸ˜€πŸ˜πŸ˜‚πŸ˜ƒπŸ˜„".split("") ["πŸ˜€", "😁", "πŸ˜‚", "πŸ˜ƒ", "πŸ˜„"]
sqrt square root
2.sqrt 1.4142135623730951
squeeze trim surrounding whitespace and squeeze multiple spaces
" 123    e\r\n".squeeze "123 e"
s, str, string, tostring turn a value into a string
null.str "null"
true.str "true"
-3.75.str "-3.75"
"abc".str "abc"
a(123, "abc").str "[123,"abc"]
_{"a": 1, "b": true}.str() "{a:1,b:true}"
strip, trim remove surrounding whitespace
" 123    e\r\n".strip "123    e"
tan tangent
(pi / 4).tan 1
tanh hyperbolic tangent
(pi / 4).tanh 0.6557942026326724
textafter remove all text up to the end of the substring given
"abcdef".textafter("bc") "def"
"abcdef".textafter("xyz") ""
textbefore remove all text starting from the substring given
"abcdef".textbefore("bc") "a"
"abcdef".textbefore("xyz") "abcdef"
title turn string into a title-cased one
"breakfast in america".titled "Breakfast In America"
"NO SHOUTING, PLEASE!".title "No Shouting, Please!"
tofixed turn number into a string rounded to n decimals
123_456.7890123.tofixed(0) "123457"
123_456.7890123.tofixed(1) "123456.8"
123_456.7890123.tofixed(2) "123456.79"
123_456.7890123.tofixed(3) "123456.789"
toupper, touppercase, upper unicode-uppercase string
"AbCdE".upper "ABCDE"
"No shouting, please!".upper "NO SHOUTING, PLEASE!"
tr, transpose, transposed switch nesting of values
a({a: 123, b: 456}, {a: 789, b: null}).tr {"a": [123, 789], "b": [456, null]}
trim, trimmed, trimspace remove surrounding whitespace
" 123    e\r\n".trim "123    e"
trimbefore remove all text up to the end of the substring given
"abcdef".trimbefore("bc") "a"
"abcdef".trimbefore("xyz") "abcdef"
trimdec, trimdecs, trimdecimals remove excessive trailing zeros after a dot
"123,456,000".trimdec 123,456,000
"123,456.0000".trimdec 123,456
"123,456.789000".trimdec 123,456.789
trimend remove trailing whitespace in a string
"123 e \r".trimend "123 e"
textbefore remove all text starting from the substring given
"abcdef".textbefore("bc") "a"
"abcdef".textbefore("xyz") "abcdef"
trimprefix remove starting substring, if present
"# comment".trimprefix("# ") "comment"
"abc # 123".trimprefix("# ") "abc # 123"
trimstart remove leading whitespace in a string
"    abc".trimstart "abc"
trimsuffix remove ending substring, if present
"text line\r".trimsuffix("\r") "text line"
"text line".trimsuffix("\r") "text line"
trunc, truncate truncate, or round closer to 0
-19.9.trunc -19
19.9.trunc 19
tstype get any value's TypeScript type
null.tstype "null"
false.tstype "boolean"
3.5.tstype "number"
"".tstype "string"
a().tstype "any[]"
a(1, 2, 3).tstype "number[]"
a(-5.3, "abc").tstype "(number | string)[]"
_{a: 1, b: "abc"}.tstype() "interface {\n  \"a\": number\n  \"b\": string\n}"
typeof get any value's type
null.typeof "null"
false.typeof "boolean"
3.typeof "number"
"".typeof "string"
a().typeof "array"
_{}.typeof "object"
y0 0th-order bessel y function
y1 1st-order bessel y function
yn(n, x) nth-order bessel y function
ymd2d parse a date string and get the day as a number
"2020-05-16".ymd2d 16
"2020/05/16".ymd2d 16
ymd2m parse a date string and get the month as a number
"2020-05-16".ymd2m 5
"2020/05/16".ymd2m 5
ymd2y parse a date string and get the year as a number
"2020-05-16".ymd2y 2,020
"2020/05/16".ymd2y 2,020

Examples of Evaluator Functions

all, every do all values satisfy the formula?
a(1, 2, 3, 4, 5) . all(v % 2 == 0) false
any, some do any values satisfy the formula?
a(1, 2, 3, 4, 5) . any(v % 2 == 0) true
assert, must ensure a (pre)condition holds
assert(123.type == "number") null
assert(123.type == "number", "not a number") null
call call a function by name
"c".call("hi", 123) ["hi", 123]
count, countif count how many values satisfy the formula
a(1, 2, 3, 4, 5) . countif(v % 2 == 0) 2
dive like each, but transforms basic values depth-first recursively, keeping the same general nested shape of the input
a(1, 2, 3, 4, 5) . dive(v % 2) [1, 0, 1, 0, 1]
each transform values according to the formula
a(1, 2, 3, 4, 5) . each(v % 2) [1, 0, 1, 0, 1]
a(1, 2, 3, 4, 5) . each(v % 2 == 0) [false, true, false, true, false]
eval evaluate GoTron source code
"5.each(v) . pow2".eval [2, 4, 8, 16, 32]
filter, only keep only the values satisfying the formula
a(1, 2, 3, 4, 5) . filter(v % 2 == 0) [2, 4]
fn, lambda make an anonymous function
group, groupby split array/object by formula
a(1, 2, 3, 4, 5) . group(v % 2) {"1"; [1, 3, 5], "0": [2, 4]}
order, orderby, sort sort array/object using multiple criteria
a("abc", "xyz", "def").sort [3.4, "abc", "def"]
a("abc", "xyz", "def").sort ["abc", "def", "xyz"]
a("abc", "xyz", "def").sort(v.len, -v) ["xyz", "def", "abc"]
a("abc", "xyz", "def").sort(-v) ["xyz", "def", "abc"]
a("abc", "xyz", "def").sort ["abc", "def", "xyz"]
rekey rename all object keys recursively
monthlen.rekey(k.lower[:3]).keys() ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"]
ren, rename rename an object
_{a: 123, b: 456}.rename(k + v) {"a123": 123, "b456": 456}
_{a: 123, b: 456}.rename(_{a: `xyz`}) {"xyz": 123, "b": 456}
surgery recursively transform values of matching object keys
tally make a tally (count) of each distinct result the formula gives
a(1, 2, 3, 4, 5) . tally(v % 2) {"1"; 3, "0": 2}

Complete Examples

Some of these examples are for `jf` (Jeff), instead of `gt` (GoTron).

Wondering how long float64 mantissas will work as unix-style timestamps... are those in millionths or billionths of a second?

gt '2i.pow(_{52,53,64})/_{1e6,1e9}/day/365.25+1970' .

A partial ASCII table.

gt '(space + visascii).each(v, v.ord)' .

Calculate how long do 4GB of PCM-audio (.wav files) last, under various settings.

gt '// 16-bit/2-byte samples, mono or stereo, for both CD-audio and DAT
    _{44_100, 48_000, 96_000} * _{mono: 1, stereo: 2} * 2 &

    // find how many seconds 4 GB last with those settings, playback-wise
    (4 * gb) / _ &

    // turn seconds into HH:MM:SS.SS-style strings
    _ . dive(a(floor(v / 3600), floor(v % 3600 / 60), fix(v % 60, 2)) ^ `:`)
' .

Another way to do it.

gt '// bytes/sec
    (4 * gb) / (_{44_100, 48_000, 96_000} * _{mono: 1, stereo: 2} * 2) &
    // sec to HH:MM:SS.SS
    _ . dive(a(floor(v / hr), floor(v % hr / 60), fix(v % 60, 2)) ^ `:`) &
    // use fancier top-level labels
    _ . each(k + ` hz`, v)
' .

Same as above, but using a more general formula.

jf -from=n '{`${64*v}k`: 8*v: 2..4} * {v.fix1: v: .5*20.iota} * 60'

You say ... about 1500 each day, what range is that a year?

jf -from=n 1500.fuzz*[365,366].kv

Now you tell me it's about 1400-1500 a day, so I guess you meant to say between 1400 and 1500 a day, which makes the yearly ranges...

gt '^a(1400, 1500) * ^a(365, 366)' .

Approximate e using its truncated-series expansions.

gt '_{
    e: e,
    approx: define(a, 0) & (0 ^ 20).each(v, define(a, a + 1 / gamma(v + 1)) & a),
}' .

Get date/time-related info for your timezone.

gt . https://worldtimeapi.org/api/ip

Get date/time-related info for your timezone, then ignore info about your own IP address, so it doesn't show in the result.

gt 'data.drop(`client_ip`)' https://worldtimeapi.org/api/ip

A quick way to view a few integer base-10 logarithms.

gt '10i.each(v, v.log10.fix2)' .

A complete shell function to REPeat the text given.

rep() { jf -from=null "repeat('${1:--}', ${2:-80}, '${3:-}')"; }

Reshape headlines/data from live reuters feed.

gt 'data.rss.channel[0].item .
    each(_{ title: v.title, link: v.link, when: v.pubDate })' \
"https://news.google.com/rss/search?q=when:12h+allinurl:reuters.com&ceid=US:en&hl=en-US&gl=US"

Get URI for JSON exchange rates from the Bank of Canada, since the start of the month: using shell substitution effectively prevents using the string-interpolation syntax, which would interfere with the shell's own substitution syntax.

echo https://www.bankofcanada.ca/valet/observations/group/FX_RATES_DAILY/json?\
start_date=`gt 'now.year + "-" + now.month + "-01"' .`

Get recent `live` exchange rates from the Bank of Canada, and transform values from the latest record. The shell-injected use of the current year is to get a URI for data since the beginning of the current year: this avoids downloading data for several years, thus speeding up things.

gt 'define(
    latest, data.observations[-1],
    rates, latest.drop(`d`).each(k - `FX` - `CAD`, +v.v),
) &
merge(_{ date: latest.d }, rates.sort(k))' \
https://www.bankofcanada.ca/valet/observations/group/FX_RATES_DAILY/json?start_date=`date +%Y`-01-01

Calculate the first 80 fibonacci numbers, since float64 values start giving wrong results at around 80 items.

echo 80 | gt 'define(a, 1, b, 0) & data.each(v, define(b, a + b, a, b) & b)'

Calculate prime numbers using the algorithm with O(n**1.5) time-complexity.

echo 100 | gt 'data .
only(define(n, v) & n != 1 && n.sqrt.all(define(div, v) & (div == 1 || n % div != 0))) .
each((k + 1) + denil(a(`st`, `nd`, `rd`)[k % 10], `th`), v)'

Coming from Excel

excel closest gt concise gt
=CHAR(n) =char(n) n.char, n.rune
=LOWER(s) =lower(s) s.lower
=UPPER(s) =upper(s) s.upper
=TEXTBEFORE(s, t) =textbefore(s, t) s.textbefore(t)
=TEXTAFTER(s, t) =textafter(s, t) s.textafter(t)

Coming from SQL

SQL closest gt concise gt
select * from v order by x v.orderby(x) v.sort(x)
select * from v order by x asc, y desc v.orderby(x, -y) v.sort(x, -y)
printf("%s ...", x) x.str + ... `${x} ...`

Coming from JavaScript

javascript closest gt concise gt
null null nil
true true true
false false false
Math.E e e
Math.PI pi pi
NaN nan nan
Infinity infinity inf
isNaN(n) isnan(n) n.isnan
isFinite(n) isfinite(n) n.isinf.not
!isFinite(n) !isfinite(n) n.isinf
+s +s +s
a.reduce((x, y) => x + y) a.reduce(x + y) a.sum
a.reduce((x, y) => x * y) a.reduce(x * y) a.prod
Math.sin(n) sin(n) n.sin
x.toString() x.tostring() x.str()
s.toLowerCase() s.tolowercase(), s.tolowercase s.lower
s.toUpperCase() s.touppercase(), s.touppercase s.upper
s.replaceAll(t, "") s.replaceall(t, ""), s.replace(t, "") s - t
s.replaceAll(t, u) s.replaceall(t, u), s.replace(t, u) s / t ^ u
a.join(s) a.join(s), s.join(a) a ^ s, s ^ a
s.split(t) s.split(t) s / t
s.split("") s.split("") s.chars, s.runes, ^s, s / ""
String.fromCharCode(n) fromcharcode(n), chr(n) n.char, n.rune, n.chr
n.toString(2) n.tostring(2) n.bin
n.toString(8) n.tostring(8) n.oct
n.toString(16) n.tostring(16) n.hex
JSON.stringify(x) stringify(x) x.json()
JSON.parse(s) parse(s) s.parse
a.length a.length a.len
Object.keys(o) keys(o) o.keys()
Object.values(o) values(o) ^o
c = 0; for (e of s) { c++ }; c s.count(true) s.len
a.map((v, k) => [k, v]) a.map((v, k) => [k, v]) a.map((k, v))
a[a.length - 2] a[a.length - 2] a[-2]
a.slice(0, Math.min(a.length, 8)) a.slice(0, min(a.length, 8)) a[:9], a.first9
a.slice(0, Math.min(a.length, 19)) a.slice(0, min(a.length, 19)) a[:20], a.first(20)
s.repeat(n) s.repeat(n) s * n
a.map(x => 125 * x) a.map(x => 125 * x) 125 * a
+s +s +s

Coming from Python

python closest gt concise gt
None none nil
True true true
False false false
math.e e e
math.pi pi pi
math.tau tau tau
math.nan nan nan
math.inf inf inf
string.whitespace whitespace whitespace
string.punctuation punctuation punctuation
string.digits digits digits
string.hexdigits hexdigits hexdigits
string.ascii_lowercase lowercase lower
string.ascii_uppercase uppercase upper
string.ascii_letters letters letters
math.isnan(n) isnan(n) n.isnan
math.isinf(n) isinf(n) n.isinf
float(s) float(s) +s
sum(a) sum(a) a.sum
prod(a) prod(a) a.prod
math.sin(n) sin(n) n.sin
str(x) str(x) str(x)
tolower(s) tolower(s) s.lower
toupper(s) toupper(s) s.upper
s.replace(t, "") s.replace(t, "") s - t
s.replace(t, u) s.replace(t, u) s / t ^ u
s.join((str(e) for e in a)) s.join(a), a.join(s) s ^ a, a ^ s
s.split(t) s.split(t) s / t
[e**2 for e in a] a.pow(2) a.pow2()
[e for e in s] s.each(v) s.chars, s.runes, s / ""
[tolower(e) for e in a] aeach(tolower(v)) a.lower
[[log2(f) for f in e] for e in a] [e => [f => log2(f): e]: a] a.log2
ord(s) ord(s) s.ord
bin(n) bin(n) n.bin
hex(n) hex(n) n.hex
json.dumps(x) dumps(x) x.json()
json.loads(s) loads(s) s.loads, s.parse
len(s) len(s) s.len
len(a) len(a) a.len
list(o.keys()) o.keys() o.keys()
list(o.values()) o.values() ^o
list(enumerate(a)) a.each(i, v) a.each(i, v)
list(range(n)) indices(n), indexes(n) *n
list(range(1, n+1)) seq(1, n) n.each(v), 1^n
list(range(m, n+1)) m^n m^n
a[-2] a[-2] a[-2]
a[:min(len(a), 9)] a[:min(len(a), 9)] a[:9], a.first9
a[:min(len(a), 20)] a[:min(len(a), 20)] a[:20], a.first(20)
25 * s 25 * s 25 * s
[125 * e for e in a] a.each(125 * v) 125 * a

Function Names

A recent run of the following command results in the table below.

jf -from=null -to=html 'funcs().toentries().map({name: v[0], type: v[1]})'

name type
name type

Values

Before showing most variables, here are some special-use variables.

name type uses

The following (shell) script created the table shown right after.

#!/bin/sh

name value
name value