jemc changed the topic of #ponylang to: Welcome! Please check out our Code of Conduct => https://github.com/ponylang/ponyc/blob/master/CODE_OF_CONDUCT.md | Public IRC logs are available => http://irclog.whitequark.org/ponylang | Please consider participating in our mailing lists => https://pony.groups.io/g/pony
atk has quit [Quit: Well this is unexpected.]
atk has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
<alexashka> hi, I'm using use "debug", it works in the online playground but when I compile on my machine using ponyc, the debug messages are missing. I'm on macOS
<alexashka> any ideas?
<SeanTAllen> you have to do a debug build, which is the default in the playground
<SeanTAllen> ` --debug, -d Don't optimise the output.`
<SeanTAllen> that's one of the ponyc options
<SeanTAllen> so instead of `ponyc`
<SeanTAllen> `ponyc --debug`
acarrico has quit [Ping timeout: 260 seconds]
khan_ has joined #ponylang
khan_ has quit [Client Quit]
khan_ has joined #ponylang
khan has quit [Ping timeout: 276 seconds]
khan_ is now known as khan
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
gokr has quit [Ping timeout: 256 seconds]
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
<alexashka> ah ok, great thank you
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
endformationage has quit [Quit: WeeChat 1.9.1]
bimawa2 has joined #ponylang
bimawa1 has quit [Ping timeout: 256 seconds]
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
vaninwagen has joined #ponylang
gokr has joined #ponylang
khan has quit [Remote host closed the connection]
lisael_ has quit [Ping timeout: 248 seconds]
lisael has joined #ponylang
atk has quit [Ping timeout: 260 seconds]
atk has joined #ponylang
vaninwagen has quit [Ping timeout: 240 seconds]
_andre has joined #ponylang
acarrico has joined #ponylang
vaninwagen has joined #ponylang
acarrico has quit [Ping timeout: 240 seconds]
SenasOzys has quit [Remote host closed the connection]
SenasOzys has joined #ponylang
acarrico has joined #ponylang
inoas has joined #ponylang
aturley has quit [Quit: aturley]
jemc has joined #ponylang
SenasOzys has quit [Ping timeout: 256 seconds]
SenasOzys has joined #ponylang
_rck has joined #ponylang
vaninwagen has quit [Ping timeout: 248 seconds]
aturley has joined #ponylang
endformationage has joined #ponylang
aturley has quit [Quit: aturley]
aturley has joined #ponylang
aturley has quit [Client Quit]
inoas has quit [Ping timeout: 248 seconds]
inoas has joined #ponylang
acarrico has quit [Ping timeout: 240 seconds]
acarrico has joined #ponylang
khan has joined #ponylang
aturley has joined #ponylang
aturley has quit [Client Quit]
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
jemc has quit [Read error: Connection reset by peer]
jemc has joined #ponylang
aturley has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
_rck has quit [Ping timeout: 240 seconds]
khan has quit [Client Quit]
khan has joined #ponylang
inoas has quit [Quit: inoas]
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
droman has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
SenasOzys has quit [Ping timeout: 265 seconds]
SenasOzys has joined #ponylang
<alexashka> Hi folks, regarding exceptions in pony - if I can have 2 exceptions raised inside a try block - is there a way to know which one got thrown in the else block?
<alexashka> for example I try to access an index of an array, and then I want to call another function that may fail with that value. How would I know if it was index out of bounds or function fail
<aturley> alexashka there's no way to differentiate between the two. you'll need to use 2 exception handlers.
<alexashka> aturley: right, so what's the common pattern with doing so? Variables created inside a try block are inaccessible. For accessing an array index, would I create a mutable variable before the try block and assign inside?
<alexashka> that seems somewhat clunky, because I have to provide a default value? Or am I missing something?
<aturley> i kind of depends on how you want to handle the failure (or if you want to handle it at all).
<alexashka> well, getting stuff out of an array is a common operation, it looks like it's 4-5 lines of code each time?
<aturley> a try block is an expression, so one thing you can do is say `var x = try ... else return end` and then you can use the value of x afterward.
<aturley> the `return` will return from the function the type of `x` will be whatever the result of a successful try would be. in this case, that would be the array lookup.
<alexashka> hm, I'm a little lost on the return part. Let's say I have a class Cat and it has a field name. It's an array of Cats. If I try to get an index that doesn't exist - what does return do?
<aturley> `return` bails from whatever function you're in.
<aturley> one sec, i'm trying to put together a gist ...
<aturley> basically the `return` just stops the execution, which may not be what you want.
<alexashka> aturley: hehe let me do a gist as well :)
<aturley> but ... if you return a type that signifies a specific error then you could have some error handling code outside the function that does something specific to the kind of failure.
<alexashka> my confusion is why that works at all - clearly the initialization of cat failed, and yet the compiler isn't complaining about it?
<aturley> it failed, but that caused the `else` path to run, which exits the `create` method.
<alexashka> right, and the create method requires a string, so shouldn't that have not worked?
<aturley> well, in the case of the example you sent, it looks like the 2 cat objects were created before the try block.
<aturley> so those create methods already ran.
<aturley> the only thing that could fail is the array access.
<alexashka> ok I think I'm not getting it - what does 'return' return exactly? It has to return a cat, and it does as far as I can tell. My question is which cat? Where'd it come from?
<aturley> no, the `return` doesn't return a Cat. it returns nothing, it just exits the `create` method altogether.
<alexashka> ok, so let cat is not an uninitialized variable?
<aturley> it doesn't return something from the `try ... else ... end` block to the enclosing scope, it actually ends the function.
<alexashka> now*
<aturley> `let cat` isn't even uninitialized ... execution never reaches the point of trying to set that variable because you return before hitting it.
<aturley> there is no `let cat` if there is an exception.
<aturley> and pony knows that there will never be a `let cat`, so it doesn't complain about types.
<alexashka> I see, so shoudn't Debug(cat) throw an error, because there is no cat then?
<alexashka> Debug(cat.name) rather
<aturley> no, again, it never reaches that point in the program.
<aturley> the `return` returns from `create` at the point where it is encountered. nothing else gets run.
<alexashka> ohhhhhh, ok I finally got it, it returns from the create method of Main :P
<aturley> yes.
<aturley> hm ... ok, now i see where the confusion came from.
<alexashka> hah I'm sorry, I got fixated on Cat's create
<aturley> i'm sorry about that.
<aturley> haha.
<aturley> whoops.
<alexashka> this is rather obvious in hindsight :)
<aturley> and i was fixated on Main.create().
<aturley> cool, things make sense now?
<alexashka> ya, i was expecting return to be only active within the try block's scope
_rck has joined #ponylang
<alexashka> but it actually returns from create instead, that's what was tripping me up
<aturley> yeah, i mean, that could be a reasonable thing to expect, depending on what languages you're used to.
<aturley> in pony, return always returns from a function.
<aturley> er ... a method (either a function or a behavior)
<alexashka> ya, ok phew :)
<alexashka> and assigning a try block to a variable is the piece I was missing before
<SeanTAllen> everything in pony is an expression
<alexashka> ya, i forgot about that very important bit, thank you :)
<SeanTAllen> at this point, i get irritated when i encounter statements in other languages.
<SeanTAllen> you get used to what you get used to.
<SeanTAllen> i'll be here all day if anyone wants pithy statements like "you get used to what you get used to"
<alexashka> so what is the common pattern for accessing an array index to do something with it? Is it to have let cat: (Cat | None) and pattern match on it?
<aturley> when i jump back to python i definitely experience a lot of "damn it, you're really going to make me do this aren't you?"
<SeanTAllen> alexashka: that would be common
<jemc> getting used to handling all errors appropriately is one of the two big hurdles to getting used to pony
<_rck> hello! I'm looking less for a concrete answer and more from general advice re: implementing something in pony
<jemc> _rck: welcome! feel free to ask
<alexashka> one more question - how do I Debug multiple things as a one liner?
<_rck> hi @jemc! I saw your delta crdt impl in pony, very cool
<jemc> alexashka: one way to do it is something like `Debug("x, y: " + x.string() +
<jemc> alexashka: one way to do it is something like `Debug("x, y: " + x.string() + ", " + y.string())`
<jemc> (sorry, ignore my first incomplete line - hit the enter key too soon)
<alexashka> ya, there's no printf equivalent?
<aturley> alexashka Debug is a subtle beast ... take a look at the function signature.
<aturley> there's no printf equivalent, but it will do some impressive things with arrays, depending on what you're trying to do.
<alexashka> aturley: I did, I don't know what's going on there so I settled for printing one thing a time :)
<jemc> alexashka: I also have a small library called `inspect` that is sometimes more convenient, but it's not a printf equivalent: https://github.com/jemc/pony-inspect
<jemc> it's hard to have a printf equivalent in Pony because Pony has no equivalent of varargs
<alexashka> jemc: well, an array would do just fine I think?
<jemc> _rck: thanks, that's my primary focus project right now
<jemc> I'm working on a distributed database with that library as the backbone of it
<SeanTAllen> _rck: anything in particular in the general advice category you are looking for?
<_rck> that's cool, I took a look at the code the other day :^)
<_rck> yeah, so my general question is: how do you handle having some global object (like say, a map), that you want to be able to read in parallel with other readers, while also being able to update it?
<_rck> so (coming from an erlang background), something similar to an ETS table, or some map with a reader-write lock associated to it
<jemc> the short answer is that it needs to be wrapped in an actor that acts as the gatekeeper for both reads and writes
<jemc> to read or write, you call the actor
<jemc> and due to the way actors work, it ends up acting sort of like a lock that guards reads and writes
<_rck> yeah, that was my first idea
<_rck> I was concerned that it would become a bottleneck in the system, though
<jemc> yeah, that's definitely a concern with this pattern
<_rck> like, would reads happen in parallel? if, say, you return a promise with some value, you're still performing the reads sequentially
<jemc> honestly, what you need might be a CRDT :)
<_rck> haha, maybe :^)
<jemc> another intermediate approach would be to partition the global key/value store
<jemc> so that each partition would still be sequential, but reads and writes to different partitions could be in parallel
<SeanTAllen> Wallaroo does that
<_rck> some thing I thought about is, you have a single actor that owns and can write to the map, and a set of read-only replica actors connected to the main actor in a sort-of pub-sub mechanism
<aturley> _rck that's what i was going to recommend
<SeanTAllen> yeah, that is something i mention to folks.
<aturley> depending on your use case
<_rck> in that case, I'm wondering what the capabilities of the map would be
<SeanTAllen> indeed. it always depends.
<_rck> you might want to propagate a sendable version of the map (or of the update to a specific key), but you want to keep your version writable
<SeanTAllen> if you have a write only copy managed by an actor, i would look at doing a ref or perhaps a persistent data structure.
<aturley> if you're using an immutable data structure (in the functional data structures sense) the gatekeeper can pass out val reference to that.
<jemc> _rck: it would be `ref` inside the actor, and the map itself wouldn't be sendable
<jemc> yeah, or if you're using an immutable data structure, `val`
<SeanTAllen> aturley and jemc are both about to suggest the two things i said, so i will be quiet now.
<_rck> yeah, so you would send like a (key, value) tuple to the subscribers?
<jemc> yeah, that's one way to do it
<jemc> it should work as long as there is only one writer and the rest are read only
<_rck> alright, I was wondering if that was an over-engineered solution, but I'm happy to hear it's a sensible thing to do :^)
<SeanTAllen> CRDTs are good at solving this.
<jemc> yeah, if go further than one writer, a CRDT is what you probably want
<SeanTAllen> you could do a lot of other things, but depending on how robust you want this to be, amount of work to get started, i would conisder doing CRDTs out of the gate.
<SeanTAllen> persistent data structure is probably the quickest way to get up and running.
<_rck> yes, I considered that re: crdts
<SeanTAllen> well, welcome to the community!
<SeanTAllen> we'll be here if you need assistance.
<_rck> thanks :^)
<SeanTAllen> everything is logged so if no one is on here, someone will answer eventually.
<SeanTAllen> and there's also the mailing list.
<SeanTAllen> logs are here: http://irclog.whitequark.org/ponylang
<_rck> yeah, I've been lurking the irc logs for a bit, it's nice to be able to read back
<alexashka> back to my cats - is there an easy way to say "I know this won't fail, don't make my life difficult"? It'd be great if I could get the first item out of an array as just Cat, without relying on a default value or pattern matching
<alexashka> in Swift for example there's a try, and there's try!, try! means just let me do what I want to do, and if it raises an exception, crash the entire program I deserve it
<SeanTAllen> so
<alexashka> another option I can see is using the (Cat | None) result in another try block and going let c = cat as Cat, to save the pattern matching bit, but that also seems ugh
<SeanTAllen> you could do
<SeanTAllen> create a primitive that calls exit
<SeanTAllen> and inside a try
<SeanTAllen> you can go blah(1) as Cat
<SeanTAllen> you'll need to return a Cat from your else in order to satisfy the compiler
<SeanTAllen> but it would be after your Unreachable() or whatever
<SeanTAllen> we use that pattern in Wallaroo
<SeanTAllen> Im particularlly fond of the error message
<SeanTAllen> given all the time i've tracked bugs down to "this can never happen" code
<alexashka> hm, would it be unreasoanble to ask for a gist example of this?
vaninwagen has joined #ponylang
<alexashka> most of what you've said flew right over my head :)
<alexashka> here are the cats that I have, it seems like a lot of work to do a simple thing
<alexashka> This is with the casting example included. It just feels verbose to need to do this.
<SeanTAllen> i dont really follow what you are doing there
<SeanTAllen> do you have a less contrived example
<alexashka> let me try :)
<SeanTAllen> here is how you would use unreachable: https://playground.ponylang.org/?gist=c87566bb3f5f67fffcf9da390992a4c1
<aturley> alexashka if i'm understanding you correctly there's nothing really in the pony language to make that easier.
<aturley> it looks like you're kind of hoping for something like typed exceptions, would that be correct?
<aturley> instead of having a general `else` on line 13 you'd like some way of differentiating between the out of range error and the `meow` error?
<alexashka> aturley: well yes, that seems like a very simple ask
<aturley> i mean ... simple is never simple :)
<alexashka> aturley: from what I can tell, I'd need to separate out any code that can blow up, to it's own try block
<aturley> at some level, yes.
<alexashka> aturley: but then there is no simple mechanism to go if a type is (Cat | None), to go 'if c is Cat then something', or 'guard c is Cat else return'
<alexashka> aturley: I'm coming from Swift, there are clean mechanisms to handle these very cases
<alexashka> aturley: so I'm a little surprised you can't pattern have multiple exceptions thrown within a single try block. It'd seem that should eitehr be prohibited by the language, or you could know which exception blew up. Otherwise it's a complete anti-pattern
<aturley> there's some overhead associated with typed exceptions.
<alexashka> aturley: Pony allows multiple exceptions within a try block, without a way to tell which. That should not be allowed, no?
<aturley> i don't know if i'd say "should not be allowed".
<SeanTAllen> there are also safety issues with typed exceptions
<SeanTAllen> pony doesn't have exceptions
<SeanTAllen> it has errors
<alexashka> aturley: unless you'd do the same thing for both exceptions, then it's ok I guess, but I think you'll almost always want to know which
<alexashka> for logging at the very least
<aturley> i guess what i'd say is that the language give you the tools to build your own solution to this problem that fits with the design of the system you're building.
<aturley> it makes a different set of tradeoffs from, say, swift.
<alexashka> aturley: it's not a show stopper, it's just very strange :)
<SeanTAllen> huh: jemc... did i never PR the rename from Exception to Error in the tutorial? i could have sworn i did that.
<aturley> alexashka keep in mind that speed and safety are two major goals of pony.
<alexashka> aturley: right, I imagine this has to do with async, and that it'll become clear why it is the way it is later on
<SeanTAllen> it doesnt alexashka: typed exceptions are much slower than `error` in pony
<SeanTAllen> additionally there are safety edge cases with typed exceptions
<alexashka> SeanTAllen: right, I don't know how often pony code relies on errors and try blocks. If it happens all the time, I imagine the overhead becomes important
<alexashka> SeanTAllen: but then again, if errors are commonplace, not knowing which one gets thrown within a try block is strange, ah well. I don't know :)
<aturley> alexashka again, i don't know if i'd say it is strange, but it is definitely a different set of design tradeoffs than other languages make.
<alexashka> aturley: ya, I'm really just complaining out loud. It'd be great if there was a universal language and/or obvious trade-offs, haha
<aturley> i get it.
jemc has quit [Read error: Connection reset by peer]
jemc has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
<SeanTAllen> alexashka: error is less expensive than exceptions in something like Java, but it still has a cost: https://www.ponylang.org/reference/pony-performance-cheatsheet/#avoid-error
_rck has quit [Ping timeout: 264 seconds]
khan has quit [Client Quit]
khan has joined #ponylang
<SeanTAllen> here's some issues that are problematic: https://github.com/ponylang/rfcs/pull/76#issuecomment-276335284
hmans has joined #ponylang
<hmans> \o/
<SeanTAllen> Getting hmans
<SeanTAllen> Greetings
<hmans> \\\o///
<aturley> that's a lot of arms
<aturley> hmans is a spider.
<hmans> We are legion.
<SeanTAllen> That was a mighty small message I managed to mess up
<hmans> No profiteroles, SeanTAllen
<hmans> *problem
<hmans> Hot damn
<SeanTAllen> Now you are just trying to make me feel better. Thanks.
<hmans> :)~
<jemc> alexashka: we discussed some time in the past about something similar to the `try` / `try!` that you mentioned
<hmans> Why did I come here? I'm off to bed. I will get all excited about Pony tomorrow. Night everyone.
<jemc> hmans: o/
<SeanTAllen> Good night
<alexashka> SeanTAllen: Sylvan seems to have the stance of 'either we have exhaustive pattern matching on errors, or nothign at all'. I'm not sure why partial matching is a bad idea still
<alexashka> SeanTAllen: most languages I've used have an 'otherwise' or 'default' clause, to make pattern matching total
<jemc> alexashka: we have `else` for making it total - am I missing something?
<alexashka> jemc: right, the context is 'I cant' tell which error got thrown'. So 'else' and nothign else but else :D
<alexashka> jemc: with partial pattern matching on errors, you'd handle IndexOutOfBounds one way, TimeOutError some other way, and all else, some third way
<jemc> I'm talking about `else` within a `match` block, not `else` within a `try` block
<jemc> coming back to something you said while I was briefly offline:
<alexashka> jemc: oh, i was talking about the try block, I think the match block is great :)
<jemc> > if errors are commonplace, not knowing which one gets thrown within a try block is strange
<jemc> yeah, so this is actually a crucial point, where working in pony turns the statement around on itself
<jemc> errors are anonymous, therefore I end up being *much* more careful about using functions that raise them, and I try like hell to not make my functions partial in the first place
<jemc> in other words, it forces errors to be a lot *less* commonplace
<jemc> this is one of several places where the language puts some pressure on you to adopt some (admittedly, opinionated) patterns with the goal of making your final code easier to reason about
<jemc> another example of this kind of pressure is on waiting - pony is designed to make you avoid blocking operations, which is kind of a pain, but once you've done it you're usually glad you did
<alexashka> jemc: well it sounds like you're smart, and you've come to a good design pattern regarding try blocks. I wonder if the solution is to document this in bold red caps, that folks, we cant' have multiple error-throwing functions within a single try block, unless you handle both errors exactly the same way
<jemc> yes, you've got the point exactly there in that statement - I agree we should do what we can to make this more clear to newcomers
<alexashka> jemc: the other pain point besides potentially shooting myself in the foot with this, is it makes getting an object out of an array and passing it to an error-able function very verbose
<alexashka> jemc: because I have to pattern match on the result of fetching the item, then another try block for the function call, ugh
<alexashka> jemc: I don't know how common of an operation this is, so in practice it may not be a big deal at all
<jemc> yeah, I definitely understand the pain - when I run into this kind of pain, my next step is to critically examine both sources of potential error and see if one or more can be removed or otherwise shifted
<alexashka> jemc: I am enjoying Pony quite a bit for the fact that it makes explicit, what is implicit in the other languages that I've used. Implicit error handling makes for spaghetti code down the line. Here I'm wondering about it one week in, so that's great
<jemc> I've come to really like the pressure the compiler puts on you to shift and mitigate errors at authoring time instead of at runtime - it makes me feel really confident about the code I end up with after finding ways to relieve the pressures
<jemc> SeanTAllen: I don't know if this is of any interest to Wallaroo, but this weekend I published an initial commit for a library with an alternative hash map implementation: https://github.com/jemc/pony-dict
<jemc> it does incremental rehashing when resizing the table instead of resizing all at once
brainproxy has joined #ponylang
<jemc> which lets you keep latencies more predictable
<jemc> it's an implementation taken from Redis
<jemc> next step is to add the "stateless" scanning feature from redis where you can iterate over a changing hash map something close to "at least once" semantics while the keyspace is changing - which was my main impetus for creating the library
<jemc> but I thought the latency thing might be more interesting/useful to you (if at all)
vaninwagen has quit [Quit: WeeChat 2.1]
<SeanTAllen> Thanks
<jemc> basic premise is that it holds both the old and the new hash table in memory, and rehashes a little bit at a time (or a lot, if you choose) each time you call `run_maintenance`, until the new hash table is fully populated and it destroys the old one
<jemc> and there's a parameter in `run_maintenance` that basically lets you control the number of slots that get migrated, effectively letting you set a limit on the latency of that call
SenasOzys has quit [Remote host closed the connection]
SenasOzys has joined #ponylang
khan has quit [Quit: khan]
khan has joined #ponylang
khan has quit [Client Quit]
khan has joined #ponylang
droman has quit [Quit: WeeChat 2.1]
SenasOzys__ has joined #ponylang
SenasOzys has quit [Remote host closed the connection]
gokr has quit [Ping timeout: 240 seconds]