Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 912 lines (664 sloc) 30.067 kB
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
1 Getting started
2 ===============
3
4 Your first Opa program:
5
6 * Get Opa from [its web-page](http://opalang.org/).
7 * In `hello.opa` write:
8
9 Server.start(Server.http,
10 { title: "Chat"
11 , page: function() { <>Hello web</> }
12 }
13 )
14
15 * Compile (yes, Opa is a *compiled* language) with: `opa hello.opa`
16 * Run with: `./hello.exe`
17 * (You can also combine the two above steps with: `opa --parser js-like hello.opa --`)
18 * Test by opening [http://localhost:8080](http://localhost:8080) in your browser.
19
20 The language
21 ============
22
23 Comments
24 --------
25
26 Opa supports both single and multi-line comments.
27
28 // This is a single line comment. It goes until the end of the line
29
30 /* this is a
31 multi-line comment,
32 which must be closed with: */
33
34 Type declarations
35 -----------------
36
37 Opa features almost complete type-inference so often, especially at the prototyping phase, you can write your programs without explicitly defining any types and they will be inferred by the compiler. However, you'll learn to appreciate the value of defining explicit types for important notions in your program: it greatly improves readability of your programs (serving as a documentation of sorts) and also allows Opa to produce much more readable and accurate error information.
38
39 // type abbreviation
40 type age = int
41
42 // functional types
43 /* meaning: a function taking two arguments: the first one is an int, the
44 second one is a string. It returns an integer */
45 type binary_fun = int, string -> int
46
47 // record types
48 type person = { string name, int age }
49
50 // parametrized (polymorphic) types
51 /* meaning: a binary operator of a parametric type */
52 type operator('ty) = 'ty, 'ty -> 'ty
53
54 // variant (sum) types
55 type boolean = {true} or {false}
56 // equivalent to:
57 /* i.e. we can omit the type if it's void, in which case the record
58 field just acts as a label (carries no information, except for its presence). */
59 type boolean2 = {void true} or {void false}
60
61 // parametrized variant type
62 type option('a) = {'a some} or {none}
63
64 // recursive type
65 type list('a) = {nil} or {'a hd, list('a) tl}
66 type bin_tree('a) = {'a leaf} or {tree('a) left, tree('b) right}
67
68 //[TODO]: Add module types and functor types
69
70 Expressions
71 -----------
72
73 ### Functions
74
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
75 #### Function declarations
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
76
77 // function declaration
7edcd80 @akoprow [fix] Doc/refcard: few fixes.
akoprow authored
78 function int incr(int x)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
79 {
80 x + 1
81 }
82
83 // type annotations for arguments and results can be omitted
84 function incr_alt(x) { x + 1 }
85
86 // function with local bindings and using tuples for arguments
87 function distance((x1, y1), (x2, y2)) {
88 dx = x1 - x2
89 dy = y1 - y2
90 Math.sqrt_f(dx*dx + dy*dy)
91 }
92
93 // anonymous function
94 function(x) { x + 1 }
95
7edcd80 @akoprow [fix] Doc/refcard: few fixes.
akoprow authored
96 // mutually recursive functions; 'recursive' and 'and' only
97 // needed for *local* functions (not needed at top-level)
98 recursive function odd(x) { if (x == 1) true else even(x-1) }
99 and function even(x) { if (x == 0) true else odd(x-1) }
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
100
101 //[TODO]: Add recursive functions
102 //[TODO]: Add partial application
103
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
104 #### Function/module modifiers
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
105
106 The following modifiers can alert the declaration of the function in some way.
107
108 // Visibility modifiers:
109 private function priv_fun() {...} // function is invisible outside of its module
110 public function pub_fun() {...} // function is visible from other modules
111
112 // Distribution modifiers:
113 server function server_fun() {...} // function will be on the server
114 client function client_fun() {...} // function will be on the client
115
116 // Security modifiers:
117 exposed function exposed_fun() {...} // marks an entry-point (function can be called from the client)
118 protected function protected_fun() {...} // function should not be exposed to the client
119
120 ### Strings
121
122 Strings are primitive types in Opa.
123
124 String literals are constructed using double quotes `"..."`. Please note that single quotes `'...'` are **not allowed** for strings in Opa.
125
126 string s = "This is a string"
127
128 String concatenation. See also [here](/refcard/Standard-library/General-data-types/string) for more about functions for string manipulation.
129
130 string hello = "Hello" ^ " world"
131
132 A particular feature of Opa are *inserts*, which you'll use a lot. They allow to insert values into a string using curly braces.
133
134 // hence:
135 "{x} + {y} = {x+y}"
136 // is equivalent to:
137 x ^ " + " ^ y ^ " = " ^ (x + y)
138
139 You'll see that Opa also features [HTML inserts](/refcard/The-language/Expressions/XHTML).
140
141 ### XHTML
142
143 XHTML is a [defined](/type/stdlib.core.xhtml/xhtml) not a primitive type in Opa, but there is a built-in syntax support for constructing XHTML values.
144
145 Here we only present an overview of the syntax used for XHTML; you'll find more info about functions for operating on this data-type [here](/refcard/Standard-library/Web-features/XHTML).
146
147 type xhtml = ...
148 // XHTML is a data-type with built-in syntax
149 xhtml span = <span class="test">Hello XHTML</span>
150 // closing tag is optional, so are the quotes around literal attributes
151 span2 = <span class=test>Hello XHTML</>
152
153 Inserts work in XHTML too (both for tags & attributes)
154
155 function mk_span(class, body) {
156 <span class="{class}">
157 {body}
158 </>
159 }
160
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
161 #### DOM manipulations
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
162
163 DOM (Document Object Model) is a representation of X(HT)ML. You will often interact with the DOM to dynamically change the content of the page.
164
165 You will find more about functions to manipulate the DOM [here](/refcard/Standard-library/Web-features/DOM). Below we just present few syntactical goodies that make it easier to make some most common transformations.
166
167 // manipulating (replacing/prepending/appending) DOM content for a given ID
168 #toto = <h1>Replace</>
169 #toto += <h1>Prepend</>
170 #toto =+ <h1>Append</>
171
172 // manipulating DOM selection
173 dom_pointer = Dom.select_children(#toto)
174 *dom_pointer += <h2>before</>
175
176 // manipulating CSS
177 // #toto css = {color : blue}
178 // [WARNING] manipulating CSS above; syntax doesn't work as of Dec 1, 12:00
179
180 ### Records
181
182 While working with Opa you'll use records *a lot*. Therefore it's probably a good idea to get familiar with their syntax right away.
183
184 // full record construction
185 john = { name: "John Smith", age: 31}
186 // accessing record fields
187 john_string = "Name: {john.name}, Age: {john.age}"
188
189 // tilde-shortcut
190 name = ...
191 age = ...
192 // '~field' within the record abbreviates 'field: field'
65ba951 @Aqua-Ye [doc] refcard: typo
Aqua-Ye authored
193 person = { ~name, ~age }
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
194 // one can even also abbreviate all fields by putting tilde in front of the record
65ba951 @Aqua-Ye [doc] refcard: typo
Aqua-Ye authored
195 person2 = ~{ name, age }
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
196 // both 'person' and 'person2' are equivalent to
197 person3 = { name: name, age: age }
198
199 // record extension
200 // meaning: take record 'john' and replace its 'age' field with the given value
201 older_john = { john with age: john.age + 1 }
202
203 ### Pattern matching
204
205 Pattern matching is used to analyze values that may take several variants.
206
207 // pattern matching on boolean values
208 bool x;
209 match (x) {
210 case {true}: ...
211 case {false}: ...
212 }
213
214 // pattern matching on a record representing an URL
215 match (url) {
216 // record field path is an empty list
217 // '...' indicates there may be more fields in the record
218 case {path:[] ...}: show_root()
219 // any path, bound to 'path' identifier
220 case {path:path ...}: show_at(path)
221 // equivalent to the above case
222 case {~path ...}: show_at(path)
223 // default case
224 default: show_root()
225 }
226
227 //### Parsing
228 //[TODO]
229
230 Database
231 --------
232
233 In Opa the database is tightly integrated in the language. At the moment the compiler supports 2 DB backends:
234
235 - db3: Opa's internal database
236 - MongoDB: [http://www.mongodb.org/](http://www.mongodb.org/)
237
238 One can choose the back-end with the `--database {mongo/db3}` compiler switch. Combining two different backends in one program is possible.
239
240 ### Simple types
241
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
242 #### Declaring
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
243
244 Declare a collection of database values called `person`
245
246 database person {
247 // it contains an integer value 'age'
248 int /age
249 // a float value 'weight'
250 float /weight
251 // and a string value 'name'
252 string /name
253 }
254
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
255 #### Reading
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
256
257 The primitive values can be read with `/db_name/field_name` notation
258
259 function string present_person() {
260 "Hey, my name is {/person/name}, I'm {/person/age} years old and I weight {/person/weight} kg."
261 }
262
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
263 #### Modifying
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
264
265 You can simply set a value:
266
267 /person/age <- 37
268 /person/weight <- 76.5
269 /person/name <- "John Doe"
270
271 You can also increment or decrement integer values.
272
273 /person/age++
274 /person/age -= 20
275
276 ### Records
277
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
278 #### Declaring
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
279
280 Database declaration can also include records
281
282 type person = { int age, string name }
283
284 database people {
285 person /me
286 }
287
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
288 #### Reading
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
289
290 We can read the whole record
291
292 person myself = /people/me
293
294 or just a chosen field
295
296 int my_age = /people/me/age
297
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
298 #### Modifying
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
299
300 Similarly we can update the whole record
301
302 /people/me <- { age: 27, name: "Unknown" }
303
304 or just some of its fields:
305
306 /people/me/name <- "John Doe"
307 /people/me/age++
308
309 ### Lists
310
311 Lists are in fact just records, but there are few special syntactical goodies for operating on them:
312
313 database cities {
314 list(string) /capitals
315 }
316
317 Overwrite an entire list
318
319 /cities/capitals <- ["Amsterdam", "New York City", "Paris"]
320
321 Remove first and last element of a list
322
323 // first one
324 string city1 = /cities/capitals pop // city1 == "Amsterdam"
325 // last one
326 string city2 = /cities/capitals shift // city2 == "Paris"
327
328 Adding elements:
329
330 // Append one element
331 /cities/capitals <+ "Tokyo"
332 // Append several elements
333 /cities/capitals <++ ["Mumbai", "Delhi", "Shanghai"]
334
335 After all those operations we have:
336
337 /cities/capitals == ["New York City", "Tokyo", "Mumbai", "Delhi", "Shanghai"]
338
339 ### Sets and Maps
340
341 Sets and maps are very powerful concepts allowing to better organize and query data.
342
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
343 #### Declaring
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
344
345 Let us begin with declaring a *set* of persons
346
347 type user_status = {regular} or {premium} or {admin}
348 type user = { int id, string name, int age, user_status status }
349
350 database users {
351 user /all[{id}]
352
353 // the status field is user-defined so we need to specify the default value
354 /all[_]/status = { regular }
355 // or to indicate that we will only manipulate full-records
356 // /all[_] full
357 }
358
359 The `[{id}]` after the path `/all` indicates that we are declaring a *set* and not a single `user` value and the `{id}` value indicates that `id` field will be the *primary key*.
360
361 To illustrate maps we will just use a simple abstract example with a map from `int`s to `string`s.
362
363 database map {
364 intmap(string) /m
365 }
366
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
367 #### Querying
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
368
369 We can fetch a single value from a set with a given key:
370
371 key = {id: 123}
372 user user1 = /users/all[key]
373
374 {block}[WARNING]
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
375
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
376 Note that in Opa 0.9.0 abbreviating the above with
377
378 user user1 = /users/all[{id: 123}]
379
380 is not possible. This will be fixed in the subsequent version.
381 {block}
382
383 Similarly for maps:
384
385 string v = /map/m[123]
386
387 For an overview of querying syntax and options we refer to the [relevant chapter](/manual/Hello--database/Sets-and-Maps) in the manual. Here we will just provide some examples.
388
389 Examples for sets:
390
391 // TODO First example should just return a single value
392
393 user /users/all[id == 123] // accessing single entry by its primary key
394 dbset(user, _) john_does = /users/all[name == "John Doe"] // return a set of values
395 dbset(user, _) underages = /users/all[age < 18]
396 dbset(user, _) non_admins = /users/all[status in [{regular}, {premium}]]
397 dbset(user, _) /users/all[age >= 18 and status == {admin}]
398 dbset(user, _) /users/all[not status == {admin}]
399 // showing second 50 results for users that are below 18 or above 62,
400 // sorted by age (ascending) and then id (descending)
401 dbset(user, _) users1 = /users/all[age <= 18 or age >= 62; skip 50; limit 50; order +age, -id]
402
403 Examples for maps:
404
405 string /map/m[123] // unique map association
406 intmap(string) /map/m[< 123 and > 456] // a sub-map for keys below 123 and above 456
407
408 // TODO: Add updating; one example doesn't work for now...
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
409 //#### Updating
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
410
411 //Complete, single-value update:
412
413 // /users/all[id == 123] <- {name: "John Doe", age: 32, status: {regular}}
414
415 //Partial, many-values update:
416
417 // /users/all[age < 32] <- {age++}
418
419 Structuring programs
420 --------------------
421
422 ### Packages
423
424 // declaring file's package
425 package mlstate.tutorials.refcard
426
427 // importing other packages
428 import stdlib.web.mail
429 // more than one package at once
430 import stdlib.widgets.{button, dateprinter}
431 // all sub-packages
432 import stdlib.apis.facebook.*
433
434 ### Modules
435
436 // declaring a module
437 module ModuleA {
438 function fooh() {
439 ...
440 }
441 }
442
443 // calling functions from another module
444 module ModuleB {
445 function bar() {
446 ModuleA.fooh();
447 ...
448 }
449 }
450
451 // nested modules
452 module OuterModule {
453 private module InnerModule {
454 ...
455 }
456 }
457
458 //[TODO]: Add functors...
459
460 Debugging Opa
461 -------------
462
463 [Log](/module/stdlib.core/Log) messages
464
465 // Add logs with Log.debug/info/notice/warning/error/fatal
466 Log.info("event_type", "debug msg, x={x}, v={v}")
467 /* note that the log will either appear in the browser (use Development Console to see it)
468 * or in the terminal where you executed your server, depending on where the code with
469 * the debug command is executed
470 */
471
472 The compile cycle is rather long and you don't want to use it to tweak with resources (CSS) etc. Instead you can:
473
474 * compile your app in development mode (without `--compile-release` switch);
475 * run it with the `-d` switch (or `--debug-editable-css` or similar);
476 * `opa-debug` directory will be created with app resources;
477 * edit them and see the changes in your app immediately;
478 * *Remember*: when you're finished you still need to update app resources in their respective directory! (so that changes are kept when you recompile then app)
479
480 Standard library
481 ================
482
483 //General structure
484 //~~~~~~~~~~~~~~~~~
485
486 //* +stdlib.core+: core packages.
487 //* +stdlib.widgets+: web widgets (stateless)
488 //* +stdlib.components+: web components (_i.e._ stateful widgets)
489 //* +stdlib.api+: APIs to external services, (_ex._ Facebook, Twitter, ...)
490
491 //Important packages
492 //------------------
493
494 // parser?
495
496 //* <<datatypes,*General data-types*>>: <<bool,bool>>, <<float,float>> <<int,int>>, <<string,string>>, <<date,date>>, <<option,option>>.
497 //* <<containers,*Containers*>>: <<list,list>>, <<map,map>>, <<set,set>>.
498 //* <<webfeatures,*Web features*>>: <<Server,Server>>, <<xhtml,XHTML>>, <<css,CSS>>, <<dom,DOM>>, <<uri,URLs>>, <<resource,Resource>>, http://ap.opalang.org/module/stdlib.core.color/Color[color], /package/stdlib.web.canvas[canvas], /package/stdlib.web.mail[mail]
499 //* <<other,*Other*>>: <<markdown,Markdown>>, <<parsing,Parsing>>
500 //* <<external_apis, *External APIs*>>: /package/stdlib.apis.couchdb[CouchDB], /package/stdlib.apis.facebook[Facebook], /package/stdlib.apis.github[GitHub], /package/stdlib.apis.gmaps[Google Maps], /package/stdlib.apis.irc[IRC], /package/stdlib.apis.mongo[MongoDB], /package/stdlib.apis.oauth[OAuth], /package/stdlib.apis.rdf[RDF], /package/stdlib.apis.recaptcha[ReCaptcha], /package/stdlib.apis.twitter[Twitter], /package/stdlib.apis.worldweather[World Weather Online]
501
502 General data types
503 ------------------
504
505 ### bool
506
507 // type definition
508 type bool = {false} or {true}
509
510 // conditionals
511 if (b) { ... } else { ... }
512 // pattern matching
513 match (b) {
514 case {true}: ...
515 case {false}: ...
516 }
517
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
518 [#See the full API#](/module/stdlib.core/Bool)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
519
520 ### float
521
522 // literal -- the decimal dot makes it a float, not an int
523 float f = 10.
524 // operations
525 distance = Math.sqrt_f(dx*dx + dy*dy)
526 // conversion to int
527 int x = Float.to_int(f)
528 // conversion from int
529 float f = Float.of_int(17)
530 // conversion to string
531 string s = Float.to_string(3.14159)
532 // or simply with inserts
533 string s = "Value of f is: {f}"
534 // conversion from string
535 option(float) f = Parser.try_parse(Rule.float, "3.14159")
536
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
537 [#See the full API#](/module/stdlib.core/Float)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
538
539 ### int
540
541 // literal
542 int i = 10
543 // conversion to float
544 float f = Int.to_float(i)
545 // conversion from float
546 int i = Int.of_float(3.14159)
547 // conversion to string
548 string s = Int.to_string(42)
549 // or simply with inserts
550 string s = "Value of i is: {i}"
551 // conversion from a string
552 option(int) i = Parser.try_parse(Rule.integer, "42")
553
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
554 [#See the full API#](/module/stdlib.core/Int)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
555
556 ### string
557
558 // literal
559 string s = "This is a string"
560 // concatenation
561 s = s1 ^ s2
562 // or with inserts
563 s = "Hey, {name}, nice to meet you!"
564 // length
565 String.length("Hello") == 5
566 // n'th character
567 String.get(1, "Hello") == "e"
568 // dividing at a separator
569 String.explode(",", "1,2,3") == ["1", "2", "3"]
570 // flattening a list of string
571 String.flatten(["1", "2", "3"]) == "123"
572
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
573 See also: [String.capitalize](/value/stdlib.core/String/capitalize), [String.get_prefix](/value/stdlib.core/String/get_prefix), [String.get_suffix](/value/stdlib.core/String/get_suffix), [String.has_prefix](/value/stdlib.core/String/has_prefix), [String.has_suffix](/value/stdlib.core/String/has_suffix), [String.init](/value/stdlib.core/String/init), [String.lowercase](/value/stdlib.core/String/lowercase), [String.print_list](/value/stdlib.core/String/print_list), [String.replace](/value/stdlib.core/String/replace), [String.reverse](/value/stdlib.core/String/reverse), [String.substring](/value/stdlib.core/String/substring), [String.trim](/value/stdlib.core/String/trim), [String.uppercase](/value/stdlib.core/String/uppercase)
574
575 [#See the full API#](/module/stdlib.core/String)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
576
577 //### date
578 //[TODO]
579
580 ### option
581
582 Optional value of any type -- a type-safe approach to null-values.
583
584 // type definition
585 type option('a) = {'a some} or {none}
586 // construction
587 opt1 = none
588 option(string) opt2 = some("Hello")
589 // inspecting values (pattern matching)
590 match (opt) {
591 case {none}: ...
592 case {some: value}: ...
593 }
594 // default value; opt of type option(string)
595 string s = opt ? "default"
596
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
597 See also: [Option.map](/value/stdlib.core/Option/map), [Option.switch](/value/stdlib.core/Option/switch)
598
599 [#See the full API#](/module/stdlib.core/Option)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
600
601 Containers
602 ----------
603
604 ### list
605
606 Lists in Opa are homogeneous, i.e. all elements must have the same type. It's the simplest container and you will use lists _a lot_.
607
608 // definition
609 type list('a) = {nil} or {'a hd, list('a) tl}
610
611 // construction
612 list(int) few_primes = [2, 3, 5, 7]
613 // concatenation
614 l12 = l1 ++ l2
615 // adding element 'elt' at the beginning of list 'l'
616 {hd: elt, tl: l}
617 [elt | l] // equivalent
618 List.cons(elt, l) // also equivalent
619 // list length
620 List.length([2, 4]) == 2
621
622 // pattern matching
623 match (l) {
624 case []: ... // list empty
625 case [hd | tl]: ... // first element 'hd' followed by list 'tl'
626 }
627
628 // modifying all elements (increasing by 1)
629 List.map(function(elt) { elt + 1 }, [2, 4]) == [3, 5]
630 // aggregating elements (multiplying all elements)
631 List.fold_left(function(acc, elt) { acc*elt }, 1, [2, 4]) == 8
632 // sorting a list
633 List.sort([4, 5, 2]) == [2, 4, 5]
634 // calling a function for every element of the list
635 List.iter(function(elt) { Log.info("ELT", "{elt}") }, [2, 4])
636 // check if element belongs to the list
637 List.mem(3, [6, 3]) == true
638 // converting to string
639 List.to_string([1, 3, 5]) = "[1, 3, 5]"
640
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
641 See also: [List.assoc](/value/stdlib.core/List/assoc), [List.exists](/value/stdlib.core/List/exists), [List.filter](/value/stdlib.core/List/filter), [List.find](/value/stdlib.core/List/find), [List.flatten](/value/stdlib.core/List/flatten), [List.get](/value/stdlib.core/List/get), [List.init](/value/stdlib.core/List/init), [/value/stdlib.core/List/nth](List.nth), [List.remove](/value/stdlib.core/List/remove), [List.rev](/value/stdlib.core/List/rev).
642
643 [#See the full API#](/module/stdlib.core/List)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
644
645 ### map
646
647 Maps (dictionaries, hashmaps) are *immutable* structures mapping keys to values. They are comparable to hash-tables in other languages.
648
649 // types
650 type map('key, 'val) // map from 'key's to 'val'ues with default ordering
651 type stringmap('t) // map from strings to type 't
652 type intmap('t) // map from ints to type 't
653
654 // construction
655 stringmap(int) map = Map.singleton("ten", 10) // a map from strings to ints
656 intmap({string name, int age}) s = Map.empty // a map from ints to records
657 // conversion from list
658 stringmap(int) map = Map.From.assoc_list([("one", 1), ("six", 6)])
659 // conversion to list
660 Map.To.assoc_list(map) == [("one", 1), ("six", 6)]
661
662 // extending maps
663 new_map = Map.add("six", 6, map)
664 // checking if an element belongs to a map
665 if (Map.mem("seven", map)) { ... } else { ... }
666 // getting an element from a map
667 option(int) v = Map.get("seven", map)
668
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
669 Iterators: `fold`, `map`, `iter`, `filter` -- similar to [lists](/refcard/Standard-library/Containers/list).
670
671 [#See the full API#](/package/stdlib.core.map)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
672
673 //[TODO] add See also
674
675 ### set
676
677 Sets are containers holding and allowing to manipulate a number of elements of the same type.
678
679 // types
680 type set('elem) // set with elements of type 'elem
681 type intset // set of integers
682 type stringset // set of strings
683
684 // construction
685 stringset names = Set.singleton("John Smith")
686 // from list
687 Set.From.list([1, 4, 7])
688 // to list
689 Set.To.list(names) == ["John Smith"]
690
691 // extending sets
692 Set.add("Joe", names)
0ba70d7 @akoprow [fix] doc/refcard: typo
akoprow authored
693 // checking if an element belongs to a set
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
694 if (Set.mem("Dave", set)) { ... } else { ... }
695 // getting an element from a set
696 option(int) v = Set.get("Alice")
697
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
698 Iterators: `fold`, `map`, `iter` -- similar to [lists](/refcard/Standard-library/Containers/list) and [maps](/refcard/Standard-library/Containers/map)
699
700 [#See the full API#](/package/stdlib.core.set)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
701 //[TODO] add See also
702
703 Web features
704 ------------
705
706 ### Server
707
708 This module allows one to declare Servers, i.e. entry-points of Opa programs. One declares a server with `Server.start` that gets two parameters: configuration and a handler defining how to map URIs to resources.
709
710 // Start a server defined by 'handler' with configuration 'conf'
711 Server.start(Server.conf conf, Server.handler handler)
712
713 /* Configurations (1st argument of Server.start) */
714 Server.http // default HTTP config (on port 8080)
715 Server.https // default HTTPS config (on port 8080)
5b714e8 @Aqua-Ye [doc] refcard: typo
Aqua-Ye authored
716 {port: 80, netmask:0.0.0.0, encryption: {no_encryption}, name:"my server"} // custom server
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
717
718 /* Handlers (2nd argument of Server.start) */
719 function mypage() {
720 <>Hello web!</>
721 }
722 // single page server (URI ignored, always the same page)
723 { page: mypage
724 , title: "My app"}
725
726 // multi-page server, function from URI (string) to a resource
727 dispatcher = parser
728 | "/" -> Resource.page("Hello", <>Hello web</>)
729 | "/_rest_/" .* -> Resource.page(...)
730 | .* -> Resource.page(...)
731 { custom: dispatcher }
732
733 // multi-page server, function from URI (structured) to a resource
734 // + possibility to add a filter to decide which URIs to handle
735 function start(url) {
736 match (url) {
737 case {path:[] ... }: ...
738 case {~path ...}: ...
739 }
740 }
741 { dispatch: start }
742
743 // simple server for *serving* a bundle of resources
744 { resources: @static_resource_directory("resources") }
745
746 // no request handling but registering a list of custom resources (JS/CSS)
67b9b60 @Aqua-Ye [doc] manual: fix register syntax
Aqua-Ye authored
747 { register: {css: ["resources/css/style.css", "resources/js/myjs.js"]} }
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
748
749 // One can also use a list of servers.
750 // For instance bundle + custom resources + dispatcher).
751 // Helpful for building servers in a structured way
752 // Servers are tried in the given order and the first successful will serve the request
753 Server.start(
754 Server.http,
755 [ {resources: @static_resource_directory("resources")} // serve custom resources
67b9b60 @Aqua-Ye [doc] manual: fix register syntax
Aqua-Ye authored
756 , {register: {css: ["resources/css.css"]}} // use custom CSS
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
757 , {title: "Chat", page:start } // serve the one-page app!
758 ]
759 )
760
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
761 [#See the full API#](/module/stdlib.core.web.server/Server)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
762
763 ### XHTML
764
765 In Opa XHTML is a data-type, with special syntax support.
766
767 See [syntax introduction](/refcard/The-language/Expressions/XHTML) for more info.
768
769 page = <span class="hello">Hello web</span>
770
771 // name in the closing tag is optional
772 // so are the quotes for attributes
773 page = <span class=hello>Hello web</> // equivalent
774
775 // you can pass XHTML as arguments to functions
776 // and use it with inserts
777 function block(title, content) {
778 <div class=block>
779 <span class="{class}">
780 </span>
781 }
782
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
783 [#See the full API#](/module/stdlib.core.xhtml/Xhtml)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
784
785 ### CSS
786
787 // just like XHTML, CSS is a data-type in Opa
788 red_style = css { color: red }
789 span = <span style={red_style} />
790
791 // one can use inserts inside css
792 function div(width, height, content) {
793 <div style={ css { height: {height}px; width: {width}px }}>
794 {content}
795 </>
796 }
797
798 // a top-level css section defines application-wide css
799 css = css
800 .body {
801 background: red
802 }
803
804 // one can also register external css (from a separate project file)
805 Server.start(Server.http,
67b9b60 @Aqua-Ye [doc] manual: fix register syntax
Aqua-Ye authored
806 [ {register: {css: ["resources/css/style.css"]}}
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
807 , ...
808 ])
809
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
810 It's very easy to use [Bootstrap](http://twitter.github.com/bootstrap) in Opa. Check [this page](http://bootstrap.opalang.org) for more info.
811
812 See [syntax introduction](/refcard/The-language/Expressions/XHTML) for more info.
813
814 [#See the full API#](/module/stdlib.core.xhtml/Css)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
815
816 ### DOM
817
818 See [syntax introduction](/refcard/The-language/Expressions/XHTML) for some introduction to DOM manipulation.
819
820 // get a fresh ID
821 Dom.fresh_id()
822
823 // DOM selections
824 #test // element with ID "test"
825 #{test} // element with ID equal to (string) variable 'test'
826 Dom.select_all() // complete document
827 Dom.select_class(class) // all elements with class 'class'
828 // and much more...
829
830 // DOM effects
831 Dom.transition(#some_id, Dom.Effect.fade_out())
832 Dom.transition(dom_selection, Dom.Effect.slide_in())
833
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
834 For more effects and ways of applying them see the: /module/stdlib.core.xhtml/Dom/Effect[Dom.Effect] module.
835
836 [#See the full API#](/module/stdlib.core.xhtml/Dom)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
837
838 ### URLs
839
840 // URI definition:
841 type Uri.uri = Uri.absolute or Uri.relative or Uri.mailto
842 // where Uri.relative is:
843 type Uri.relative =
844 { list(string) path
845 , option(string) fragment
846 , list((string, string)) query
847 , bool is_directory
848 , bool is_from_root
849 }
850
851 // When constructing a server you can dispatch pages by their relative URIs:
852 function dispatch(url) {
853 match (url) {
854 case {path:[] ... }: ...
855 case {path:["_rest_" | _] ...}: ...
856 default: ...
857 }
858 }
859 Server.start(Server.http, { dispatch: start })
860
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
861 [#See the full API#](/module/stdlib.core.web.core/Uri)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
862
863 ### Resource
864
865 Resources are objects that can be served by the server to the clients, such as web pages, images, scripts, stylesheets etc.
866
867 // Constructing resources
868 Resource.page("Page title", <span>Page body</>) // HTML page
869 Resource.styled_page(title,
870 ["resources/style.css"], body) // HTML page + custom CSS
871 Resource.image({png:
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
872 @static_source_content("./resources/index.jpg")}) // image
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
873 Resource.raw_status({wrong_address}) // HTTP response code
874
875 // Registering custom CSS resource (app-wide)
876 Resource.register_external_css(url)
877 // Registering custom JS resource (app-wide)
878 Resource.register_external_js(string url)
879
880 // You will provide Resources in the server in response to URLs
881 function start(url) {
882 match (url) {
883 case {path:[] ... }: Resource.page("Home", home())
884 case {~path ...}: Resource.page("Some page", gen_page(path))
885 }
886 }
887 Server.start(Server.http, {dispatch: start})
888
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
889 [#See the full API#](/module/stdlib.core.web.resource/Resource)
c878465 @Aqua-Ye [doc] opadoc: open sourcing opadoc resources
Aqua-Ye authored
890
891 //Other
892 //-----
893 //### Markdown
894 //[TODO]
895 //### Parsing
896 //[TODO]
897
898 External APIs
899 -------------
fef70fb [doc] opadoc: improving refcard layout
Ida Swarczewskaja authored
900 ![^MongoDB (stdlib.apis.mongo)^]{/package/stdlib.apis.mongo}(/resources/img/api-mongodb.jpg)
901 ![^CouchDB (stdlib.apis.couchdb)^]{/package/stdlib.apis.couchdb}(/resources/img/api-couchdb.jpg)
902 ![^Dropbox (stdlib.apis.dropbox)^]{/package/stdlib.apis.dropbox}(/resources/img/api-dropbox.jpg)
903 ![^Facebook (stdlib.apis.facebook)^]{/package/stdlib.apis.facebook}(/resources/img/api-facebook.jpg)
904 ![^GitHub (stdlib.apis.github)^]{/package/stdlib.apis.github}(/resources/img/api-github.jpg)
905 ![^Twitter (stdlib.apis.twitter)^]{/package/stdlib.apis.twitter}(/resources/img/api-twitter.jpg)
906 ![^Google Maps (stdlib.apis.gmaps)^]{/package/stdlib.apis.gmaps}(/resources/img/api-google-maps.jpg)
907 ![^IRC (stdlib.apis.irc)^]{/package/stdlib.apis.irc}(/resources/img/api-irc.jpg)
908 ![^OAuth (stdlib.apis.oauth)^]{/package/stdlib.apis.oauth}(/resources/img/api-oauth.jpg)
909 ![^RDF (stdlib.apis.rdf)^]{/package/stdlib.apis.rdf}(/resources/img/api-rdf.jpg)
910 ![^ReCaptcha (stdlib.apis.recaptcha)^]{/package/stdlib.apis.recaptcha}(/resources/img/api-recaptcha.jpg)
911 ![^World Weather Online (stdlib.apis.worldweather)^]{/package/stdlib.apis.worldweather}(/resources/img/api-worldweatheronline.jpg)
Something went wrong with that request. Please try again.