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
<SamantazFox> How?
<SamantazFox> the compiler yells at me every time, because of data types
<FromGitter> <Blacksmoke16> have it accept a generic and use that?
<FromGitter> <Blacksmoke16> then could prob do like
<FromGitter> <Blacksmoke16> ```T.from_json pull ⏎ rescue e : JSON::ParseException ⏎ # Do something here ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=6113136d9484630efa300240]
<FromGitter> <Blacksmoke16> but if the value is invalid why not just let the user know that and they can fix it?
<FromGitter> <Blacksmoke16> technically yes, but that'll run into typing issues
<SamantazFox> heck
<FromGitter> <Blacksmoke16> `module Convert(T)`
<FromGitter> <Blacksmoke16> is the correct syntax
<SamantazFox> Blacksmoke16: in theory, an invalid value *shouldn't* happen. But as we're running large instance (thousand of users) the best idea is to not care about erroneous data and keep going.
<FromGitter> <Blacksmoke16> where do these values come from?
<SamantazFox> 3 places: the YAML config file, PREFS cookie (JSON) and URL parameters (URI)
<SamantazFox> and I want one place for all of that, that can fallback to already-initialized values if there is any error
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/bqq8 oh so apparently it'll use the default if it returns `nil`
<FromGitter> <Blacksmoke16> ofc would break if there was no default
<SamantazFox> everything has defaults
<FromGitter> <Blacksmoke16> so guess that would be fine then
<SamantazFox> That's my hope ^^
<SamantazFox> Blacksmoke16: why the `T.new value`, though?
<FromGitter> <Blacksmoke16> because thats what `from_json` calls internally
<SamantazFox> oh, okay
<FromGitter> <Blacksmoke16> stdlib types and types including `JSON::Serializable` define a `new` overload that accepts the pull parser
<SamantazFox> mmh, ok, I see
<SamantazFox> thanks
<SamantazFox> that's the "advanced" crystal part I wasn't ready for x)
ua_ has quit [Ping timeout: 258 seconds]
ur5us has joined #crystal-lang
ua_ has joined #crystal-lang
avane has quit [Ping timeout: 268 seconds]
avane_ has joined #crystal-lang
ua_ has quit [Ping timeout: 258 seconds]
ua_ has joined #crystal-lang
avane_ has quit [Ping timeout: 258 seconds]
avane has joined #crystal-lang
ua_ has quit [Excess Flood]
ua_ has joined #crystal-lang
ur5us has quit [Ping timeout: 258 seconds]
Vexatos_ has joined #crystal-lang
Vexatos has quit [Ping timeout: 240 seconds]
ur5us has joined #crystal-lang
ur5us_ has joined #crystal-lang
ur5us has quit [Read error: Connection reset by peer]
<FromGitter> <asterite> @straight-shoota exceptions that are not rescued by default was proposed and implemented a long time ago by waj. Sadly, mostly everyone rejected that idea. I don't know why.
<yxhuvud> I remember some long discussions in some issue around that.
ur5us_ has quit [Ping timeout: 248 seconds]
<raz> hmpf, vscode messed up their fullscreen mode on osx. the draw to linux is becoming stronger again...
<SamantazFox> raz: do it :D
<FromGitter> <Blacksmoke16> arch is calling
<FromGitter> <beta-ziliani> Regarding exceptions, we seriously need to think if we shouldn't move to a more idiomatic/functional way of dealing with them. We often confuse them for valid return values. A `raise` should only happen if the invariants/preconditions are violated. For valid execution path we ought to return a value. For instance, opening a file shouldn't throw an exception. It's not exceptional that a file isn't there
<FromGitter> ... with that name, or that it has different permissions. I find better to be explicit: `File | NotFound | NotPermitted`.
<FromGitter> <Blacksmoke16> 😬
<FromGitter> <Blacksmoke16> that sounds annoying
<FromGitter> <beta-ziliani> (the line between a valid return value and an exception is blurry though)
<FromGitter> <beta-ziliani> it can be, but it's easy to build support for having a similar structure to raise/rescue, with the benefit of not letting you forget about handling those cases
<FromGitter> <beta-ziliani> I'm not saying we must have this, I'm saying this is a path that's not explored enough
<FromGitter> <djberg96> Don't agree
<FromGitter> <djberg96> Having Golang pushed down my throat recently where I'm constantly checking `err` manually sucks.
<FromGitter> <djberg96> and 90% of the time it's not like i'm seeing what the failure was, just `return err`
<FromGitter> <djberg96> except when `err` is the wrong "type", then it becomes `err.Error` which is a joy to deal with
<FromGitter> <beta-ziliani> again, it's a matter of the infrastructure you have to deal with this. Crystal is not Go, and it has many advantages to build a wonderful API for dealing with errors. when I get some time I'll draft something to clarify what I mean (and to see if it's a reasonable approach).
<yxhuvud> I think it depends. Most cases when people open files and it doesn't exist, I'd say it is exceptional (like someone deleted the file when the program wasn't watching). But I could defintiely see a more result oriented api as well. Do we have to choose? :troll:
<yxhuvud> Though in case we want to introduce some cases where it needs to be handled (cough, checked exceptions), I'd suggest to simply use union types and have different types for the diffferent results. Why build structure when we already have what we need?
<raz> [NoRaise]
<raz> should solve it all
<raz> put it where you want to be specific about your errors. no exceptions past that point.
<raz> (well, new exceptions could be raised from there of course, but the caller of *that* method will know that everything has been handled)
<raz> i think that gives the best of both worlds. flexible exceptions as usual, but an easy way to switch to golang-style explicity where it's needed
<yxhuvud> BTW, I think parsing JSON would be a better example of something that should be handled - I can't think of a time where I've had to handle missing files, but JSON? it is broken and need to be handled all the time, either locally because someone mistyped it, or remote because some server 500s or whatever.
<raz> there's a bazillion things that nobody ever handles (other than at the top-level "rescue ex : Exception"). all types of I/O errors that "never happen" except when they do, string decoding errors (locales), etc.
<raz> these are the things that then only crop up later in production, when some user entered "illegal" chars as their username etc.
<raz> so yes, json parsing would def be one of the places where i'd put a [NoRaise]. i bet it will show me at least 3 exceptions that i never thought about before :)
<FromGitter> <riffraff169> you would think exceptions are exceptional, but in python, exceptions are optimized over if (at the c level), so checking if a file exists before trying to access it is less efficient than trying to access it anyway, and catching the exception
<FromGitter> <riffraff169> which seems counter intuitive to me, but it means that python is littered with exceptions all over the place, rather than proper checking to being with
<raz> i use exceptions for flow control even in crystal quite regularly. sometimes it's just more readable than nested conditionals. wouldn't want to lose that. just want a way little firewall to put in places where i really want to know at compile-time that no random exceptions from who-knows-where will surprise me at runtime.
<raz> -way
<FromGitter> <jwaldrip> Do fibers all run on a single thread? or do they use different cpus?
<FromGitter> <Blacksmoke16> they could do either, ofc requires you're running on MT mode
<FromGitter> <Blacksmoke16> there is a flag that makes them go on the same thread tho
<FromGitter> <jwaldrip> right, I see that
<FromGitter> <jwaldrip> but the default for spawn current_thread is false
<FromGitter> <Blacksmoke16> right, so it could go on any
<FromGitter> <jwaldrip> even when not in MT mode?
<yxhuvud> if not in mt mode, everything is on the same thread.
<FromGitter> <Blacksmoke16> no because when not using MT mode there is only 1 thread
<FromGitter> <jwaldrip> what are the known issues for MT mode?
<FromGitter> <Blacksmoke16> most of stdlib not being thread safe is prob the biggest
<FromGitter> <jwaldrip> not thread safe as in there is shared memory access?
<yxhuvud> I can't ever be threadsafe either. It is not as if we'd want all array or hash access to be behind locks - it would be way too heavy. There are no threadsafe variants for when it is needed though, which would be nice to have
<raz> would be nice if there was an MT mode where `current_thread` is true by default
<raz> so shards that know what they're doing can opt-in. and the rest doesn't blow up my app :p
<yxhuvud> Hmm. Yes, that could be cute to have. *adds to to-do-list*
<FromGitter> <jwaldrip> how does golang do it?
<FromGitter> <jwaldrip> Could we employ some sort of copy on write logic?
<FromGitter> <jwaldrip> I dont think we would have to copy anything from the main thread until its written to on the local thread
<SamantazFox> Re: threading: would be nice to have a way to spawn child processes
<SamantazFox> some simple thing only using unix or TCP sockets would be very nice
postmodern has joined #crystal-lang
postmodern has quit [Read error: Connection reset by peer]
<FromGitter> <jwaldrip> Is there a subclass of IO that can timeout if there is no writes?
<SamantazFox> why the...
<SamantazFox> Shouldn't that return "Enum"?
<riza> > puts x.bar.is_a?(Object) => true
<straight-shoota> `Enum` is the base type of an enum member's instance type
<straight-shoota> But there's no Enum in the metaclass hierarchy
<straight-shoota> >> module Foo; end; typeof(Foo)
<DeBot> straight-shoota: # => Class - https://carc.in/#/r/bqub
<straight-shoota> every type's metaclass is just Class, whether it's class, struct, module, enum
<straight-shoota> *every metaclass' type
<SamantazFox> ah, so `typeof` will never return the metaclass type?
ur5us_ has joined #crystal-lang
<straight-shoota> No, it returns the type. It's just Class.
ua_ has quit [Ping timeout: 268 seconds]
<SamantazFox> I *am* missing something, I'm sure.
<SamantazFox> ok, seems like a class can't inherit from more than one other?