Upload
aturleyslides
View
299
Download
0
Embed Size (px)
Citation preview
What Is Pony?“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high performance programming language.” -- ponylang.org
What Is Pony?“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high performance programming language.” -- ponylang.org
BSD licenseCopyright (c) 2014-2015, Causality Ltd.All rights reserved.
Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
What Is Pony?“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high performance programming language.” -- ponylang.org
Classes, Interfaces, Traits(but they may work a little differently than you expect)
What Is Pony?“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high performance programming language.” -- ponylang.org
Actors communicate by passing messages to other
actors
What Is Pony?“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high performance programming language.” -- ponylang.org
The compiler enforces what you can and cannot do with
an object
What Is Pony?“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high performance programming language.” -- ponylang.org
Uses LLVM to compile to native code
What Is Pony?“Pony is an open-source, object-oriented, actor-model, capabilities-secure, high performance programming language.” -- ponylang.org
Also:
● powerful type system (unions, intersections, parameterized types and functions)
● fast actor-based garbage collection system
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
traits: nominal subtyping
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
interfaces: structural subtyping
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
primitive: object with no data and only one instance
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
more-interesting.ponytrait Shape fun area(): F64
interface Named fun name(): String
class Circle is Shape let _radius: F64 new create(radius: F64) => _radius = radius fun name(): String => "circle" fun area(): F64 => 3.14159 * _radius * _radius
class Square is Shape let _side: F64 new create(side: F64) => _side = side fun name(): String => "square" fun area(): F64 => _side * _side
primitive AreaReporter fun report(shape: (Shape & Named)): String => "The area of this " + shape.name() + " is " + shape.area().string()
actor Main new create(env: Env) => let s: F64 = 15.3 var area = AreaReporter.report(Circle(s)) env.out.print(area) area = AreaReporter.report(Square(s)) env.out.print(area)
> ./ponyc src/more-interesting> ./more-interestingThe area of this circle is 735.415The area of this square is 234.09>
Pony: The Really Interesting PartsPony uses actors and reference capabilities to allow the compiler to guarantee that a program is data-race-free.
Pony: The Really Interesting PartsPony uses actors and reference capabilities to allow the compiler to guarantee that a program is data-race-free.
Pony: The Really Interesting PartsPony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting PartsPony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting PartsPony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting PartsPony uses actors and reference capabilities to allow the compiler to guarantee
that a program is data-race-free.
Pony: The Really Interesting PartsPony uses actors and reference capabilities to allow the compiler to guarantee that a program is
data-race-free.
Off To The Data Races!Some pseudo code (not Pony) …
global int a = 0
function inc() { for x in range(0, 1000001) { a = a + 1 }}
function main() { inc() print(“a = “ + a)}
1000000
Off To The Data Races!Some more pseudo code (not Pony) …
global int a = 0
function inc() { for x in range(0, 1000001) { a = a + 1 }}
function main() { thread thread1 = Thread(inc) thread thread2 = Thread(inc) thread1.run() thread2.run() thread1.join() thread2.join() print(“a = “ + a)}
● Run “inc()” simultaneously in two places
● wait for both runs to finish● print the value of “a”
Off To The Data Races!Some more pseudo code (not Pony) …
global int a = 0
function inc() { for x in range(0, 1000001) { a = a + 1 }}
function main() { thread thread1 = Thread(inc) thread thread2 = Thread(inc) thread1.run() thread2.run() thread1.join() thread2.join() print(“a = “ + a)}
Expected (two threads each
incrementing a variable
1000000 times):
2000000
Off To The Data Races!Some more pseudo code (not Pony) …
global int a = 0
function inc() { for x in range(0, 1000001) { a = a + 1 }}
function main() { thread thread1 = Thread(inc) thread thread2 = Thread(inc) thread1.run() thread2.run() thread1.join() thread2.join() print(“a = “ + a)}
Expected:
2000000
Actual Run 1:
1987735
Actual Run 2:
1935010
Actual Run 3:
1941217
Off To The Data Races!Some more pseudo code (not Pony) …
global int a = 0
function inc() { for x in range(0, 1000001) { a = a + 1 }}
function main() { thread thread1 = Thread(inc) thread thread2 = Thread(inc) thread1.run() thread2.run() thread1.join() thread2.join() print(“a = “ + a)}
Expected:
2000000
Actual Run 1:
1987735
Actual Run 2:
1935010
Actual Run 3:
1941217
WHY?
Off To The Data Races!In thread1 …
// get the value of “a”// add 1 to that value// write the new value back to “a”a = a + 1
Meanwhile, in thread2...
// get the value of “a”// add 1 to that value// write the new value back to “a”a = a + 1
a = 26
Off To The Data Races!In thread1 …
// get the value of “a” 26// add 1 to that value// write the new value back to “a”a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26// add 1 to that value// write the new value back to “a”a = a + 1
a = 26
Off To The Data Races!In thread1 …
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a”a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a”a = a + 1
a = 26
Off To The Data Races!In thread1 …
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
a = 27
Off To The Data Races!In thread1 …
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
a = 27
We wanted a = 28
Off To The Data Races!In thread1 …
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
a = 27
This may not happen every time, but each time it happens it increases the error of the result.
We wanted a = 28
Off To The Data Races!In thread1 …
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
Meanwhile, in thread2...
// get the value of “a” 26// add 1 to that value 26 + 1 = 27// write the new value back to “a” a = 27a = a + 1
a = 27
This may not happen every time, but each time it happens it increases the error of the result.
We wanted a = 28
“Shared mutable state is the root of all evil.” -- several different people, all at the same time
Off To The Data Races!Techniques various and sundry for avoiding data races ...
● Locks! → a unit of execution acquires a lock, no other unit of execution can acquire the lock until it is released
○ C and C++
● Synchronized blocks/functions/methods! → somebody writes the locks for you○ Java
● Everything is read-only! → don’t need to worry about writes anymore○ Erlang
● There’s only one binding to an object at any time! → move, borrow, copy○ Rust
Off To The Data Races!Techniques various and sundry for avoiding data races ...
● Locks! → a unit of execution acquires a lock, no other unit of execution can acquire the lock until it is released
○ C and C++
● Synchronized blocks/functions/methods! → somebody writes the locks for you○ Java
● Everything is read-only! → don’t need to worry about writes anymore○ Erlang
● There’s only one binding to an object at any time! → move, borrow, copy○ Rust
WELL ACTUALLY
Nope, save it until the end.
Leaving The Data RacesPony uses two rules to avoid data races:
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
THE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONE
Actorsmessage3message4
message1message2 } Queue
THE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONE
Actors
Get next message
message3message4
message1message2 } Queue
THE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONE
Actors
Get next message
Processmessage
message3message4
message1message2 } Queue
THE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONE
Actors
Get next message
Processmessage
Collect garbage
message3message4
message1message2 } Queue
THE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTORTHE LIFE OF ACTOR
THE LIFE OF ACTOR
WHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONEWHICH / ONE WHICH / ONE
Actors
Get next message
Processmessage
Collect garbage
message3message4
message1message2 } Queue
Actorsactor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
Actorsactor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
“be” means “behavior”, this is what processes a message
Actorsactor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
“fun” means “function”, these are run by the actor as part of processing the message
Actorsactor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
An actor sends a message to another actor using the “<a>.<be>(...)” syntax
Actorsactor Donald
be foo(x: Something) =>
bar(x)
fun bar(x: Something) =>
// do something …
actor Jessica
let _d: Donald = Donald
let _s: Something = Something
be baz() =>
_d.foo(_s)
When talking about Pony, “method” means either a function or a behavior.
Actors
a1.bar() a2.baz() a1.bar()
a3.dee() a4.doo() a3.doh()
a5.moo()
a8.fee() a7.foo()
a6.mee()
a7.fuz()
time
CPU1: thread1
CPU2: thread2
CPU3: thread3
CPU4: thread4
Actors run on threads (1 thread per CPU by default)
Actors
a1.bar() a2.baz()1 a1.bar()
a3.dee() a4.doo() a3.doh()
a5.moo()
a8.fee() a7.foo()
a6.mee()
a7.fuz()
time
CPU1: thread1
CPU2: thread2
CPU3: thread3
CPU4: thread4
a2.baz()2
Behaviors cannot be preempted
Actors
a1.bar() a2.baz() a1.bar()
a1.buz() a4.doo() a3.doh()
a5.moo()
a8.fee() a7.foo()
a6.mee()
a7.fuz()
time
CPU1: thread1
CPU2: thread2
CPU3: thread3
CPU4: thread4
Actors process one message at a time
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main
create(env)
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Maincreate(env)
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
create(“howdy”)
create(env)
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e
create(env)
o
create(“howdy)
create(env)
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Maincreate(env)create(“howdy)
foo(o)
e_text=”howdy”
o_env=envcreate(env)
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e_text=”howdy”
o_env=env
foo(o)1
foo(o)2
create(env)
foo(o)1
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e_text=”ydwoh”
o_env=env
foo(o)2
foo(o)1
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e_text=”ydwoh”
o_env=env
foo(o)2 say(“ydwoh”)
say(“ydwoh”)foo(o)2
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e_text=”howdy”
o_env=env
YDWOH
foo(o)2
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e_text=”howdy”
o_env=env
say(“howdy”)
YDWOH
say(“howdy”)
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e_text=”howdy”
o_env=env
YDWOHHOWDY
Actors: An Example
actor Example
var _text: String
new create(text: String) =>
_text = text
be foo(o: Other) =>
o.say(rev())
fun ref rev(): String val =>
_text = recover
_text.reverse()
end
_text
actor Other
let _env: Env
new create(env: Env) =>
_env = env
be say(s: String) =>
_env.out.print(s)
actor Main
new create(env: Env) =>
let e = Example("howdy")
let o = Other(env)
e.foo(o) // prints “ydwoh”
e.foo(o) // prints “howdy”
Main e_text=”howdy”
o_env=env
YDWOHHOWDY
Reference CapabilitiesRemember the Read Rule and the Write Rule:
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
Reference Capabilitiesclass Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference CapabilitiesSPOT THE REFERENCE CAPABILITIES!
class Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference CapabilitiesSPOT THE EXPLICIT REFERENCE CAPABILITIES!
SPOT THE IMPLIED REFERENCE CAPABILITIES!
class ref Foo
class val Bar let v: U32 val new val create(vv: U32 val) => v = vv
actor tag Main new create(env: Env val) => let a: Foo iso = recover iso Foo end var b: Bar val = Bar(1) b = Bar(2) baz(b) fun box baz(c: Bar val): U32 val => c.v + 16
Reference CapabilitiesActors have a default reference capability of tag, objects created from classes have a default reference capability of ref
You can change the implicit reference capability of a class (normally it is ref)
You can change the reference capability of the object generated by the constructor (normally it is ref)
class ref Foo
class val Bar let v: U32 val new val create(vv: U32 val) => v = vv
actor tag Main new create(env: Env val) => let a: Foo iso = recover iso Foo end var b: Bar val = Bar(1) b = Bar(2) baz(b) fun box baz(c: Bar val): U32 val => c.v + 16
Reference CapabilitiesYou can specify the type of reference capability that the receiver must have to call a function
class ref Foo
class val Bar let v: U32 val new val create(vv: U32 val) => v = vv
actor tag Main new create(env: Env val) => let a: Foo iso = recover iso Foo end var b: Bar val = Bar(1) b = Bar(2) baz(b) fun box baz(c: Bar val): U32 val => c.v + 16
Reference CapabilitiesYou can specify the type of reference capability that the receiver must have to call a function
This can get really tricky!
class ref Foo
class val Bar let v: U32 val new val create(vv: U32 val) => v = vv
actor tag Main new create(env: Env val) => let a: Foo iso = recover iso Foo end var b: Bar val = Bar(1) b = Bar(2) baz(b) fun box baz(c: Bar val): U32 val => c.v + 16
Reference CapabilitiesYou can specify the type of reference capability that the receiver must have to call a function
This can get really tricky!
class ref Foo
class val Bar let v: U32 val new val create(vv: U32 val) => v = vv
actor tag Main new create(env: Env val) => let a: Foo iso = recover iso Foo end var b: Bar val = Bar(1) b = Bar(2) baz(b) fun box baz(c: Bar val): U32 val => c.v + 16
Reference CapabilitiesAn alias is a name given to a particular object in memory
Aliases are created when
● an object is assigned to a variable● an object is passed as an argument to a
method
class Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference CapabilitiesAn alias is a name given to a particular object in memory
Aliases are created when
● an object is assigned to a variable● an object is passed as an argument to a
method
class Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference CapabilitiesAn alias is a name given to a particular object in memory
Aliases are created when
● an object is assigned to a variable● an object is passed as an argument to a
method
class Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference CapabilitiesAn alias is a name given to a particular object in memory
Aliases are created when
● an object is assigned to a variable● an object is passed as an argument to a
method
class Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference CapabilitiesAn alias is a name given to a particular object in memory
Aliases are created when
● an object is assigned to a variable● an object is passed as an argument to a
method
class Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference CapabilitiesAn object may have more than one alias, possibly in more than one actor, but the combination of aliases must not violate the read rule and write rule.
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
class Foo
class val Bar let v: U32 new val create(vv: U32) => v = vv
actor Main new create(env: Env) => let a: Foo iso = recover Foo end var b = Bar(1) b = Bar(2) baz(b) fun baz(c: Bar): U32 => c.v + 16
Reference Capabilities: A Visual Guide
objectalias can send object a message
ref cap
A visual language
Reference Capabilities: A Visual Guide
object note: any alias can send an actor a message, regardless of reference capability
ref cap
A visual language
Reference Capabilities: A Visual Guide
object another alias in the actor can read object
ref cap
A visual language
Reference Capabilities: A Visual Guide
object
another alias outside the actor can read object
ref cap
A visual language
Reference Capabilities: A Visual Guide
objectanother alias inside the actor can modify object
ref cap
A visual language
Reference Capabilities: A Visual Guide
objectanother alias outside the actor can modify object
ref cap
A visual language
Reference Capabilities: A Visual Guide
object
ref cap
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
Reference Capabilities: iso (isolated)
iso
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
object
iso reference can read and modify an object. No other reference can read or modify the object.
Reference Capabilities: trn (transitional)
trn
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
object
trn reference can read and modify an object. No other reference can modify the object, but the actor may have other references that can read the object.
Reference Capabilities: ref (reference)
ref
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
object
ref reference can read and modify an object. Other references in the object may be able to read or modify the object, but no other actor may have a reference that can read or modify it.
Reference Capabilities: val (value)
val
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
object
val reference can read an object. The actor may have other references that can read the object, and other actors may have references that can read the object, but no actor may have a reference that can modify it.
Reference Capabilities: box (box)
boxOR
box
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
objectobject
Reference Capabilities: box (box)
boxOR
box
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
objectobject
This looks like a ref This looks like a val
Reference Capabilities: box (box)
boxOR
box
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
objectobject
A box capability is used when you want to create a new read-only reference to an object that is either val or ref.
This looks like a ref This looks like a val
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ???): I32 => x.v() + 1
What should the reference capability be?
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ref): I32 => x.v() + 1
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ref): I32 => x.v() + 1
ref doesn’t work because a ref (x) can’t alias a val (b)
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ref): I32 => x.v() + 1
class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X val): I32 => x.v() + 1
ref doesn’t work because a ref (x) can’t alias a val (b)
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ref): I32 => x.v() + 1
class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X val): I32 => x.v() + 1
ref doesn’t work because a ref (x) can’t alias a val (b)
val Doesn’t work because a val (x) can’t alias a ref (a)
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ref): I32 => x.v() + 1
class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X val): I32 => x.v() + 1
ref doesn’t work because a ref (x) can’t alias a val (b)
val Doesn’t work because a val (x) can’t alias a ref (a)
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ref): I32 => x.v() + 1
class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X val): I32 => x.v() + 1
ref doesn’t work because a ref (x) can’t alias a val (b)
val Doesn’t work because a val (x) can’t alias a ref (a)
class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X box): I32 => x.v() + 1
Reference Capabilities: box (box)class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X ref): I32 => x.v() + 1
class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X val): I32 => x.v() + 1
ref doesn’t work because a ref (x) can’t alias a val (b)
val Doesn’t work because a val (x) can’t alias a ref (a)
class X let v: I32 new create(v': I32) => v = v'
actor Main new create(env: Env) => let a: X ref = X(7) let b: X val = recover X(8) end bar(a) bar(b) fun bar(x: X box): I32 => x.v() + 1
box works because a box (x) can alias a ref (a) or a val (b)
Reference Capabilities: tag (tag)
tag
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
object
tag reference cannot read or modify an object, but it can be used to send the object messages if the object is an actor. Other references may read or modify the object as long as they do not violate the Read Rule and the Write Rule.
Reference CapabilitiesSendable → iso, val, tag
Objects with sendable reference capabilities can be sent to other actors in messages
iso trn
ref val
box box
OR
tag
Reference Capabilities: Sending A valclass Bar
actor Foo be baz(x: Bar val) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover val Bar end f.baz(b)
Reference Capabilities: Sending A valclass Bar
actor Foo be baz(x: Bar val) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover val Bar end f.baz(b)
main
Reference Capabilities: Sending A valclass Bar
actor Foo be baz(x: Bar val) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover val Bar end f.baz(b)
Main Foo
foo
Reference Capabilities: Sending A valclass Bar
actor Foo be baz(x: Bar val) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover val Bar end f.baz(b)
Main Foo
f
Bar
b
Reference Capabilities: Sending A valclass Bar
actor Foo be baz(x: Bar val) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover val Bar end f.baz(b)
Main Foo
f
Bar
b
baz( )
Reference Capabilities: Sending A valclass Bar
actor Foo be baz(x: Bar val) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover val Bar end f.baz(b)
Main Foo
f
Bar
b
baz( )
x
Reference Capabilities: Sending A valclass Bar
actor Foo be baz(x: Bar val) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover val Bar end f.baz(b)
Main Foo
f
Bar
b x
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
An actor’s default reference capability is tag
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
main
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
Main Foo
foo
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
Main Foo
f
Bar
b
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
Main Foo
f
Bar
b
baz( )
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
Main Foo
f
Bar
b
baz( )
x
Reference Capabilities: Sending A tagactor Bar
actor Foo be baz(x: Bar tag) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = Bar f.baz(b)
Main Foo
f
Bar
b x
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
main
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Main Foo
foo
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Main Foo
f
Bar
b
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Main Foo
f
Bar
b
consume causes b to give up it’s reference
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Main Foo
f
Bar
b
once we consume b, we can no longer use it
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Main Foo
f
Bar
b
baz( )
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Main Foo
f
Bar
b
baz( )
x
Reference Capabilities: Sending An isoclass Bar
actor Foo be baz(x: Bar iso) => // do something with x
actor Main new create(env: Env) => let f = Foo let b = recover iso Bar end f.baz(consume b)
Main Foo
f
Bar
b x
● The Read Rule: If an actor can read an object then no other actor can modify that object
● The Write Rule: If an actor can modify an object then no other actor can read or modify it
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
2000000
No More Data Racesuse “collections”
actor Counter var _count: U64 = 0 be increment() => _count = _count + 1 be print(env: Env) => env.out.print(_count.string())
actor Incrementer new create(counter: Counter, main: Main) => for x in Range(0, 1_000_001) do counter.increment() end main.finished(this)
actor Main let _finished_count = 0 let _counter: Counter = Counter let _env: Env new create(env: Env) => _env = env let inc1 = Incrementer(_counter, this) let inc2 = Incrementer(_counter, this) be finished() => _finished_count = _finished_count + 1 if _finished_count = 2 then _counter.print(env) end
The Counter actor “protects” the _count data structure
Sendence’s Experience With PonyIt’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
Sendence’s Experience With PonyIt’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation
Sendence’s Experience With PonyIt’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation● things change
Sendence’s Experience With PonyIt’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation● things change● there are some sharp edges (compiler bugs, runtime bugs)
Sendence’s Experience With PonyIt’s nice to catch errors a compile time rather than runtime
Pony is a young language (not even 1.0.0 yet)
● limited documentation● things change● there are some sharp edges (compiler bugs, runtime bugs)
“America is all about speed. Hot, nasty, badass speed.” -- Eleanor Roosevelt
PONY
Learn MoreUser Mailing List
● https://pony.groups.io/g/user
Website
● https://www.ponylang.org
IRC
● freenode #ponylang
ContributeDeveloper Mailing List
● https://pony.groups.io/g/dev
Github
● Pony compiler → https://github.com/ponylang/ponyc● RFCs → https://github.com/ponylang/rfcs