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. [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”. [#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. // 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. [#person name: “Chris” brother: [#person name: “Ryan”] [#person name: “Jeff” age: 20]]
Attributes can also be accessed using dot notation. person = [#person] = [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 [#html/div 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 [#html/div text: “You clicked on !”]

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. // 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. // Something that always fails. x = 10 x = 100
Using the same variable in two patterns will find pairs where the value is the same. // pairs of boats and people with the same age. person = [#person age] boat = [#boat age]
You can also filter using inequalities. // Filter within an attribute. cube = [#rectangle width > 30 height] height > 30 // Filter a variable. cube.depth > 30 // Filter with dot notation.


You can check for the absence of any matching record for a search by wrapping it in not(). // 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.
Multiple If statements without else let each branch contribute to a variable (equivalent to union). // 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! (points, passing) = 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. // 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. // *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. chris.likes += “pizza”
(-=) Remove value of attribute. Note: An attribute with no values ceases to exist. chris.likes -= “eggplant”
(:=) Set value of attribute. Set is the same as removing the current value(s) and adding the new value(s). chris.age := 30
(<-) Merge pattern into record. Attributes from the pattern on the right overwrite those of the record on the left. 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