Pony: Combining safe memory sharing with Erlang-like actors
tutorial.ponylang.org
tutorial.ponylang.org
We love when folks notice us, hopefully a couple people who read this end up in the Pony community. That said, the "better-than-Rust" makes me uncomfortable. Pony and Rust have different goals and make different tradeoffs with regard to memory safety. We don't think one is better than the other. They are different.
Anyway, back to my Sunday. Y'all enjoy.
Given this is a link to part of the tutorial. I'll drop some additional links if you are interested in learning more:
high-level overview of Pony's value proposition: https://www.ponylang.org/discover/
our current "start here" resources for learning pony: https://www.ponylang.org/learn/
collection of blog posts, videos and what not: https://www.ponylang.org/community/planet-pony/
main compiler GitHub repo: https://github.com/ponylang/ponyc
user mailing list you can sign up for to get more info: https://pony.groups.io/g/user
#ponylang on freenode for IRC (generally very quiet on weekends)
there's a http server that is part of the standard library but it wasn't written to be high-performance. it has good latency characteristics but poor throughput characteristics.
i've written a number of http servers during my career, don't really have the stomach to do another. hopefully in the not so distant future, someone writes one in Pony with an eye towards performance.
It would be better to compare pony's memory safety to a GC language: go, Java, C#, Haskell, etc.
As for the rest, IT world is full of political murders of nice technology.
As Alan Kay puts it, pop culture driven development.
You have Joe Duffy's blog entries about Midori and one entry back when it was still called M#.
Then there are the little pieces that came to C# from it.
Namely async/await, TPL, the MDIL compiler on Windows 8.x, the .NET Native compiler for UWP, the improved GC control in .NET 4.6 and the planned features for C# 7.1, 7.2 and 8.0 related to more mechanical sympathy.
Joe Duffy's blog about Midori
http://joeduffyblog.com/2015/11/03/blogging-about-midori/
Joe's blog entry about what was known as M# at the time
http://joeduffyblog.com/2013/12/27/csharp-for-systems-progra...
Joe's presentation at QCon 2015, "Safe Systems Programming in C# and .NET"
https://www.infoq.com/presentations/csharp-systems-programmi...
Channel 9 presentations about MDIL compiler for Windows 8.x
https://channel9.msdn.com/Events/Build/2012/3-005
https://channel9.msdn.com/Shows/Going+Deep/Mani-Ramaswamy-an...
Channel 9 presentations about .NET Native
https://channel9.msdn.com/Shows/Going+Deep/Inside-NET-Native
https://channel9.msdn.com/events/dotnetConf/2014/-NET-Native...
GC Improvements on .NET 4.6, including memory guarantees for performance critical sections
https://docs.microsoft.com/en-us/dotnet/api/system.gc.trysta...
https://blogs.msdn.microsoft.com/alphageek/2017/01/24/signif...
C# roadmap for 7.1, 7.2 and 8.0 with more memory friendly features
https://github.com/dotnet/roslyn/blob/master/docs/Language%2...
Joe is presenting a keynote at Rustconf, about memory safe systems programming.
Go, Java and C# all suffer from all the problem above. Go in particular (due to confusing slicing semantics and dearth of immutable data structures) and C# slightly less (due to a lot of syntactic sugar to help you with null-safety).
Haskell is a slightly different beast. I assume that with idiomatic Haskell, except for an occasional runtime error due to bad program logic, you'll rarely run into these issues.
I've found that the capability system is both the most exciting part of Pony and the most difficult part to grok for a new comer.
We have a section of the website on learning Pony that focuses on a "plan of action" for learning reference capabilities:
Both very interesting to read!
* It looks like exceptions carry no error information. When something goes wrong, you know nothing. Is that right?
* Calling finalizers from GC is usually troublesome. They get called late, so they can't be relied to close files and such. They also have to be prevented from making trouble by doing things you can't do during GC, or "re-animating" the object being deleted. How's that handled?
* The notion that variable type is established at initialization is becoming mainstream. How about extending that to structures? The fields of structures could get their types inferred from the structure constructor. (There was a statically typed variant of Python, Shed Skin, which did this.)
Yes and no. You know something went wrong. `error` is supposed to only be used when it indicates a specific thing that went wrong. If you need error information, you should use a union type ala Rust.
There's been discussion on the Pony core team to change the name from "exception" has that carries a lot of expectations these days (folks generally expect that they will be akin to exceptions in Java et al)
pony: class Foo[A: Any val] c#: public class MyGenericArray<T> rust: fn foo<T>(T) { ... } golang: none, because existing examples (outside of pony) too complicated
Which most obviously suggests a generic func? Geez, took us this long to just reach some clarity? Nice job, Pony.
More: 1 + 2 * 3 // wont compile 1 + (2 * 3) // will compile
yes! I have devs with college degrees who don't understand operator precedence.
Liking what I see so far. Nice mix of low cognitive load/high expressiveness/safety. Keep at it.
Bitwise operators in C-like languages have precedences that make no sense at all; I can't remember those either. (Even though they sort-of make sense if you consider their historical heritage... no excuses though.) But do you really see software developers with a university degree that mess up the precedence of times and plus? I shudder when thinking about them working with my code. I would really appreciate to be able to write e.g.
a + b == 0 || c * d - e > f / g
without a misunderstanding of precedence. Why is that not a basic feature in the first programming course one gets? It certainly was in mine, two years ago.EDIT: is there any way to sanely embed an asterisk in normal text here?
In Pony developers must write behaviours in a way that allows the scheduler to give CPU to other behaviours and to run GC periodically to collect unused memory. Otherwise other behaviours won't be able to run or will consume too much memory.
https://tutorial.ponylang.org/gotchas/
Erlang processes are also much smarter. They can be linked to each other to be notified when their linked counterparts die. This allows to create a well structured hierarchy of processes, each one with a different role to fulfil in the application.
http://erlang.org/doc/design_principles/des_princ.html
A completely separate issue is their different approach to handling errors. Pony, similarly to Rust, tries to prevent the developer from crashing the application. Usually they do a decent job, but situation where the actor will need to crash or will never return are inevitable (see gotchas above, also imagine some dodgy code executed through FFI, etc).
Erlang takes a "let it crash" approach to managing those situations. Its BEAM (runtime, or VM in which the processes run) is the core that executes all processes. The core is not supposed to crash under normal circumstances but the processes are expected to crash as soon as they can't recover from an error.
http://lists.ponylang.org/pipermail/ponydev/2016-February/00...
-2 alias types and especially ephemeral types. Anonymity should be no big deal (e.g. lambda is boring, closing over variables is interested). This seems like a monkey patch over not respecting that principle.
Good job for being much more interesting than your average new PL post.
Pony looks interesting and I hope it develops further.
Never been personally bit by those two.
C's runtime is called Crt0 in most POSIX systems.
But truth to be told, it was a quick reply without much thought.
Thanks.
But maybe that model changed in the meantime.
Unless you mean that some data is shared, but cannot be modified, but this would be semantically identical to not sharing anything.
Look, just read up on the type system, specifically reference capabilities[0]. It's basically what allows for safe mutability and data passing when required.
[0] https://tutorial.ponylang.org/capabilities/reference-capabil...
That's the gist of Rust's borrow checker. Shared data can't be modified (unless you use a Mutex or something similar, but then you need to acquire a lock, so data you can mutate is not shared).
> [...] this would be semantically identical to not sharing anything.
Erlang's data sharing (and no, not all binary data, just over a certain threshold; if you want to nitpick, be diligent and precise) is merely optimization trick, highly uninteresting when it comes to discussing type systems (because its semantics are identical to not sharing anything at all).
BTW, if you talk about Erlang, use proper Erlang's terminology. Erlang doesn't have "actors", it has "processes".
From the point of view of those that understand GC implementation algorithms, it is an actor local GC only executed at specific defined points, coupled with capabilities.
Rust use of affine types for memory management is great, but not all applications need such tight memory management, so it is a good productivity improvement to just be able to use a GC approach.