Live data from Hacker News

Pony: An actor-model, capabilities-secure, high-performance programming language

ponylang.io

231–240 of 284 posts

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#231
post #229
post #223

Earlier quoted context omitted.

I appreciate your good intentions re the site guidelines! But I'm afraid you've been breaking them multiple times in this thread by being much too aggressive with other users. This post is one example, and here are two others: https://news.ycombinator.com/item?id=44728708 https://news.ycombinator.com/item?id=44722043 It's laudable to want work like Pony to get discussed in terms of the most interesting things about i…

All I see is that I've been personally attacked and mischaracterized. If I could downvote such comments I would do that rather than respond. Calling my response here aggressive or an attack is simply not factual, it is hypervigilance against me. Where is your criticism of "Good faith argumentation, or really argumentation in general, went out the window when you started treating whether syntax matters (for this langu…

I really did not mean it as a personal attack, as unbelievable as that may be, apologies if it came across that way.

> I can't flag that outrageous personal attack and no one else has.

Why wouldn't you be able to flag it? And there's no flagged counter, it's not possible for ordinary users to tell how many times a post has been flagged; you cannot know that no one has flagged it, only that it is yet to reach the threshold.

> it's not the target's fault for perceiving it that way.

Where did I say or suggest that it was? If I thought that, what would I be apologizing for?

> If you're saying something negative about someone then that's a personal attack.

I disagree: if someone has negative traits or behavioral patterns that are externally observable, people should not be at fault for observing them and confronting the person about it.

In my view, and I believe in most everyone's view, personal attacks (personal insults) are attacks (expressions that incite) that use the other party's real, perceived, or claimed-perceived personal attributes as but a delivery vehicle for insult. They're the exact opposite of a genuine critique of someone's character or behavior in this sense, which is a thing I recognize as existing, valid, and distinct from this.

And so when I said I didn't mean those to be personal attacks, that's why I did so; it was me clarifying that I wasn't abusing personal critique to deliver an insult (nor do I think I actually delivered any), I legitimately just meant to offer a critique. Clearly it didn't land that way, and so for that I apologize. This is in contrast with "You seem to be struggling with the whole fallacy thing by the way", which I 100% meant as a personal insult, and was unsurprisingly moderated out for it. I did mean it, I do agree with it, but it was absolutely a vehicle for delivering an insult first, and everything else second.

It really does seem like we just disagree every step of the way.

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#232

Earlier quoted context omitted.

Nim feels like the perfect language to me. Keep meaning to give it a shot for something.

The way it handles imports is weird. Default to importing everything from the module without qualification? I know you can choose to qualify everything, but that seems to go against the language's conventions.

Using fully qualified imports is a Python tradition.

Python doesn't have a notion of public/private symbols (no, "__" prefix does absolutely nothing). It also doesn't have a good type system, so it can't have function overloading.

This is why you're required to qualify almost all imports in Python, to avoid name clashes.

Nim doesn't have this problem and also "fixes" a lot of other shortcomings[1] of Python.[2]

[1] - https://github.com/yugr/python-hate

[2] - https://github.com/nim-lang/Nim/wiki/Nim-for-Python-Programm...

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#233
post #16

The difference between Pony and Rust is that Pony allows easy reference cycle. One of the innovative point of Pony is the iso reference. iso reference means that an object graph is accessible from only that iso reference. It avoids sharing mutable data.

Pony also seems to hide more complexity and come with more batteries included than Rust, making it a little closer to the spirit of Go in that sense. That’s my first impression.

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#234
post #13

This is probably my favorite programming language I would like to use if it had more backing. Their reference capabilities in particular seem like a very good match for the actor model. Alas, it does not appear to have a large corporation behind it pushing it forward, nor a compelling niche use case (e.g. it is still GC'd).

Go is GC’d and that doesn’t stop it. What’s wrong with GC? Maybe for tiny tiny tiny embedded or constant time use cases that’s a deal breaker.

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#235
post #234
post #13

This is probably my favorite programming language I would like to use if it had more backing. Their reference capabilities in particular seem like a very good match for the actor model. Alas, it does not appear to have a large corporation behind it pushing it forward, nor a compelling niche use case (e.g. it is still GC'd).

Go is GC’d and that doesn’t stop it. What’s wrong with GC? Maybe for tiny tiny tiny embedded or constant time use cases that’s a deal breaker.

> constant time use cases that’s a deal breaker.

There are real-time safe GC algorithms. I don't know whether Pony offers that option. I would like to know.

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#236
post #76

Earlier quoted context omitted.

Sending a message between Actors can be just moving a pointer to a piece of shared memory. I think sending messages is more about the way you think about concurrency, more than the implementation. I have always found the "one thread doing "while True receive message, handle message" much easier to reason about than "remember to lock this chunk of data in case more than one thread should access it"

> Sending a message between Actors can be just moving a pointer to a piece of shared memory. No, you also need synchronization operations on the sending and the receiving end, even if you have a single sender and a single receiver. That's because message queues are implemented on top of shared memory – there's no way around this on general-purpose hardware.

Depends on your definition of synchronization operations. You certainly need memory fences, and possibly atomic operations. These may or may not have a performance cost.

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#237
post #24

Earlier quoted context omitted.

Sure, if I go dig deep I'll find that. But I was talking about the sales pitch. Once it's necessary to go click links in a levels-down comment in the HN discussion section, you've already lost most folks.

They aren't selling anything, and they didn't write their documentation with HN in mind ... the OP is probably not associated with them.

The OP is definitely not associated with them. Just a curious actor model enthusiast.

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#238

"Exception-Safe¶ There are no runtime exceptions. All exceptions have defined semantics, and they are always caught." So checked Exceptions like Java?

The difference is that there's only one exception type and it can't carry payloads. This turns out not to be very different from an option type like in Rust or Swift, just with a bit of syntactic sugar around it.

Hmm ... How do you implement the common pattern of a top-level exception catcher (e.g. for a long-running thread) with option types in pony/rust/swift? In Haskell this is ergonomic thanks to Functor and friends, but how do langs other than Haskell propagate this behavior up the call stack?

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#239
post #49

Earlier quoted context omitted.

For Pony in particular, the syntax is not important ... it's simply not the point of the language.

If the syntax is not important, that would mean coding in whitespace or malboge would be as easy as coding in python

The GP is factually wrong. There's plenty of empirical evidence to indicate that language influences thought, and that syntax is therefore important.

Although, I would point out that while your argument ad absurdum is generally reasonable (the fact that syntax can make the difference between a very good language and an unusable one), whitespace and malbolge also have terrible semantics that contribute to them being unusable.

As a former Lisp enthusiast (and still an enjoyer), I'd actually use my own darling as an example: Lisps have amazing semantics and are generally good languages. Their syntax is highly regular and structured and easy to parse...except that it's brain-hostile, and I'm convinced that it actively makes it harder to read and write - not just adopt, but actually use.

Re: Pony: An actor-model, capabilities-secure, high-performance programming language

#240

Earlier quoted context omitted.

The difference is that there's only one exception type and it can't carry payloads. This turns out not to be very different from an option type like in Rust or Swift, just with a bit of syntactic sugar around it.

Hmm ... How do you implement the common pattern of a top-level exception catcher (e.g. for a long-running thread) with option types in pony/rust/swift? In Haskell this is ergonomic thanks to Functor and friends, but how do langs other than Haskell propagate this behavior up the call stack?

So for baseline context, we can consider two kinds of errors; there's no standard terminology, but I'll call them "exceptional results" (caused by problems outside your process's control, like filesystem or network failures) and "runtime errors" (caused by bugs in your code, like trying to dereference a null pointer or index past the end of an array).

Pony: Doesn't distinguish between exceptional results and runtime errors; either a function is guaranteed not to fail, or it isn't. A function that isn't is called "partial", and can only be called either from another partial function or from a try block that specifies how to handle errors. So anything that can fail in any way, including indexing into an array, has to be partial; there's no way to tell the compiler "please don't force my caller to handle the possibility of a bounds check failure, I'm sure that won't happen, and if it does then everything is terminally messed up and we should just crash". Likewise with a value of a union type being None when it shouldn't be, or otherwise being the wrong type. (They tried having integer division be partial, but apparently that was a bridge too far—so instead, any integer divided by zero is zero.) The top-level error-handling pattern would need to be implemented by making basically every non-leaf function in your codebase partial. Also, these errors can't have payloads or anything, so the top-level handler can't make use of any diagnostic information (if you want that then you need to instead return a custom union type and forgo the partial-function syntactic sugar). I haven't actually used Pony in anger but this is definitely the feature of the language that impresses me least; it's ostensibly in the name of correctness, by prohibiting programs from crashing, but you can't actually prevent the root causes of crashes without dependent types, so instead they've made this mess that makes effective error handling impossible.

Rust: Exceptional results are represented with the Result type, instances of which are just values returned from a function like any other. There's syntactic sugar (the ? operator) to propagate an error up a stack frame. A Result has a payload whose type must be specified; ergo, every function's API must effectively declare not only whether it can return exceptional results, but also what kinds. In a library, you'd typically design a structured error type to represent the possible exceptional results that your API can return, but in a binary, you may not care about that level of detail in each function's API, and instead prefer to return a catchall "some exceptional failure, idk what" type. Out of the box the language has Box for this, but it's more common to use a third-party crate like anyhow or eyre that makes this pattern more ergonomic. In an application that handles errors this way, most likely every function that does I/O returns Result> (or the anyhow or eyre equivalent), while functions that just do pure computation on trusted data return non-Result types. Runtime errors use a different system, panics, which are not part of a function's API (so any function can panic); by default, panicking unwinds the call stack until it reaches a catch_unwind call or the bottom frame of the current thread's stack (allowing a top-level handler to use catch_unwind or Thread::join to catch and handle runtime errors), but when building an executable binary you can instead configure it to skip all that and immediately crash the process when a panic occurs (there are pros and cons to doing this). For this reason, library code can't rely on catch_unwind working, so it's important for libraries not to try to use panics to convey recoverable errors. A Result can be turned into a panic with the unwrap method, if you're sure that the relevant exceptional result can't occur or if you're just being lazy/writing prototype throwaway code and don't want to bother getting the function signatures right.

Swift: Exceptional results work like checked exceptions in Java, but without all the problems that make the latter not work very well in practice. Each function signature can either never throw anything (the default), throw any Error (with an arbitrary payload whose type is unknown at compile time, analogous to Rust's Box), or throw a specific Error subtype with a specified payload (this last one is uncommon). When calling a throwing function, you must either handle the error or (if you throw a compatible type) propagate it up to your own caller; there are various syntax-sugar niceties to handle this. There's a Result type like in Rust but it's not commonly used as a return value, it's mostly only needed if you're storing errors in data structures or similar. So a top-level error handler is done by having all functions that do I/O be throwing functions, like in Rust but with nicer syntax. Runtime errors are not declared in function signatures and always immediately crash the process; unlike in Rust, there is no way to have a top-level handler for them. Like in Rust, you can turn an exceptional result into a runtime error (Swift's syntax for this is the try! operator).

Post reply on HN