Syntax Reference

Records and Patterns

Eve represents data as attribute-value pairs called records. They can have many attributes and attributes can have many values. ``` commit [tag: "person" age: 30, name: "Jeff"] [tag: "boat" tag: "expensive" type: "yacht"] ```
The tag attribute is used to indicate the type of a record. #foo is short for tag: "foo". ``` search [#person] = [tag: "person"] ```
You can alias an attribute to a different name like age: person-age. Without an alias, the name of the attribute is bound to its value. ``` search // These do the same thing. person-age = 20 [#person age: person-age] age = 20 [#person age] ```
Records can be nested to find or create relationships. Note: All records in Eve are global. The Ryan record can still be matched on its own. ``` commit [#person name: "Chris" brother: [#person name: "Ryan"] [#person name: "Jeff" age: 20]] ```
Attributes can also be accessed using dot notation. ``` search person = [#person] person.brother = [name: "Ryan"] ```
You can search for records by pattern. Eve will match records based on the pattern of attributes you provide. Any attributes you don’t provide a value for will be filled in from the matches. ``` search me = [#person brother] bind [#my-family me relative: brother] ```

Program Structure: Search, Bind, and Commit

Eve programs are markdown documents, with code blocks fenced between three grave (`) or tilde (~) characters. In each block you (optionally) search for patterns, then either bind or commit new or updated records for each match found. Note: With no search, the records are automatically added once. # An example Eve program ``` search // Find something interesting [#person name] bind // Do something with it [#ui/text text: name] ```
The search section finds records matching its patterns, staying up to date as data changes.Ifthere aren’t any matches, the bind or commit will do nothing. ``` search person = [#person name: "Jeff"] person.age = 20 ```
The bind section creates or updated records from your pattern. Since this is a bind, when the search stops matching, those records or updates disappear. ``` search person = [#person name: "Jeff" age] bind [#my-age age] ```
Like bind, the commit section creates or updates records. Unlike bind, it does so permanently.Ifthe search stops matching, the records will remain. ``` search [#html/event/click element] commit [#ui/text text: "You clicked on {{element}}!"] ```

Equivalence and Filtering

Eve has equivalence instead of assignment. Instead of setting Jeff’s age to 20, equivalence causes us to only find the people whose age is 20. ``` search // Filter for people named "Jeff" who are 20 years old. person = [#person name: "Jeff" age] age = 20 ```
Nothing can be equivalent to two different values at once. ``` search // Something that always fails. x = 10 x = 100 ```
Using the same variable in two patterns will find pairs where the value is the same. ``` search // pairs of boats and people with the same age. person = [#person age] boat = [#boat age] bind [#ui/text text: "{{person.name}} has an old boat"] ```
You can also filter using inequalities. ``` search // Filter within an attribute. cube = [#rectangle width > 30 height] height > 30 // Filter a variable. cube.depth > 30 // Filter with dot notation. ```

Not

You can check for the absence of any matching record for a search by wrapping it in not(). ``` search // People who are not employees. person = [#person] not(person = [#employee]) ```

If…Then and If…Else

If lets your block try multiple branches for a variable. If every branch has no matches, the block fails.

If … else lets you express ordered choice. Only the first branch with matches will contribute values to the variable. ``` search [#todo filter] switch = if filter = "completed" then 1 else if filter = "active" then 2 else if filter = "all" then 3 ```
Multiple If statements without else let each branch contribute to a variable (equivalent to union). ``` search // All my friends and their spouses are party guests. guest = if f = [#friend] then f if [#friend spouse] then spouse ```
If can return multiple values each. Note: Each branch must return the same number! ``` search (pts, pass) = if score > 90 then (3, "true") if score > 70 then (1, "true") else (0, "false") ```

Functions and Aggregates

Functions are record-like constructs that return values. ``` search // The sin function with input in degrees. x = sin[degrees: 30] // …or radians x = sin[radians: 3 * π / 180] ```
Aggregates return a value (or value per group) for all matches of your search (akin to reduce() in other languages). Eve will set collapse inputs to an aggregate. That is, if you have 5 unique salary levels for 100 employees, Eve would add each unique salary once. To adjust this, specify the actual identity (employee) you care about with for. To get a value per group, specify the grouping variables with per. ``` search // *for* specifies the matches to count. total-employees = gather/count[for: employee] // *value* is the number to add to the sum // *per* specifies the groups to sum the matches in. budgets = gather/sum[value: employee.salary, for: employee, per: employee.department] ```

Update Operators

Besides creating new records, Eve has four operators to modify existing records in bind or commit.

(+=) Add value to attribute. ``` search chris = [#chris] commit chris.likes += "pizza" ```
(-=) Remove value of attribute. Note: An attribute with no values ceases to exist. ``` search chris = [#chris] commit chris.likes -= "eggplant" ```
(:=) Set value of attribute. Set is the same as removing the current value(s) and adding the new value(s). ``` search chris = [#chris] commit chris.age := 30 ```
(<-) Merge pattern into record. Attributes from the pattern on the right overwrite those of the record on the left. ``` search chris = [#chris] commit chris <- [eye-color: "green", hair-color: "brown"] ```
The set operator with the special value none deletes entire attributes and records. Note: This should usually be done in commits. ``` search chris = [#chris] commit chris.likes := none chris := none ```