SamantazFox has quit [Killed (NickServ (GHOST command used by SamantazFox_))]
SamantazFox_ has joined #crystal-lang
HumanG33k has quit [Ping timeout: 272 seconds]
human_g33k has joined #crystal-lang
ur5us__ has joined #crystal-lang
ur5us__ is now known as ur5us
ua_ has quit [Read error: Connection reset by peer]
brokkoli_origin has joined #crystal-lang
brokkoli_origin has quit [Quit: Leaving]
ua_ has joined #crystal-lang
ur5us has quit [Ping timeout: 272 seconds]
ua_ has quit [Excess Flood]
ua_ has joined #crystal-lang
ua_ has quit [Excess Flood]
ua_ has joined #crystal-lang
hightower4 has joined #crystal-lang
<hightower4>
Hey do I see/remember it right that when capturing &blocks in method defs, the proc can't be optional? Like, in `def x(&bl : Proc(Nil))`, the Proc(Nil) can't be made optional with Proc(Nil)? ?
<raz>
man, clear orm & crystal are a joy to work with. takes some time to rattle things into place, but then nested transactions, jsonb, pg arrays, custom pg func's, squeaky clean specs with rollback etc. all works flawlessly. having implemented this stuff in a bunch of languages the crystal impl is by far my fav now.
<FromGitter>
<Blacksmoke16> now just pair that with athena and get magically (de)serialization/validation of your models 😉
<FromGitter>
<Blacksmoke16> i'm open to feedback but you actually have to bring things up
<raz>
well it's not bad, for big apps/teams that can be just right.
<FromGitter>
<Blacksmoke16> the aliases should help with the verbosity of the types, but thats moreso a product of Crystal
<raz>
yea, verbosity was more an alias for all the contextual knowledge you need to get started beyond the basics
<raz>
i don't think there's really a way to "fix" that easily. there's just a new class/abstraction to learn at every step.
<FromGitter>
<Blacksmoke16> every framework is going to have that to a degree
<raz>
yup. grip = small degree. athena = full degree ;)
<raz>
each has its place
<raz>
it's great that crystal has both
<FromGitter>
<Blacksmoke16> also prob doesnt help it doesnt follow the `HTTP::Handler` middleware approach all the others do
<FromGitter>
<Blacksmoke16> i imagine thats the main area thats takes some learning
<raz>
yup, and arguably something like lucky is even more opaque / magical
<raz>
at least in athena all the springs and cogs are out in plain sight
<FromGitter>
<Blacksmoke16> lucky really likes their macros
<raz>
yup, guess it counts as a third philosophy. athena makes you write like java. lucky like lucky. and well, grip is pretty much just crystal with some helpers.
<FromGitter>
<Blacksmoke16> ehh i wouldnt directly compare it to java just because it makes you use interfaces
<FromGitter>
<Blacksmoke16> thats a good design principle regardless ;P
<raz>
well, if someone comes from java-spring i'd send them straight to athena. approach is pretty similar i think, not in a bad way :)
<raz>
inject all them dependencies! ;)
<FromGitter>
<Blacksmoke16> im still curious how lucky handles that kind of stuff
<FromGitter>
<Blacksmoke16> grip just doesnt afaik, which is probably fine given its purpose
<raz>
i've never used lucky enough to really know. it's probably great when you want to build your app exactly the lucky-way. but custom-everything down to the orm always makes me feel a bit uneasy (there's always some detail that i want different, and usually the claim "works with any orm" only means that in principle it does - but hardly anyone ever tries it ;))
<FromGitter>
<eliasjpr> Question: Ruby has `Raise` and `Fail` keywords, Crystal has `raise`. While ruby makes no distinctive difference between raise and fail implementation. I wonder if there is an opportunity to implement fail in Crystal as in Panic in go? @straight-shoota @asterite
<FromGitter>
<Blacksmoke16> there was a forum thread about that iirc
<straight-shoota>
error is just a return value. There's nothing special about it in the language.
<straight-shoota>
And panic is just like raise. And it's possible to recover from a panic, using the recover keyword. So that's like rescue in Crystal/Ruby
<FromGitter>
<eliasjpr> Go’s approach makes it easy to see which functions return errors and to handle them using the same language constructs employed for any other, non-error tasks
<straight-shoota>
Yeah. You can actually do the same in Crystal if you want.
<straight-shoota>
Maybe it could even be better with union types *shrug*
<FromGitter>
<eliasjpr> I guess one can have a Error struct that does not inherit from Exception and raise it
<straight-shoota>
If you want a struct, yes. If you're happy with a class, you can just return an Exception instance
<FromGitter>
<eliasjpr> Exception builds stack traces, while the Error struct/class does not. Am I assuming correct?
<FromGitter>
<eliasjpr> I guess raise always builds a stack trace
<FromGitter>
<eliasjpr> In regards to Panic it is very similar to Raise
<straight-shoota>
A callstack is only created when raised
<straight-shoota>
You can even disable that by assigning an empty callstack before that
<FromGitter>
<eliasjpr> Really!!!
<FromGitter>
<eliasjpr> thats neat
<FromGitter>
<eliasjpr> should that be an overload `raise` method?
<straight-shoota>
yeah, either a custom raise method or a custom exception class that assigns an empty array on initialization
<FromGitter>
<eliasjpr> maybe would be good to add an overload raise(exception : Exception, callstack = true)
<FromGitter>
<eliasjpr> for usability/visibility
<straight-shoota>
I don't think this is really a great idea though
<straight-shoota>
You gain a little speed but lose debug information
<FromGitter>
<eliasjpr> well this can be something that probable should be turned on at the process level
<straight-shoota>
For signalling expected application errors this might be fine, but everything that's out of a normal state, you'd be happy to have a callstack when debugging
<FromGitter>
<eliasjpr> like we do with logging
<FromGitter>
<eliasjpr> DEBUG=true
<straight-shoota>
yes, that should work
hightower2 has joined #crystal-lang
<FromGitter>
<eliasjpr> also wouldn't be more safe for the program to not default to print/build callstack traces for prod apps
<straight-shoota>
But if you really want to skip that for performance reasons, I would go the entire way and not use raise at all
hexology- is now known as hexology
<FromGitter>
<eliasjpr> I think security is a good reason
<straight-shoota>
What kind of security?
<FromGitter>
<eliasjpr> a lot of hacks happens because exposure of the call stack
<FromGitter>
<eliasjpr> Error values do not expose the call stack
<straight-shoota>
But where/how is the call stack exposed?
<FromGitter>
<eliasjpr> in the logs, io etc no?
<straight-shoota>
But that could be handled at that point: don't print the callstack to the logs if you don't want that
<FromGitter>
<eliasjpr> maybe I don't understand enough 😅
<straight-shoota>
Raising the exception just collects the callstack. It doesn't publish it anywhere, it's just attached to the exception object.
<straight-shoota>
Of course, you can't accidentally disclose something that isn't even there. And if you don't use the callstack at all, it's probably useful to just skip creating it.
<straight-shoota>
But callstacks are just so important for hunting bugs.
<straight-shoota>
If something goes wrong, you need to know where and how the program got there
<FromGitter>
<eliasjpr> Would you agree then maybe is worth to have `raise(exception : Exception, callstack: true)`?
<straight-shoota>
I don't see a use case for that in stdlib
<FromGitter>
<eliasjpr> Agree about the bugs and callstack, but only then is needed
<straight-shoota>
If you want that behaviour, you can just add the method in your codebase
<FromGitter>
<eliasjpr> Got it. I was just wondering if it was worth to have and explore the thought
<FromGitter>
<eliasjpr> Thanks it is always good to cross check. Thank you for the clarification
<straight-shoota>
Sure =)
<straight-shoota>
Exploring thoughts is always helpful
<straight-shoota>
I'm just stating my opinion, maybe others would want to have that in stdlib...
<FromGitter>
<eliasjpr> yeah, hopefully it will inspire a conversation at the least
<raz>
stdlib needs `@[NoRaise]`. that's what stdlib needs, yup yup. for full error control bliss. i'd love for it to be called "@[GoLangMode]" but that probably violates some trademark.
yxhuvud has quit [Read error: Connection reset by peer]
yxhuvud has joined #crystal-lang
avane has joined #crystal-lang
notzmv has quit [Ping timeout: 248 seconds]
notzmv has joined #crystal-lang
<FromGitter>
<asterite> There's abort and exit in Crystal. I'm not sure non recoverable exceptions are desireable
<yxhuvud>
I could see a use for a methodthat kill the current fiber, in a controlled way. It could be nice for implementing cancellation.
<yxhuvud>
regardless of discussion on if outside forceful cancellation should be a thing.
<yxhuvud>
And that is basically a nonrecoverable exception, even if it perhaps doesn't take the same code paths.
<raz>
shouldn't it be Fiber#raise (to raise an exception inside the fiber)? hard stopping a fiber from the outside at a random point without allowing it to cleanup sounds like a last-resort kinda thing
<yxhuvud>
shrug. It doesn't need to come from the outside.
hightower2 has quit [Remote host closed the connection]
<raz>
hm, but if a fiber wants to stop itself, it could just do the same - raise an exception?
* raz
scratches head
ur5us has joined #crystal-lang
<straight-shoota>
@asterite I don't think we need non-recoverable exceptions either. But exception that are not rescued by a default `rescue` might be nice (i.e. you can recover but you need to explicitly ask for that).
<FromGitter>
<Blacksmoke16> couldn't that just be another type
<FromGitter>
<Blacksmoke16> like `MyError < Error` wouldn't be caught by `rescue e : Exception` but would if you did `rescue e : Error` or `rescue e : Raisable`
<FromGitter>
<riffraff169> say, i have an expression where a = b or c, like the c trinary: `a = (x < 0) ? b : c`
<FromGitter>
<riffraff169> is there an idiom for that? you can do an if/else, so i was doing a = if b.....
<FromGitter>
<riffraff169> or is there a better way....like this:
<FromGitter>
<Blacksmoke16> whats wrong with `a = (x < 0) ? b : c`?
<straight-shoota>
@Blacksmoke16 Yes, exactly. It would just need an exception type above the one that's the default for an untyped `raise`
<FromGitter>
<riffraff169> ah so crystal does have the trinary, ill use that
<FromGitter>
<riffraff169> must have missed it
<FromGitter>
<Blacksmoke16> ternary but yes ;P
<FromGitter>
<riffraff169> ah yes that too
<FromGitter>
<riffraff169> cool, that reads better to me than assigning the result of an if/else to a var
<FromGitter>
<Blacksmoke16> @straight-shoota thats exactly what PHP did as well
<FromGitter>
<Blacksmoke16> `Throwable` is implemented by `Error` and `Exception`
<FromGitter>
<riffraff169> which worked, but playground indents it wrong
<straight-shoota>
Yeah, that's in part modeled after the Java exception hierarchy IIRC
<FromGitter>
<Blacksmoke16> looks like its exactly the same ha
<FromGitter>
<Blacksmoke16> least the top most ones
ua_ has quit [Ping timeout: 248 seconds]
<SamantazFox>
Hello!
<SamantazFox>
I'm playing with annotations (expecially JSON::Field() and YAML::Field() converters) and I've been looking around for hours at that problem
<SamantazFox>
is there a way to handle nicely the conversion of JSON/YAML to enums (so {"theme": "Dark"} gives Theme::Dark), without having to re-define a full converter each time to handle bad data (e.g {"theme": "invalid"})?
ua_ has joined #crystal-lang
<FromGitter>
<Blacksmoke16> im pretty sure you can just type that field as the enum and it should just work
<SamantazFox>
Blacksmoke16, ok, so it works fine with JSON, but not YAML