FAQ
About Pony
How’d Pony come to be?
Check out “An Early History of Pony”.
Why’s it called “Pony”?
Interesting question. We hear that a lot. If you read enough of “An Early History of Pony”, you’ll get your answer.
What makes Pony different?
See the “What makes Pony different” section of “Discover”.
Why would I use Pony instead of language X?
That’s a hard question to answer. Language X is probably very compelling for some problems. It’s probably less compelling for others. Such is computers. In the end, the best we can do is tell you what Pony is good at and you can make the decision for yourself. To learn more about Pony, we suggest checking out the “Discover” section of the website. There’s a portion of that section called “Why Pony” that might answer your question.
Where can I find the Pony roadmap?
There is no official roadmap. Pony is a volunteer driven project. Unlike many programming languages, we don’t have corporate backing. Our users add features and fix issues based on their needs. Pony users solve the problems that matter to them, and we all benefit.
Many of us who are regular contributors share some general goals as we move towards an official 1.0 release. We are working towards making Pony a stable, rock-solid platform for writing high-performance, concurrent applications.
We invite you to join our small but growing community and help push Pony forward. We’re still at an early stage, and new community members can have a huge influence on the language. Join us!
Does Pony really prevent data races?
So, this question usually comes in many different forms. And the question usually arises from a misunderstanding of the difference between a “data race” and a “race condition”.
Pony prevents data races. It can’t stop you from writing race conditions into your program.
To learn more about the differences between race conditions and data races, check out “Race Condition vs. Data Race” by John Regehr.
Are there any examples of something complex built in Pony?
Yes! Here’s a few projects we regularly point people towards:
- Jylis - A distributed in-memory database for Conflict-free Replicated Data Types
- Novitiate - A procedurally generated RPG inspired by Rogue and written in Pony.
- Ponycheck - Property Based Testing for Pony
- Wallaroo - Distributed Stream Processor written in Pony
Does Pony have a formatter?
At this time, no. There is no formatter for Pony code. The lack of a formatter doesn’t indicate that the Pony core team is opposed to code formatters. There is strong interest in having a code formatter for Pony.
An easy to maintain code formatter would share parsing code with the compiler. At this time, sharing said code is difficult. We are working towards making maintaining a code formatter and other parsing related tooling easier. We plan to introduce a code formatter in the future.
Code
How can I turn a ref
into a val
?
Generally, you can’t.
A ref
may have any number of untracked mutable aliases, so it can’t be declared immutable. If you start with iso
or trn
instead, you can guarantee that by consuming it you are destroying the only mutable reference, hence allowing it to become immutable. See the capabilities section of the tutorial for more information.
Similarly, a ref
may sometimes be “lifted” to a val
capability if it was created in the isolated region formed by a recover
block, from which the compiler guarantees that no mutable references can leak. See the recover section of the tutorial for more information.
What does Foo()
do if my Foo
class has both create()
and apply()
methods? Does it call both?
Yes, it calls both. However perhaps not in the way you imagine.
Foo
creates a new object instance usingcreate()
()
is theapply
call on the newly createdFoo
instance
This example program demonstrates what is going on:
use "debug"
class Foo
new create() =>
Debug("create called")
fun apply() =>
Debug("apply called")
actor Main
new create(env: Env) =>
Debug("call Foo()")
Foo()
Debug("call Foo")
let foo = Foo
Debug("call foo()")
foo()
Check out the example program in the Pony Playground.
For more information see the Sugar section of the the tutorial.
How can I write code that works for every kind of Number in Pony?
If you want to support all kinds of numeric types for which Pony supports there are three ways to approach this problem:
- Via Inheritance:
You pick the trait or interface that satisfies the operations you need from those numbers (e.g. support for sub
is defined in trait val Real[A: Real[A] val]
) and use this as a type or type parameter in Generics. This works fine for a lot of cases. But e.g. literal inference will not work here, as this example shows:
// does not compile
primitive OneForAllInheritance
fun do_generic_stuff[T: Real[T] val](t: T): T ? =>
if t == T.min_value() then
error
else
t.divmod(1) // can be fixed by: t.sub(T.from[U8](1))
end
. Why is that? Literal inference only works for the built-in primitive types, but Integer[T] val
could be extended by further not yet known classes.
- Via Type Expressions:
There are plenty of pre-defined union types for all classes of numbers in Pony. E.g. type Signed is (I8 | I16 | I32 | I64 | I128 | ILong | ISize)
. There is also Unsigned
, Int
, Float
and Number
. Just pick what you need as your type.
// does not compile
primitive OneForAllTypeExpressions
fun do_generic_stuff[T: Int](t: T): T ? =>
if t == T.min_value() then
error
else
t.sub(1)
end
But there is a problem with this approach. Not only do we state that T
could be any element of Int
. It could even be a combination of them. e.g. ( U8 | I16 )
and how you use t
and T
here must work for all possible instantiations of Int
, that is every possible combination.
- Via Type Expressions AND Inheritance:
To get rid of the literal inference problem and to make sure only single numeric types are accepted, not unions of them, in order to use the methods on the different integer types for our generic problem, we need to combine both the type unions and inheritance to get to a safe solution: (Int & Integer[T] val)
. The reason why this works is that Integer[T] val
can only be instantiated by a single concrete Int
element, so we get rid of the combinations and at the same time make the literal inference work as we lock our generic T
down to single concrete types being part of Int
:
primitive OneForAllCombined
fun do_generic_stuff[T: (Int & Integer[T] val)](t: T): T ? =>
if t == T.min_value() then
error
else
t.sub(1)
end
Nice!
Compiling
What are Pony’s supported CPU platforms?
As of ponyc
release 0.26.0
, we provide the following support:
- Full support for 64-bit platforms
- x86 and ARM CPUs only
- Experimental, incomplete, and/or buggy support for 32-bit platforms
I get a “requires dynamic” error when compiling, how do I solve it?
/usr/bin/ld.gold: error: ./fb.o: requires dynamic R_X86_64_32
reloc against 'Array_String_val_Trace' which may
overflow at runtime; recompile with -fPIC
try running ponyc
with the --pic
flag.
For example:
ponyc --pic examples/helloworld
As of Pony 0.17.0, if you are building ponyc
from source, you can have --pic
automatically set for you. When building ponyc
, run the following make
command and your generated ponyc
binary will always supply --pic
without you having to set it.
make default_pic=true
On Windows I get “fatal error LNK1112: module machine type ‘x86’ conflicts with target machine type ‘x64’”
Only 64-bit Windows is supported.
Make sure you’re running a cmd.exe/powershell.exe that does not include 32-bit VS environment variables.
This error occurs when ponyc is compiled in a 32-bit Visual Studio Developer Command Prompt.
Ecosystem
Does Pony have a package manager?
That would be yes and no. Package manager means different things to different people. What we have is a simple dependency manager called pony-stable that we are planning on growing into a full featured tool. Whether that is a more full featured “dependency manager” or more full featured “package manager” depends on how you define the two terms.
Is there SSL support?
Yes! There used to be SSL support in the Pony standard library, but it’s been moved out into its own library.
Linking
How can I supply custom linker parameters?
So, you need to link your program to a custom library or otherwise pass a particular linker option? You can accomplish your goal using the ponyc
--linker
option.
You’ll need to know what your current linker is. To get it, compile a pony program and pass --verbose 3
.
On Linux, MacOS or other Unix-like
Then examine the output. You should see something like:
ld -execute -no_pie -dead_strip -arch x86_64 -macosx_version_min 10.8
-o ./timer ./timer.o -L"/usr/local/lib/pony/0.9.0-e64bff88c/bin/"
-L"/usr/local/lib/pony/0.9.0-e64bff88c/bin/../lib"
-L"/usr/local/lib/pony/0.9.0-e64bff88c/bin/../packages"
-L"/usr/local/lib" -lponyrt -lSystem
The ld
is the linker command that is usually used on MacOS or Linux. If I wanted to link in the library Foo
and needed to pass -lFoo
then I would compile my program as:
ponyc --linker="ld -lFoo"
That would change the linker command that ponyc
runs to:
ld -lFoo -execute -no_pie -dead_strip -arch x86_64 -macosx_version_min 10.8
-o ./timer ./timer.o -L"/usr/local/lib/pony/0.9.0-e64bff88c/bin/"
-L"/usr/local/lib/pony/0.9.0-e64bff88c/bin/../lib"
-L"/usr/local/lib/pony/0.9.0-e64bff88c/bin/../packages"
-L"/usr/local/lib" -lponyrt -lSystem
On Windows
Compiling a pony program with --verbose 3
will produce something like:
cmd /C ""C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\bin\HostX64\x64\link.exe"
/DEBUG /NOLOGO /MACHINE:X64 /OUT:.\helloworld.exe .\helloworld.obj
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\ucrt\x64"
/LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\x64"
/LIBPATH:"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\lib\x64"
/LIBPATH:"C:\pony\ponyc\build\release-llvm-3.9.1"
/LIBPATH:"C:\pony\ponyc\build\release-llvm-3.9.1\..\..\packages"
kernel32.lib msvcrt.lib Ws2_32.lib advapi32.lib vcruntime.lib legacy_stdio_definitions.lib dbghelp.lib ucrt.lib libponyrt.lib "
The path ending in link.exe
is the linker that the pony compiler is currently using.
To add options to the link command, I would compile my program as something like:
ponyc --linker="C:\OtherPath\link.exe /LIBPATH:C:\Foo"
Runtime
Does Pony have green threads?
The short answer is no. Pony doesn’t have green threads. By default, the Pony scheduler starts 1 “actor thread” per available CPU. These threads are used to schedule actors. Each of these threads is a kernel thread.
The longer answer is “it depends”. Actors are Pony’s unit of concurrency and many people when asking if Pony has green threads really are asking about how concurrency is modeled. You, as a Pony programmer, never interact with scheduler threads directly, you never interact with any sort of thread. You worry about actors and sending messages between them.
What is causal messaging?
When we say that Pony has causal messaging, we mean that the Pony runtime provides certain guarantees about message delivery order. Given two actors, actor A and actor B. All messages sent from actor A will arrive at actor B in the order they were sent by Actor A and will be processed by Actor B in the same order. The causal ordering between messages will be preserved as an invariant by the runtime.
Causal messaging extends to a chain of actors. For example, if Actor B sends messages to Actor C in response to messages from Actor A, then there is a causal messaging chain from Actor A to Actor C. The cause of a message is a message from another actor and the ordering will be preserved.
It is essential to understand that the causal ordering of messages only exists between the two actors who are the sender and recipient of those messages. So for example, if actors X and Y send to actor Z, there is no guarantee what order the messages will be processed by Z except that we can say, all messages sent by X will be processed in the order they were sent, as will all messages sent by Y. However, messages from X and Y can arrive at Z interleaved in any order that maintains the causal ordering of X to Z and Y to Z.