Goal Docs

Translating Lil’s examples to Goal

We show below an html highlighted version of the Goal file found at examples/lil.goal in the repos.

/ Translation of Lil examples (as of 2024-09-12) from the manual:
/   https://beyondloom.com/decker/lil.html#lilthequerylanguage
/ For each example, the Lil version is written in a comment, followed by the
/ translation(s) in Goal, and then by the ouput (when appropriate).
(env"GOALLIB")or"GOALLIB"env"../lib"
import!"fmt math table" / assuming GOALLIB contains now goal's lib directory
pp:fmt.tbl[;0i-1;0i-1;"%.1f"] / pretty-printing function for tables

/ people.name:"Alice","Sam","Thomas","Sara","Walter"
/ people.age:25,28,40,34,43
/ people.job:"Developer","Sales","Developer","Developer","Accounting"
/ people:table people
people:..[
  name:!"Alice Sam Thomas Sara Walter"
  age:25 28 40 34 43
  job:!"Developer Sales Developer Developer Accounting"
]

/ select from people
pp people
/ === Table 5x3 ===
/     name age          job
/ -------- --- ------------
/  "Alice"  25  "Developer"
/    "Sam"  28      "Sales"
/ "Thomas"  40  "Developer"
/   "Sara"  34  "Developer"
/ "Walter"  43 "Accounting"

/ select name from people
pp(,"name")#people
pp people[;"name"]
/ === Table 5x1 ===
/     name
/ --------
/  "Alice"
/    "Sam"
/ "Thomas"
/   "Sara"
/ "Walter"

/ select firstName:name dogYears:7*age from people
pp people....[firstName:name;dogYears:7*age]
/ === Table 5x2 ===
/ firstName dogYears
/ --------- --------
/   "Alice"      175
/     "Sam"      196
/  "Thomas"      280
/    "Sara"      238
/  "Walter"      301
 
/ select name where name like "S*" from people
pp("name";..rx/^S/name)#people
pp("name";.."S*"%name)#people
/ === Table 2x1 ===
/   name
/ ------
/  "Sam"
/ "Sara"
 
/ select name index orderby name asc from people
pp(..x@<name)people[;"name"]..[index:!#name]
pp@|"index""name"!people..1(name@)\<name
/ === Table 5x2 ===
/     name index
/ -------- -----
/  "Alice"     0
/    "Sam"     1
/   "Sara"     3
/ "Thomas"     2
/ "Walter"     4
 
/ select name job by job orderby name asc from people
pp(..x@<%job)(..x@<name)"name""job"#people
/ === Table 5x2 ===
/     name          job
/ -------- ------------
/  "Alice"  "Developer"
/   "Sara"  "Developer"
/ "Thomas"  "Developer"
/    "Sam"      "Sales"
/ "Walter" "Accounting"

/ select name job orderby (job join name) asc from people
pp(..x@<job)(..x@<name)"name""job"#people
/ === Table 5x2 ===
/     name          job
/ -------- ------------
/ "Walter" "Accounting"
/  "Alice"  "Developer"
/   "Sara"  "Developer"
/ "Thomas"  "Developer"
/    "Sam"      "Sales"

/ select employed:(count name) job by job from people
pp table.join["job";table.by["job";{..[employed:=y]};people];people[;"job"]]
pp (..x@&employed)table.by["job";{..[employed:=y]};people]
pp people[;"job"]..[employed:(=q.by)q.by:%job] / original order
/ === Table 5x2 ===
/          job employed
/ ------------ --------
/  "Developer"        3
/  "Developer"        3
/  "Developer"        3
/      "Sales"        1
/ "Accounting"        1

/ select employed:(count name) job:(first job) by job from people
pp table.by["job";{..[employed:=y]};people]
pp people....[job:?job;employed:=%job]
/ === Table 3x2 ===
/          job employed
/ ------------ --------
/  "Developer"        3
/      "Sales"        1
/ "Accounting"        1

/ on avg x do (sum x) / count x end
/ select job:(first job) avg_age:avg[age] by job from people
pp table.by["job";....[avgage:math.avg'=age!y];people]
pp people....[job:?job;avgage:math.avg'=age!%job]
/ === Table 3x2 ===
/          job avgage
/ ------------ ------
/  "Developer"   33.0
/      "Sales"   28.0
/ "Accounting"   43.0

/ update job:"Engineer" where job="Developer" from people
pp people..[job[&job="Developer"]:"Engineer"]
/ === Table 5x3 ===
/     name age          job
/ -------- --- ------------
/  "Alice"  25   "Engineer"
/    "Sam"  28      "Sales"
/ "Thomas"  40   "Engineer"
/   "Sara"  34   "Engineer"
/ "Walter"  43 "Accounting"

/ update manager:random[name] where job="Developer" from people
pp people..[manager:("";*1?name)job="Developer"]
/ === Table 5x4 ===
/     name age          job manager
/ -------- --- ------------ -------
/  "Alice"  25  "Developer"   "Sam"
/    "Sam"  28      "Sales"      ""
/ "Thomas"  40  "Developer"   "Sam"
/   "Sara"  34  "Developer"   "Sam"
/ "Walter"  43 "Accounting"      ""

/ jobs:extract first job by job from people
say$jobs:?people..job
/ "Developer" "Sales" "Accounting"

/ extract value orderby value asc from jobs
say$^jobs
/ "Accounting" "Developer" "Sales"

/ extract index orderby value asc from jobs
say<jobs
/ 2 0 1

/ extract value orderby index desc from jobs
say$|jobs
/ "Accounting" "Sales" "Developer"

/ extract list index by value from "ABBAAC"
say{=(!#x)!%x}@""\"ABBAAC"
/ (0 3 4
/  1 2
/  ,5)

/ extract list value by floor index/3 from "ABCDEFGHI"
say-3$""\"ABCDEFGHI"
/ ("A" "B" "C"
/  "D" "E" "F"
/  "G" "H" "I")

/ extract first value by value from "ABBAAC"
say$?""\"ABBAAC"
/ "A" "B" "C"

/ extract a:first age b:last age orderby age asc from people
say((..x@<age)people)....[a:*age;b:*|age]
/ !["a" "b"
/   25 43]

/ extract orderby value asc from "BEDAC"
say$^""\"BEDAC"
/ "A" "B" "C" "D" "E"

/ insert name job age with "John" "Writer" 32 end
pp@..[name:,"John";job:,"Writer";age:,32]
/ === Table 1x3 ===
/   name      job age
/ ------ -------- ---
/ "John" "Writer"  32

/ insert name job age with "John" "Writer" 32 into people
pp people,'..[name:"John";job:"Writer";age:32]
/ === Table 6x3 ===
/     name age          job
/ -------- --- ------------
/  "Alice"  25  "Developer"
/    "Sam"  28      "Sales"
/ "Thomas"  40  "Developer"
/   "Sara"  34  "Developer"
/ "Walter"  43 "Accounting"
/   "John"  32     "Writer"

/ jobs:insert job salary with
/  "Sales"      85000
/  "Developer"  75000
/  "Accounting" 60000
/  "Facilities" 50000
/ end
jobs:"job""salary"!+(
 "Sales"      85000
 "Developer"  75000
 "Accounting" 60000
 "Facilities" 50000
)

/ people join jobs
pp table.join["job";people;jobs]
/ === Table 5x4 ===
/     name age          job salary
/ -------- --- ------------ ------
/  "Alice"  25  "Developer"  75000
/    "Sam"  28      "Sales"  85000
/ "Thomas"  40  "Developer"  75000
/   "Sara"  34  "Developer"  75000
/ "Walter"  43 "Accounting"  60000

/ guests:insert name with "Alice" "Joan" "Oscar" "Thomas" end
/ select a:name b:name_ where name < name_ from guests cross guests
pp(1;..a<b)#"a""b"!+,/{x,`´x}@!"Alice Joan Oscar Thomas" / same order
pp(1;..a<b)#"a""b"!{x@´!2##x}@!"Alice Joan Oscar Thomas" / odometer's order (more efficient)
/ === Table 6x2 ===
/       a        b
/ ------- --------
/ "Alice"   "Joan"
/ "Alice"  "Oscar"
/ "Alice" "Thomas"
/  "Joan"  "Oscar"
/  "Joan" "Thomas"
/ "Oscar" "Thomas"

/ "name" take people
pp(,"name")#people
/ === Table 5x1 ===
/     name
/ --------
/  "Alice"
/    "Sam"
/ "Thomas"
/   "Sara"
/ "Walter"

/ ("age","job") take people
pp"age""job"#people
pp people[;"age""job"] / same but reorder columns (if order were different)
/ === Table 5x2 ===
/ age          job
/ --- ------------
/  25  "Developer"
/  28      "Sales"
/  40  "Developer"
/  34  "Developer"
/  43 "Accounting"

/ 3 drop people
pp 3_'people
/ === Table 2x3 ===
/     name age          job
/ -------- --- ------------
/   "Sara"  34  "Developer"
/ "Walter"  43 "Accounting"

/ (0,2,3) take people
pp people 0 2 3
/ === Table 3x3 ===
/     name age         job
/ -------- --- -----------
/  "Alice"  25 "Developer"
/ "Thomas"  40 "Developer"
/   "Sara"  34 "Developer"

/ expenses:insert kind jan feb with
/  "tax"   11 55
/  "gas"   22 66
/  "power" 33 77
/  "food"  44 88
/ end
expenses:(!"kind jan feb")!+(
  "tax"   11 55
  "gas"   22 66
  "power" 33 77
  "food"  44 88
)

/ flip expenses
pp table.flip expenses
/ === Table 2x5 ===
/   key tax gas power food
/ ----- --- --- ----- ----
/ "jan"  11  22    33   44
/ "feb"  55  66    77   88

/ "key" drop flip expenses
pp (,"key")^table.flip expenses
/ === Table 2x4 ===
/ tax gas power food
/ --- --- ----- ----
/  11  22    33   44
/  55  66    77   88

/ denormal: select "with \"escapes":index "count":value from "ABC"
pp denormal:{..["with \"escapes":!#x;count:x]}@""\"ABC"
/ === Table 3x2 ===
/ with "escapes count
/ ------------- -----
/             0   "A"
/             1   "B"
/             2   "C"

/ insert "pet name" "pet species" with
/  "Galena"  "Chicken"
/  "Pippi"   "Chicken"
/  "Chester" "Toad"
/ end
pp "pet name" "pet species"!+(
  "Galena"  "Chicken"
  "Pippi"   "Chicken"
  "Chester" "Toad"
)
/ === Table 3x2 ===
/  pet name pet species
/ --------- -----------
/  "Galena"   "Chicken"
/   "Pippi"   "Chicken"
/ "Chester"      "Toad"

/ select where column["with \"escapes"]>0 from denormal
pp(1;{x["with \"escapes"]>0})#denormal
/ === Table 2x2 ===
/ with "escapes count
/ ------------- -----
/             1   "B"
/             2   "C"

/ # Example from https://beyondloom.com/blog/rankingoffruits.html
/ fruits:insert name sales with
/      "Cherry" 22
/      "Lime"    5
/      "Durian" 97
/      "Banana" 12
/      "Apple"   1
/ end
fruits:..[name:!"Cherry Lime Durian Banana Apple"
          sales:22 5 97 12 1]

/ select orderby sales desc where !name like "D*" from fruits
pp(..x@>sales)(0;.."D*"%name)^fruits
/ === Table 4x2 ===
/     name sales
/ -------- -----
/ "Cherry"    22
/ "Banana"    12
/   "Lime"     5
/  "Apple"     1