This page collects (in an unorganized manner) a number of mantra examples. See Examples tar
for more.
The obligatory "hello world":
println("hello, world!");
Iterate over and print the characters of a string:
"abc":{char c|println(c);};
Define a dict and look up a value:
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:
1..10:{int x|println(x);}; list a = ["a", "b", "c", "d", "e"];
a[1..3]:println;
list select=[1,4];
a[select]:println;
emits:
1
2
3
4
5
6
7
8
9
10
b
c
d
b
e
List filtering:
list a = ["Tom", "Ter", "Tim"];
a:{string n where n!="Ter" | return n;}:println;
List comprehension that does same thing:
list a = ["Tom", "Ter", "Tim"];
list b = a:{string n where n!="Ter" | return n;};
b:println;
Define a field:
and some overloaded methods
class J {
int foo() { return 34; }
foo(int a) { ; } 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):
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.
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(); }
}
}
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:
File("coffee") => Lines() => {string line | return line.split();};
Given file:
the code emits:
[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:
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:
list a = [];
File("coffee") => lines() => {string line | return line.split();} => a;
println(a);
emits:
[[3, parrt], [2, jcoker], [8, tombu]]
A simple grep actor:
/** 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:
File("coffee")
=> Lines()
=> {string line | return line.split();}
=> grep(".*parrt.*")
=> {list r | return r[0];} => println;
emits 3.
Some rudimentary OS support. Default stream is stdout from OS.system():
mustring s = mustring("");
OS.system("pwd") => s; println(s);
Process p = OS.system("ps"); println(p.getStdout());
println(p.getStderr());
Document word frequency 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(); 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:
dict wfreq = dict();
for (string filename in args) {
File f = File(filename);
list a = [];
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(); 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:
string trim() {
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:
import java javax.swing.JFrame;
JFrame f = JFrame();
f.pack();
f.setVisible(true);
or
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:
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:
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);