This page collects (in an unorganized manner) a number of mantra examples. See Examples tar for more.
The obligatory "hello world":
| Code Block |
|---|
println("hello, world!");
|
Iterate over and print the characters of a string:
| Code Block |
|---|
"abc":{char c|println(c);};
|
Define a dict and look up a value:
| Code Block |
|---|
dict phones = ["Ter"="x5707"]; println(phones["Ter"]); |
You can iterate over ranges of a list or a subset of indexes without making a list copy:
| Code Block |
|---|
1..10:{int x|println(x);}; // or 1..10:println;
list a = ["a", "b", "c", "d", "e"];
a[1..3]:println;
list select=[1,4];
a[select]:println;
|
emits:
| Code Block |
|---|
1 2 3 4 5 6 7 8 9 10 b c d b e |
List filtering:
| Code Block |
|---|
list a = ["Tom", "Ter", "Tim"];
a:{string n where n!="Ter" | return n;}:println;
|
List comprehension that does same thing:
| Code Block |
|---|
list a = ["Tom", "Ter", "Tim"];
list b = a:{string n where n!="Ter" | return n;};
b:println;
|
Define a field:
| Code Block |
|---|
class I {
int a = 0;
}
|
and some overloaded methods
| Code Block |
|---|
class J {
int foo() { return 34; }
foo(int a) { ; } // no return type implies void
foo(int a, char b) { ; }
}
|
Static methods and fields and constants (U.x, U.HEIGHT, and U.bar() are all statically resolvable--useful and efficient):
| Code Block |
|---|
class U {
static int x = 3;
int y = 0;
const int HEIGHT = 100;
foo() { y = -1; }
static bar() { bar(4); }
static bar(int a) { x = a; }
}
|
Here's an actor that reads from stdin and writes lines (minus \n) to stdout.
| Code Block |
|---|
package mantra::io;
class Lines implements Actor {
main() {
char c = read();
while ( c isnt EOF ) {
string s = mustring("");
while ( c != '\n' && c isnt EOF ) {
s += c;
c = read();
}
write(s);
c = read(); // read next char after \n
}
}
}
|
Then you can launch an instance of Lines as an actor (in a separate thread) and pipe to another actor implicitly created from a closure. The input to the actor gets passed as the parameter and the output is the return value:
| Code Block |
|---|
File("coffee") => Lines() => {string line | return line.split();};
|
Given file:
| Code Block |
|---|
3 parrt 2 jcoker 8 tombu |
the code emits:
| Code Block |
|---|
[3, parrt][2, jcoker][8, tombu] |
because all actors read from in and write to out, whatever they are set to. They start as stdin and stdout, but the pipeline overrides them temporarily. The last actor still has out==stdout.
The Actor entity is a "mixin" that acts like an abstract base class:
| Code Block |
|---|
mixin Actor {
InputStream input = stdin;
OutputStream output = stdout;
object read() { return input.read(); }
write(object o) { output.write(o); }
/** To launch this object as an actor, create a thread and call this
* method. By default, objects are not actors since this method does
* nothing. It's like the main method for a shell program. When
* main() returns, actor deactives again.
*/
main() {;}
}
|
You can also redirect the stream to a list:
| Code Block |
|---|
list a = [];
File("coffee") => lines() => {string line | return line.split();} => a;
println(a);
|
emits:
| Code Block |
|---|
[[3, parrt], [2, jcoker], [8, tombu]] |
A simple grep actor:
| Code Block |
|---|
/** Read object stream, convert to string, grep, pass along those objects */
class grep implements Actor {
string regex = "";
grep(string regex) { this.regex = regex; }
main() {
object o = read();
while ( o isnt EOF ) {
string s = o.toString();
if ( s.matches(regex) ) {
write(o);
}
o = read();
}
}
}
|
Sample usage: find parrt's consumption and split before grep showing it's still an object after passing through grep:
| Code Block |
|---|
File("coffee")
=> Lines()
=> {string line | return line.split();}
=> grep(".*parrt.*")
=> {list r | return r[0];} // get first column
=> println;
|
emits 3.
Some rudimentary OS support. Default stream is stdout from OS.system():
| Code Block |
|---|
mustring s = mustring("");
OS.system("pwd") => s; // store stdout into s
println(s);
Process p = OS.system("ps"); // system blocks until process terminates
println(p.getStdout());
println(p.getStderr());
|
Document word frequency histogram:
| Code Block |
|---|
// for each filename, generate a histogram
dict wfreq = dict();
for (string filename in args) {
File f = File(filename);
f => Words() => { string w |
mutint c=wfreq[w];
if ( c is null ) wfreq[w]=mutint(1);
else c++;
};
}
list pairs = wfreq.items(); // return list of 2-tuples (key/value pairs)
pairs.sort({int x, int y | return x[1].compareTo(y[1]);});
pairs.backwards():{list p | print(p[1]); print(" "); println(p[0]);};
|
An alternative way:
| Code Block |
|---|
dict wfreq = dict();
for (string filename in args) {
File f = File(filename);
list a = [];
// f.lines() is not as interesting as f => lines because lines works
// with anything that emits text. f.lines() requires f to have a
// lines method. Better component-based programming.
f.lines() => a;
for (string line in a) {
for (string w in line.split()) {
mutint c=wfreq[w];
if ( c is null ) wfreq[w]=mutint(1);
else c++;
}
}
}
list pairs = wfreq.items(); // return list of 2-tuples (key/value pairs)
pairs.sort({int x, int y | return x[1].compareTo(y[1]);});
pairs.backwards():{list p | print(p[1]); print(" "); println(p[0]);};
|
Closures are amazing. Here is the string.trim() method:
| Code Block |
|---|
string trim() {
// find first non whitespace from left edge
func findFirstNonWhiteSpace =
{char c where !(c==' '||c=='\n'||c=='\t'||c=='\r') | break i;};
list r = this:findFirstNonWhiteSpace;
int left = r[0];
r = this.reverse():findFirstNonWhiteSpace;
int right = size()-r[0]-1;
return this[left..right].toString();
}
|
The same closure is used to get the index of first non whitespace moving from left to right and right to left. awesome. The closure precondition only executes "break i" when it sees a non whitespace char. The i variable is the implicitly-defined loop variable.
Accessing POJOs
It's easy to access any plain old Java object (POJO) using mantra. Just import the class using import java xxx; and then refer to it like any mantra class:
| Code Block |
|---|
import java javax.swing.JFrame; JFrame f = JFrame(); f.pack(); f.setVisible(true); |
or
| Code Block |
|---|
import java java.util.Vector;
Vector v = Vector();
v.add("hi");
v.add(34);
println(v.toString());
println(v.get(0));
println(v.get(1));
|
Here is a POJO:
| Code Block |
|---|
import java.util.*;
/** testing the integration with Java; here is a class
* with fields and overloaded methods.
*/
public class POJO {
public boolean b;
public int i = 3;
public String name = "Ter";
public List names = new ArrayList() {{add("Frank"); add("Mary");}};
public POJO() { ; }
public POJO(int i) { this.i = i; }
public POJO(String s) { this.name = s; }
public void foo() { i=99; }
public void foo(int i) { this.i = i; }
public void foo(boolean b) { this.b = b; }
public void foo(String s) { this.name = s; }
public String toString() {
return "[b="+b+", i="+i+", name="+name+", names="+names.toString()+"]";
}
}
|
To access all of this, check out the following capabilities:
| Code Block |
|---|
import java POJO;
POJO p = POJO();
println(p);
p.foo();
println(p);
p.foo(1111);
println(p);
p.foo(true);
println(p);
p.foo("George");
println(p);
POJO p2 = POJO("Jim");
println(p2);
p.i = 18;
println(p.i);
println(p2);
p.names.add("Jimi");
println(p.names);
|