I've never met anyone else using Pony in production, so I'll try and give the best answer I can.
> What made you choose Pony?
We wanted a Type Safe language to run a REST API frontend. That is to say, we wanted to have something that could redirect requests to the appropriate servers, at scale, whilst maintaining Type Safety in the server itself. We got hit by so many issues from JSON's weak/absent typing causing runtime errors, we wanted something that could sanely prove that we wouldn't crash.
Whilst we were at it, the same language seemed great for the backend for a couple languages we develop in-house. For example, Owlang is a language developed for teaching with a group of teachers. The first iteration was written in Scheme, today, it runs on top of Pony.
We considered three languages:
* Rust
* Pony
* Erlang
Erlang was a bit odd to throw in the mix, but we couldn't ignore how amazing BEAM is, especially with recovery by dropping and creating thousands of processes without effort.
However, we found Rust was making too many breaking changes, and there was sort of a culture of using Rust Nightly, which doesn't give off a nice solid feel, or didn't back then.
Erlang has this sort of huge cognitive overload with it's syntax, making it take longer to learn, for no obvious benefits.
Pony's Philosophy[0] however, felt damn good, and we investigated their mathematical proof of safety and the like.
> Can you talk more about using Pony in a production environment?
Pony's got a few gotchas. Thankfully, they spell them out. [1]
We have been burned from long running procedures when we've had to tap out to an in-house C library. We went from using around 400mb of RAM for a group of processes, to running out of memory on a 16GB RAM machine.
That was a stupid mistake. However, using a Timer, like the docs tell you to, obliterated that, and we dropped back down to 4-500mb.
The non-preemptive nature of Pony's scheduler has taken a few people, myself included, some time to get used to.
> How do you find writing 'non-actor' code - like just doing some string manipulation?
If you try and avoid the fact you're using Actors, it'll bite you. Pony is designed for concurrency.
However, if we're just talking about methods and classes and so on, and how they feel... Pony feels simple, and easy to use.
Traits and interfaces make subtyping a breeze, especially interfaces.
But, being interested in Erlang, how about some pattern matching?
fun f(x: (String | None), y: U32): String =>
match (x, y)
| (None, _) => "none"
| (let s: String, 2) => s + " two"
| (let s: String, 3) => s + " three"
| (let s: String, let u: U32) if u > 14 => s + " other big integer"
| (let s: String, _) => s + " other small integer"
else
"something else"
end
One more bonus for something Pony has, that proved unexpectedly useful, is the ability to have multiple, or generate, Environments. In terms of Pony, that means argc, argv, argp. Being able to isolate environment variables between processes has been useful for making some configuration easier.
[0] https://tutorial.ponylang.org/#the-pony-philosophy-get-stuff...
[1] https://tutorial.ponylang.org/gotchas/