Fabric is a simple formula based programming language for CouchDb. Fabric is intended to be a pragmatic and simplified language for the purpose of querying and processing data in CouchDb.
This is a brief introduction to Fabric. See the FabricTests page to see more, it contains actual test formulas that gets run and validated by the Fabric test suite.
Basics
Hello World in Fabric:
"Hello World!"
Ok, not terribly useful, its sort of like a Hello World In SQL. Here is an expression that concatenates fields FirstName and LastName and assigns it to variable FullName.
FullName := FirstName + " " + LastName
The colon-equals (:=) is the assignment operator and plus (+) is the string concatation operator (and it's the number addition operator when used with numbers).
Here is the same expression, but it converts the full name to uppercase:
FullName := Uppercase(FirstName + " " + LastName)
It has integer and floating point math support, some simple examples:
x := 5 // x is 5
squared := x*x // squared is 25
foo := (x + 7)*2 // foo is 24
bar := 5/2.5 // bar is 2
Argument separators are commas:
SomeFunction(arg1,arg2,...,argN)
Newlines are statement seperators and semi-colons are optional. The underscore continues a statement to the next line:
x := 1 // no semi
y := 2; // optional semi, no effect here
foo = 1; bar = 2; // two statements on one line
z := x + _ // continues statement on next line
y;
Lists
All values are lists (or arrays if you prefer) and they may contain many different types of elements. A list can contain any mix of strings, numbers, dates, etc. Element cannot exist outside of lists, a single element is actually a list with only one value.
Colon is the list concatenation operator. This example concatenates the lists in quantity1 through quantity4 into one list. Then it sums the total of the elements in the list:
foo := quantity1 : quantity2 : quantity3 : quantity4
Sum(foo)
A mixed type list:
Foo := 1 : "123 Fake st" : 3 : 5.67 : [10/24/1973]
Type Conversion
Fabric has implicit type conversion:
Foo := "1" + 3 // Foo is "13"
Bar := Number("1") + 3 // Bar is 4
Baz := Sum("1" : 2) // Baz is 3
Functions and operations that operate on elements of one type will automatically convert, if possible, elements to the correct datatype. Otherwise an error is generated.
Field concatenation
Concatenating a sequentially numbered fields into a single list has a simple syntax:
foo := date1..15
Will take the values in fields date1 through date15 and combine them into a single list. The second operand can bea variable or expression:
N := 15
foo := date1..N // foo is now the values of date1 through date15
foo := date1..(N - 1) // foo is now the values of date1 through date14
This will combine all fields date1, date2, date3 and so one until a field in the sequence is missing:
foo := date1..*
Branching
if (condition) {
DoSomething1()
DoSomething2()
} else {
DoSomethingElse1()
DoSomethingElse2()
}
foo := if (condition) {
bar1
}
foo := if (condition) {
bar1
} else (condition2) {
bar2
} else {
bar3
}
The terse form of the previous expression:
foo := if(condition, bar1, condition2, bar2, bar3)
User Defined Functions
You can define and call your own functions:
// Foo is a function that multiplies two number lists
// and converts them to text
function Foo(A, B) {
Text(A * B)
}
Bar := %Foo(2, 8) // Bar is "16"
x := 2 : 3
y := 8 : 9
Bar2 := %Foo(x, y) // Bar2 is "16" "27"
All user defined functions need the identifier prepended with "%". (This way so there is no collision between the core functions and avoids the need for complicated things like namespace support).
Looping/Iteration
The only looping construct I'm including for iterating over elments in a list using a forall construct. The expression is evaluated for each element and the result is used to construct a new list.
In this example, it checks each element in List to see if it starts with the letter "b", if it does, it returns the Uppercase version of the element, otherwise it returns the element unchanged. These elements then go to constructing a new list and assigning it to Foo:
CitiesList : = "baltimore" : "chicago" : "new york" : "buffalo"
NewCitiesList := forall(City in CitiesList) {
if (Begins(City, "b")) {
Uppercase(City)
} else {
City
}
}
// NewCitiesList is now "BALTIMORE" : "chicago" : "new york" : "BUFFALO"
You can process multiple lists in parallel. This example, compares each element in two lists(1st compared with 1st, 2nd compare with 2nd, etc), and returns a third list that is composed of the largest element in each corresponding list:
Foo := forall(A in ListA, B in ListB) {
if(A > B, A, B)
}
And if one list is shorter than another, the last element is reused in subsequent iterations.
So for example:
listA := 5 : 8 : 2 : 10 : 3
listB := 6 : 7 : 9
Foo := forall(A in ListA, B in ListB) {
if(A > B, A, B)
}
This produces the result 6 : 8 : 9 : 10 : 9 in Foo.
List Subscript
Brackets are used for array subscript style access, and is 1 based;
Colors := "red" : "blue" : "yellow"
Foo := Colors[1] // foo is "red"
Foo := Colors[2] // foo is "blue"
Foo := Colors[3] // foo is "yellow"
2 arguments in the brackets has a subset range meaning, where the first argument is the start position, the second is the end position and a new list is created with all the elements from start to end, inclusive:
Colors := "red" : "violet" : "blue" : "green" : "yellow" : "orange"
Foo := colors[2, 4]
// foo is "violet" : "blue" : "green"
Querying and Table Specification
Section in progress -- Damien
Fabric is designed as a document query language. This is an example of a computed table definition:
SELECT Type = "Bug Report"
COLUMN PostedDate := PostedDate
COLUMN Subject := Subject
last updated 2 years ago
#
http://blog.360.yahoo.com/blog-YpWPtuU8erQlw6QDlT1B56LhS1th?p=36 <a href=http://blog.360.yahoo.com/blog-YpWPtuU8erQlw6QDlT1B56LhS1th?p=36texas> holdem online</a> [url=http://blog.360.yahoo.com/blog-YpWPtuU8erQlw6QDlT1B56LhS1th?p=36]texas holdem online[/url] http://blog.360.yahoo.com/blog-w38pk2Y3KasX7C3Bnqx2fqy.o5do5w--?p=91 <a href=http://blog.360.yahoo.com/blog-w38pk2Y3KasX7C3Bnqx2fqy.o5do5w--?p=91mbna> credit card application</a> [url=http://blog.360.yahoo.com/blog-w38pk2Y3KasX7C3Bnqx2fqy.o5do5w--?p=91]mbna credit card application[/url] http://blog.360.yahoo.com/blog-tV.f8gYjfqIgIPrwudVniGmPfYuJ?p=135 <a href=http://blog.360.yahoo.com/blog-tV.f8gYjfqIgIPrwudVniGmPfYuJ?p=135payday> loan with savings account only</a> [url=http://blog.360.yahoo.com/blog-tV.f8gYjfqIgIPrwudVniGmPfYuJ?p=135]payday loan with savings account only[/url] http://blog.360.yahoo.com/blog-px_ffc4neqhLx9zqN_L_tERiIjxlsQ--?p=10 <a href=http://blog.360.yahoo.com/blog-px_ffc4neqhLx9zqN_L_tERiIjxlsQ--?p=10free> online blackjack</a> [url=http://blog.360.yahoo.com/blog-px_ffc4neqhLx9zqN_L_tERiIjxlsQ--?p=10]free online blackjack[/url] <a href=http://blog.360.yahoo.com/blog-lO.cEUshLar9W0gT4RBXO8QBD1R8?p=117citi> credit card account</a> http://blog.360.yahoo.com/blog-lO.cEUshLar9W0gT4RBXO8QBD1R8?p=117 [url=http://blog.360.yahoo.com/blog-lO.cEUshLar9W0gT4RBXO8QBD1R8?p=117]citi credit card account[/url]
1 year ago # reply