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
nisanharamati has quit [Quit: Connection closed for inactivity]
samuell has quit [Quit: Leaving]
gokr has quit [Ping timeout: 248 seconds]
bpicolo has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
jemc has quit [Ping timeout: 260 seconds]
aturley has joined #ponylang
aturley has quit [Ping timeout: 240 seconds]
aturley has joined #ponylang
aturley has quit [Client Quit]
jemc has joined #ponylang
dipin has quit [Quit: dipin]
dipin has joined #ponylang
jemc has quit [Quit: WeeChat 1.9]
dipin has quit [Quit: dipin]
dipin has joined #ponylang
endformationage has quit [Quit: WeeChat 1.9.1]
user10032 has joined #ponylang
bitcrusher has quit [Ping timeout: 264 seconds]
user10032 has quit [Quit: Leaving]
Shamar has joined #ponylang
<Shamar> Hi I'm quite surprised by the exception handling in ponylang
<Shamar> in particular I can't see how error comunicate to the caller what went wrong
<Shamar> in the tutorial, the factorial example seems unusable: to understand the the issue was a negative input you should know the implementation and wrap that single call in a try else
<Shamar> but this has little advantage over checking a return value
Shamar has quit [Ping timeout: 255 seconds]
samuell has joined #ponylang
samuell has quit [Remote host closed the connection]
samuell has joined #ponylang
Shamar has joined #ponylang
Shamar_ has joined #ponylang
<Shamar_> Btw probably this is something worth explaining in the tutorial
Shamar has quit [Ping timeout: 248 seconds]
gokr has joined #ponylang
Shamar_ has quit [Quit: Bye]
_andre has joined #ponylang
gokr has quit [Ping timeout: 248 seconds]
Praetonus has joined #ponylang
Shamar has joined #ponylang
acarrico has quit [Ping timeout: 260 seconds]
lopoha has joined #ponylang
lopoha has quit [Client Quit]
lopoha has joined #ponylang
lopoha has quit [Ping timeout: 260 seconds]
acarrico has joined #ponylang
Shamar has quit [Quit: Lost terminal]
aturley has joined #ponylang
Codec_ has joined #ponylang
trevorriles has joined #ponylang
dipin has joined #ponylang
jemc has joined #ponylang
TheMouster has joined #ponylang
<TheMouster> Hi Sean, thanks for the help, by iterate from 'A' to 'D' I mean enumerate all the characters between 'A' and 'D' e.g. 'A','B','C','D'. Hmmm... that might be a hint, perhaps enumeration is what I need to look up.
gopherist has quit [Quit: WeeChat 1.9.1]
trevorriles has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
trevorriles has joined #ponylang
<SeanTAllen> so if I was doing that TheMouster, i would do it based on the ascii character code. between X and Y.
<SeanTAllen> Pony has no concept of a "char" really. Its a single character string. So for printing you'd either want to do ffi to @printf or create a single character string from the U8.
<jemc> well, you can use numeric literals
Codec_ has quit [Ping timeout: 260 seconds]
<jemc> something like `Range('A', 'D')`
<SeanTAllen> i'd never thought of doing that jemc
<SeanTAllen> i am too old and C
<TheMouster> Hi Sean, re 22:19, so would I, but I couldn't make it work. I'll try @jemc's idea.
<TheMouster> BTW: What's the difference between these two apply's http://playground.ponylang.org/?gist=83e56e62ef8f76f2f40370b4309a2690
<TheMouster> One works, the other does not.
<TheMouster> Off to look up Range. Thanks @jemc, @SeanTAllen.
<jemc> np
<jemc> (it's in the `collections` package)
<jemc> TheMouster: it's not a difference in the lines you pointed out
<jemc> it's a difference in the creation of `diamond` and `q`
<jemc> `env.out.print` will only accept a `String` as input
<jemc> `Diamond(size)` is sugar for `Diamond.create(size)`
<jemc> `Square()` is sugar for `Square.create().apply()`, which returns a `String` - if you want `Square.create()`, just use `Square` without any parentheses
<jemc> admittedly, that edge case is a bit confusing, but in general don't use parenthese for `create` sugar unless you have arguments to pass to it
<TheMouster> So, I'm becoming a bit lost. Isn't apply supposed to be a "default" function i.e. if you just supply the object, the apply function is what is run? At least I could have sworn that's what the documentation inferred.
<TheMouster> Unfortunately for me, it's time for bed. I've got a plasma donation tomorrow morning. Have a good evening and give blood. The life you save, might just be your own. Preaching complete :-).
dougmacdoug has joined #ponylang
TheMouster has quit [Ping timeout: 260 seconds]
dougmacdoug has quit [Quit: dougmacdoug]
Shamar has joined #ponylang
trevorriles has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
trevorriles has joined #ponylang
gokr has joined #ponylang
Shamar has quit [Ping timeout: 260 seconds]
<SeanTAllen> Good night TheMouster!
trevorriles has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
trevorriles has joined #ponylang
endformationage has joined #ponylang
nisanharamati has joined #ponylang
trevorriles has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
enilsen16 has joined #ponylang
enilsen16 has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
enilsen16 has joined #ponylang
jtarchie has quit [Quit: Page closed]
nerfpops2 has joined #ponylang
trevorriles has joined #ponylang
<nerfpops2> Does pony have something like async/await? Say I wanted to asynchronously execute a command in a db... How would I do this?
<jemc> the general answer for "execute something asynchronously" is to call a behaviour of an actor
<SeanTAllen> For executing in a db nerfpops2, you'd want to use the ASIO stuff we talked about yesterday
<SeanTAllen> ha jemc, i think we were going to give the same answer, just in reverse
<jemc> but pony doesn't have anything like "await" - pony actors respond to input, they don't wait around for things
gokr has quit [Ping timeout: 255 seconds]
<nerfpops2> cool. I got it working, and it is indeed super simple!
<jemc> it's a bit of a subtle conceptual difference, but it's important
<jemc> for "getting the results of an asynchronous action", there are a few patterns, but they're mostly variants of "I'll call you back"
<nerfpops2> it would be nice to be able to just await db.query("select ..") but that's probably a lot easier said than done
<jemc> in practice, promises are often a good choice, sometimes callbacks are preferable, and sometimes you may want to give a more complex "notify" object, like many of the standard library "event source" actors do
<jemc> for your example, probably a promise is the best place to start
<jemc> `db.query("select ..").next({(result) => ... })`
<nerfpops2> it's kinda like javascript in the "old" days, but it's not a bad pattern ;)
nerfpops2 has quit [Quit: Page closed]
<jemc> `await` is one of those things that sounds really nice, but there are some issues that make it scary/problematic from pony devs' perspectives:
<jemc> mainly, that while that `await` is waiting, you'd basically be doing one of two things:
<jemc> 1) the actor isn't accepting any more messages, and is just queueing them up for later - you've introduced a subtle but potentially very performance-impacting bottleneck
<jemc> 2) the actor is accepting and processing other messages - actor behaviours are no longer atomic transactions over the actor's state, so you lose the ability to treat them like transactions when reasoning about your program and data races
<jemc> neither one is really very nice for the goals of pony
<jemc> it could still theoretically be used judiciously, but both lead to a world where it's harder to reason about the correctness or performance of your program
dipin has quit [Quit: dipin]
Xe has quit [Ping timeout: 246 seconds]
bpicolo has joined #ponylang
bpicolo has quit [Client Quit]
Xe has joined #ponylang
<nerfpops> that sounds like some serious issues await would introduce. it's also not an issue for that I'm trying to do now, and for programs where async/await would be used a lot, one could combine that with pony in some way
<SeanTAllen> ill try to dig up the Joe Duffy posts where he says that having async/await in midori turned out to be a fatal flaw that he wished he hadn't done. That it seems convenient at first but has insidious long term effects.
<SeanTAllen> A lot of Pony's decisions have been influenced by Sylvan's discussions with Joe/learning from midori.
<SeanTAllen> this one covers the "where they ended up at" without an "actual await"
<nerfpops> thanks i'll check it out
<nerfpops> I'm trying to teach my apprentice pony so I'm glad you guys are around to help me understand it :D
<SeanTAllen> you're welcome
enilsen16 has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<nerfpops> so when postgres notifies the listener, libpq returns a struct: typedef struct pgNotify { char* relname; int be_pid; char* extra }
<nerfpops> in pony I have struct with var relname: Pointer[U8] = Pointer and var extra: Pointer[U8] = Pointer[U8] ... I can print the relname when using String.from_cstring but the same code segfaults when using extra. I have tested in the C-version and that works. What am I doing wrong?
<jemc> nerfpops: can you make a gist with what you have so far?
<nerfpops> just a sec
<jemc> and give a link to the C example or docs for the library that you're following?
<nerfpops> the part that fails is "_env.out.write(String.from_cstring(notify.extra).string())" ... when using notify.relname instead it works
<jemc> nerfpops: I think your struct fields are in the wrong order
<jemc> your struct fields need to be in the same order as the typedef
<nerfpops> and that was indeed the problem. good to know. thanks!
bpicolo has joined #ponylang
<jemc> yeah, so in C (and in Pony), the order of struct fields is important because your struct instance is just a chunk of memory, and the fields tell the program which offset to look into to reach a particular field of that chunk
Nikesh has joined #ponylang
<Nikesh> Is there a typo, or a 'but' missing from the 'Simplicity' part of the Pony Philosophy?
<Nikesh> It reads contradictory to me
<Nikesh> > Simplicity. Simplicity can be sacrificed for performance. It is more important for the interface to be simple than the implementation. The faster the programmer can get stuff done, the better. It's ok to make things a bit harder on the programmer to improve performance, but it's more important to make things easier on the programmer than it is to make things easier on the language/runtime.
<Nikesh> Simplicity can't* be sacrificed for performance? Or... But* it is more important...?
Nikesh has quit [Quit: Lost terminal]
xllndr has joined #ponylang
_andre has quit [Quit: leaving]
Candle has quit [Ping timeout: 246 seconds]
<jemc> Nikesh: I'm not seeing the contradiction, but that may be just me
<SeanTAllen> I'm confused
<jemc> the point of the snippet is to talk about why simplicity is important, and what exactly we mean when we refer to simplicity, but to make sure to stress that ultimately, making things less simple for performance reasons can be a valid choice
Shamar has joined #ponylang
<Shamar> hi
atk has quit [Quit: Well this is unexpected.]
atk has joined #ponylang
<Shamar> I'd like to have a clarification about pony's exception handling: in the tutorial I've read that exception has no type
<Shamar> and as far as i can see they also carry no value
<Shamar> so how the caller can know what went wrong?
trevorriles has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<jemc> Shamar: welcome!
<Shamar> hi jemc, thanks :-)
<jemc> actually, we're in the midst of trying to clear up some confusion in the tutorial by avoiding the word "exception" because of some of the extra baggage this carries from other languages
<jemc> so, you're interpreting it - an `error` in Pony carries no type, value, or backtrace - it just unwinds the stack up to the nearest `try` block
<jemc> the answer to "how can the caller know what went wrong" is only "from context"
<jemc> the convention is that an error-ing function should have only one failure mode, or have a different way of communicating the information when more is needed
<jemc> this is one reason we borrow the term "partial function" from mathematics
<jemc> in practice, this "one failure mode" approach works better than you may expect, given that pony strongly encourages you to catch and appropriately handle all errors very close to the point where they are raised
<jemc> for example, when I'm accessing the value associated with a key in a map, and an `error` is raised, the documentation tells me that this `error` means the key isn't in the map
<jemc> and I can handle that with logic appropriate to my application
<Shamar> but this is not much different than checking return codes
<Shamar> you cannot do several operation and than handle exceptions
<jemc> right, it would be an anti-pattern to do several operations that can fail in different ways in the same `try` block
<Shamar> you must call function, catch error, call function2, catch error and so on
<jemc> in practice, functions that can raise an error are much rarer in Pony than in other languages
<jemc> because of the language pressure to handle errors as close to the source as possible
<jemc> I think you're right that there are some similarities to using return values for errors, but I think there are also some important differences
<jemc> with regard to how control flow works
<Shamar> can you explain?
<Shamar> I have nothing against checking return values (I'm a C programmer, among other things)
<jemc> well, unwinding-to-the-nearest-try-block is different from check-the-return-value both on the execution level, and on the visual/ergonomic level
<Shamar> nor I have nothing against exceptions (I'm also a C# and Java programmer...)
<jemc> on the visual/ergonomic level, it's an implied jump straight to the `else` block without having to explicitly say "if the operation failed, then do this"
<jemc> which means I can do something like `try my_map(key)?.string() else "" end`
<jemc> the `?` marks points that can cause a jump to the `else` block, but I can continue on with my logic that's chained onto that result without interrupting the ergonomic flow ofit
nisanharamati has quit [Quit: Connection closed for inactivity]
<jemc> however, if you like the return value pattern, or if you need to return extra information about the error, you can definitely use that pattern in pony
<jemc> something like `match try_something() | ErrorFoo => "foo went wrong" | ErrorBar => "bar is bad" ... end`
<Shamar> the problem is that, if the standard library use the error machinery, everybody else is doomed to try/else them...
<jemc> where your return value is something like `(MyResultType | ErrorFoo | ErrorBar)`
<Shamar> yes this seems better to my untrained eye
<jemc> Shamar: the standard library only uses the `try/else` where there is only one failure mode
<jemc> things like opening a file use the return value approach to indicate the various kinds of errors that can result
<jemc> as long the function author didn't conflate multiple different error reasons into the same partial function, you already know everything you need to know about the error when use `try/else`
<jemc> like in my example above, fetching values by key from a map - jumping to the `else` block means the key was missing from the map - it will never mean anything else
<Shamar> i see...
<Shamar> does the compiler prevent a function to conflate multiple errors in a single error call?
<Shamar> for example: can I have more than one error in a function?
<jemc> no, the compiler doesn't prevent this because it can't know that the two errors *mean* different things just because they are two different points in the code
<jemc> like, in an optimized `Map.apply` implementation you may have multiple places where an error can be raised, but all of those places *mean* the same thing to the caller - "the key is missing from the map"
<Shamar> maybe it's just a bias from other languages, but it seems a bit unsafe: different errors could unwind the stack from different libraries... and since the receiver has no idea of what happened it might do the wrong thing
<jemc> your fear is valid - I think ultimately it's a matter of discipline and a rejection of libraries that conflate different error meanings
<jemc> in practice, it doesn't seem to come up that much
<jemc> the language makes it "feel dirty" to mix errors like that, so libaries end up doing a pretty good job about this aspect
<Shamar> maybe removing the error machinery would remove the risk making the language safer
<jemc> I don't think it's worth the loss of that feature
<jemc> `try/else` has the ergonomic advantages I mentioned above, and it also has different performance characteristics on the micro level
bpicolo has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<jemc> SeanTAllen has written a little bit about when `try/else` is more performant than return type matching, and when it's the other way around
<jemc> they've found that those little differences in performance add up significantly when working on a latency-critical application like Wallaroo
samuell has quit [Remote host closed the connection]
<SeanTAllen> Shamar: the "written a little bit about" that jemc mentioned: https://www.ponylang.org/reference/pony-performance-cheatsheet/
<Shamar> SeanTAllen: really interesting thanks
<Shamar> still error breaks Pony's safety a little (even for a performance advantage)...
<Shamar> also how can you know if error is better than a union type in the standard library?
<Shamar> how many times the key is not in the collection?
<Shamar> s/collection/map
enilsen16 has joined #ponylang
nisanharamati has joined #ponylang
<Shamar> maybe you have eg two map interfaces? one with lookups as partial functions and one with lookups returning a union type?
Candle has joined #ponylang
<jemc> Shamar: I think it's overstating the issue a bit to say that error "breaks safety" - but that's just my take
<jemc> regarding the "two interfaces" point - we're definitely open to tuning the interface and providing new functions where the performance characteristics of the current alternative are causing problems for real users
<jemc> for example, that's how `Map.upsert` was born
xllndr has quit [Quit: Leaving]
<jemc> also, more to the point you made, we have `Map.get_or_else` which would serve that purpose
<Shamar> thanks for your explaination jemc... to get a feel of the language I definitely need to give it a try
Amun_Ra has quit [Ping timeout: 260 seconds]
Amun_Ra has joined #ponylang
bpicolo has joined #ponylang
bpicolo has quit [Client Quit]
enilsen16 has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
gokr has joined #ponylang
Shamar has quit [Quit: Lost terminal]
gokr has quit [Ping timeout: 248 seconds]