ChanServ changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
notzmv has quit [Ping timeout: 256 seconds]
walez has quit [Ping timeout: 256 seconds]
ur5us has joined #crystal-lang
<FromGitter> <jrei:matrix.org> In Swift, there a `throws` keyword in the function declaration to indicate that it can throw an error. ⏎ By the way they are similar to returns, they don't involve stack unwinding
<FromGitter> <jrei:matrix.org> So it forces the user to catch the error inside functions that don't have the `throws` keyword. ⏎ However, I'm not sure it solves the "knowing all possible errors" issue, catch all errors still exist
<FromGitter> <moe:busyloop.net> i haven't used swift but that sounds like checked exceptions.
<FromGitter> <moe:busyloop.net> i don't want to litter all methods with `throws`, that gets old quick. ⏎ i only want to put it on chosen methods where i care. "the buck stops here".
<FromGitter> <moe:busyloop.net> shard developers would be advised to put `throws` on all their public methods. ⏎ but even if they don't, i can still put it on my method that calls them and get a nice list of all the exceptions ⏎ they either deliberately expose - or forgot to handle (e.g. if i see a sth like `IndexError` i'll file a github ticket - but at ⏎ least i'll know it's there and i can handle it for the time being)
<FromGitter> <moe:busyloop.net> as a bonus it would also be nicely backwards compatible. ⏎ your code will still compile even if it doesn't contain a single `throws` :)
<FromGitter> <moe:busyloop.net> would also match the crystal philosophy well i think. "exception inference" just like we have type inference. ⏎ allows me to be strict where i need to be and otherwise stays out of my way.
notzmv has joined #crystal-lang
wwalker has quit [Quit: leaving]
wwalker has joined #crystal-lang
ur5us has quit [Ping timeout: 256 seconds]
Sankalp has quit [Ping timeout: 240 seconds]
Sankalp has joined #crystal-lang
Sankalp has quit [Ping timeout: 260 seconds]
Sankalp has joined #crystal-lang
Sankalp has quit [Ping timeout: 256 seconds]
Sankalp has joined #crystal-lang
Sankalp has quit [Ping timeout: 268 seconds]
Sankalp has joined #crystal-lang
notzmv has quit [Ping timeout: 240 seconds]
Sankalp has quit [Ping timeout: 240 seconds]
Sankalp has joined #crystal-lang
greenbigfrog has quit [Ping timeout: 252 seconds]
greenbigfrog has joined #crystal-lang
notzmv has joined #crystal-lang
ur5us has joined #crystal-lang
walez has joined #crystal-lang
ur5us has quit [Ping timeout: 260 seconds]
<FromGitter> <jrei:matrix.org> It is not that different from methods that can return nil, with adding `nil` to the return type union. ⏎ In Crystal it could be like, say `String | Error`, or `String!`, compared to `String | Nil` and `String?`.
<FromGitter> <jrei:matrix.org> But yes if this is to add to all methods, it is pointless
<FromGitter> <jrei:matrix.org> Or maybe another return field, separated to the existing one for return values
<FromGitter> <jrei:matrix.org> I don't find much a difference between inferring return types and exceptions at the end
_ht has joined #crystal-lang
jmdaemon has quit [Ping timeout: 268 seconds]
<FromGitter> <moe:busyloop.net> hm yea, syntax-wise i think i'd keep it separate from return-types. ⏎ e.g.: ⏎ `def user(id : String) : User? throws DatabaseTimeoutError | SqlError` ⏎ ⏎ i.e. i don't want to allow that method to `return` SqlError, it's only allowed to `raise` it. ... [https://gitter.im/crystal-lang/crystal?at=6370d43715a3885c70ec2552]
<FromGitter> <moe:busyloop.net> would def also need a way to declare that a method is not allowed to throw anything. ⏎ perhaps just `throws Nil` or a magic keyword like `throws nothing`. ⏎ ⏎ (i'm not married to any specifics or the word "throws" anyway - maybe calling it `raises` would be clearer) [https://gitter.im/crystal-lang/crystal?at=6370d5222cb6570240262b33]
<FromGitter> <moe:busyloop.net> ideally, when the constraint is violated, the compiler would even tell me which line violates it; ⏎ `Line 123 in user.cr: db#query may raise IndexError but #user is only allowed to raise DatabaseTimeoutError | SqlError`
<FromGitter> <moe:busyloop.net> (but i understand i'm asking a lot here 😅)
<FromGitter> <jrei:matrix.org> Agreed, and would be one step to more safety
<FromGitter> <moe:busyloop.net> yup, i also agree with the comparison to return-types. ⏎ in practice exceptions are additional return types (outcomes) of a method. ⏎ currently we just have no way to restrict them like we have for return-types - not even one to easily find out ⏎ which of them may bubble up from the depths of the callstack. [https://gitter.im/crystal-lang/crystal?at=6370d82fb1a75964366d3b7d]
<FromGitter> <HertzDevil> syntax-wise there is already `@[Raises]`
<FromGitter> <HertzDevil> c++ used to have this too but it didn't actually prevent functions during compile-time from raising exceptions not declared
<FromGitter> <moe:busyloop.net> hm yea, but i feel like if we allow to actually restrict them then a syntax like `throws` would be nicer. ⏎ (annotation would be less readable imho - but hey if that gets me the feature, i won't complain)
<FromGitter> <moe:busyloop.net> i don't know of any language that actually has this exact feature (they may exist but i don't know one). ⏎ maybe it's really hard to implement, i have no idea. ⏎ or there is some logical problem with it that i'm not seeing. ⏎ so far, in my mind, it would be tremendously useful to make my code safer. [https://gitter.im/crystal-lang/crystal?at=6370da3f25ca105c88b43a23]
<FromGitter> <HertzDevil> all that's left in c++ is `noexcept` which still isn't a compile-time check, it merely calls `std::terminate` whenever something throws
<FromGitter> <moe:busyloop.net> so basically just a `rescue exit(1)`? 🤔
<FromGitter> <moe:busyloop.net> i've used a crystal shard that did pretty much that: https://github.com/arcage/crystal-email/issues/56 ⏎ it was not great, to say the least...
taupiqueur has joined #crystal-lang
taupiqueur has quit [Remote host closed the connection]
taupiqueur has joined #crystal-lang
<FromGitter> <HertzDevil> more accurately it raises `SIGABRT` and does not run `at_exit` stuffs
<FromGitter> <HertzDevil> back to crystal, the moment we do this, then either every `@[Raises]` will be littered with `ArgumentError | OverflowError | IndexError | NilAssertionError`, or we have to define checked vs unchecked exceptions
<FromGitter> <moe:busyloop.net> hm, not sure i would call that littered. if that's what a method can raise then it should be in the docs, right?
<FromGitter> <moe:busyloop.net> and people wouldn't have to declare them manually. ⏎ they would just start noticing them when i declare something like `throws MyCustomException` higher up the chain ⏎ and then see "oh, an OverflowError can also bubble up to here? i should handle that either here, or where it originates"
<FromGitter> <moe:busyloop.net> or in other words: all exceptions remain unchecked by default. you just get syntax to check them in places where you want to.
<FromGitter> <moe:busyloop.net> in many cases the actual handling of these will likely still look the same as it does today: with a catch-all `rescue` in the method ⏎ where e.g. `OverflowError` can happen. the new syntax would make it easier to not forget about doing that (which as of today probably happens a lot more often than anyone likes to admit ;))
<FromGitter> <moe:busyloop.net> to try another example: ⏎ when i use a shard then i'd expect that shard to not throw random IndexError or OverflowErrors at me. ⏎ so shard authors would be encouraged to narrow all their public methods to only `throw WellDefinedErrorA, WellDefinedErrorB`. ⏎ ⏎ but what happens below these public methods remains up to them. ... [https://gitter.im/crystal-
<FromGitter> ... lang/crystal?at=6370fa7eff5546644b425e90]
<FromGitter> <HertzDevil> that only gives a false sense of security because without "checked" exceptions library writers *will* do the `rescue exit(1)` thing just to satisfy the `@[Raises]` contract
<FromGitter> <HertzDevil> and crystal developers would simply not use them at this rate, because this doesn't promote their happiness
<FromGitter> <HertzDevil> a `@[Raises(NoReturn)]` would be interesting because that's the one that has considerable codegen impact, but the issue is the same: people will do `rescue exit(1)` again, unless they're working with the empty prelude
<FromGitter> <moe:busyloop.net> seems unlikely to me. ⏎ developers who don't care wouldn't put in the contracts to begin with, so there are no `rescue exit` to write for them. ⏎ ⏎ and i think there are quite a few crystal developers (and even more *potential* crystal developers) ⏎ who do care a lot about runtime safety and would draw happiness from being able to ensure it. [https://gitt
<FromGitter> ... er.im/crystal-lang/crystal?at=63710716473cf96648e3d16f]
<FromGitter> <moe:busyloop.net> seeing production apps crash from random `IndexError` or `OverflowError` definitely does not help happiness. ⏎ especially not when paired with the often useless backtraces (`???`). i've had some rather unpleasant conversation about ⏎ this in my org where i'm trying to promote crystal for production use.
<FromGitter> <moe:busyloop.net> (to be precise, i've had multiple occasions where production would crash with `IndexError`, following by a bunch of `???` without any filenames or line numbers. that's the digital equivalent of a middle finger...)
<FromGitter> <Blacksmoke16> i still think you should handle that by having a fallback that handles unexpected exceptions...
<FromGitter> <Blacksmoke16> but the `???` is prob because it was built with `--no-debug` and/or stripped
<FromGitter> <Blacksmoke16> afaik all that does is reduce binary size, so if thats not a big deal, prob could just keep debug symbols so you have them for when this happens
<FromGitter> <moe:busyloop.net> it was build with `--release --static` and not stripped.
<FromGitter> <Blacksmoke16> could maybe try adding an explicit `--debug` then?
<FromGitter> <moe:busyloop.net> i don't remember what i did back then (probably built without --release). ⏎ but this is a separate subject (although it also relates to production readyness)
<FromGitter> <moe:busyloop.net> > i still think you should handle that by having a fallback that handles unexpected exceptions... ⏎ ⏎ yes, that's what i do (and presumably everyone does). ⏎ doesn't change the fact that a missed `IndexError` will cause an error or even crash in production. ⏎ ... [https://gitter.im/crystal-lang/crystal?at=63710927a34b5112112c118f]
<FromGitter> <Blacksmoke16> yea for sure, but i also agree with hertzdevil in that it feels a bit annoying needing to do `throws IndexError` just because i do like `arr[0]`
<FromGitter> <Blacksmoke16> even in casese where i can know i wont raise
<FromGitter> <Blacksmoke16> kinda like that new ameba rule...not sure warning on `.not_nil!` provides any benefit...
<FromGitter> <Blacksmoke16> same idea with math, anytime you do `a + b`, do you need to mark that as being able to overlofw/
<FromGitter> <naqvis> > kinda like that new ameba rule...not sure warning on `.not_nil!` provides any benefit... ⏎ ⏎ that's really annoying and big pita imo. Without knowing the context, linter just throwing warnings as a general concept, isn't something good
<FromGitter> <moe:busyloop.net> as described above, you would pretty much never actually declare `throws IndexError`. ⏎ either you don't care in this method, then you simply don't declare a `throws` at all. ⏎ ⏎ or you do care, in which case you will handle it but most likely not let it bubble further. [https://gitter.im/crystal-lang/crystal?at=637109f715a3885c70ec84b6]
<FromGitter> <Blacksmoke16> ah gotcha 👍
<FromGitter> <Blacksmoke16> i didnt read all of it 😅 🙈
<FromGitter> <moe:busyloop.net> yea, that's the main difference between my proposal and the common "checked exceptions". ⏎ it's purely opt-in, so existing crystal code would not have to change at all.
<FromGitter> <Blacksmoke16> so pretty much yea, just says: ⏎ ⏎ > Avoid using `not_nil!`
<FromGitter> <naqvis> > @naqvis https://github.com/athena-framework/athena/actions/runs/3398343461/jobs/5651304890 ⏎ ⏎ 😃 , so i had it just disabled
<FromGitter> <moe:busyloop.net> that warning is indeed silly. there are plenty cases where you just can't avoid using it. that's why it's in the language, duh.
* FromGitter * moe:busyloop.net mumbles something "the boy who cried wolf" and its modern incarnation in npm; https://overreacted.io/npm-audit-broken-by-design/
<FromGitter> <Blacksmoke16> i replied to the PR, worst case ill just disable it i guss
DeBot has quit [Quit: Crystal IRC]
jhass has quit [Quit: Bye]
straight-shoota has quit [Quit: ZNC 1.8.2 - https://znc.in]
jhass has joined #crystal-lang
straight-shoota has joined #crystal-lang
taupiqueur has quit [Remote host closed the connection]
<FromGitter> <HertzDevil> > as described above, you would pretty much never actually declare `throws IndexError`. ⏎ > either you don't care in this method, then you simply don't declare a `throws` at all. ⏎ > ⏎ > or you do care, in which case you will handle it but most likely not let it bubble further. ⏎ ... [https://gitter.im/crystal-lang/crystal?at=63711cd725ca105c88b4a6d8]
<FromGitter> <HertzDevil> unless some exceptions are made "unchecked" in java's sense
<FromGitter> <HertzDevil> which will of course weaken every `@[Raises]` contract
DeBot has joined #crystal-lang
walez has quit [Ping timeout: 260 seconds]
<FromGitter> <moe:busyloop.net> well, in practice in the places where you put a `throws` you *do* care about all exceptions that can be raised. that's the whole point.
<FromGitter> <moe:busyloop.net> e.g. if i build a shard that exposes a `def send_email` then i'll want to make that `def send_email throws SendError`, so my caller knows what to expect. any other spurious `IndexError` and such i would obv handle and not throw at them.
<FromGitter> <moe:busyloop.net> but most method could still go without a `throws` and behave just like today. ⏎ it's just about narrowing down the stream of possible exceptions in strategic places. ⏎ because letting an `IndexError` bubble all the way to the top-level is usually a bug waiting to happen anyway.
walez has joined #crystal-lang
ur5us has joined #crystal-lang
_ht has quit [Remote host closed the connection]
walez has quit [Ping timeout: 260 seconds]
jmdaemon has joined #crystal-lang