jhass changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Crystal 0.35.1 | 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
deavmi has quit [Ping timeout: 265 seconds]
deavmi has joined #crystal-lang
<FromGitter> <Blacksmoke16> added a new feature to my serializer
<FromGitter> <Blacksmoke16> (not released yet) ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f14eaba64b6213da14b22d3]
<FromGitter> <mixflame> is there anything in crystal like ruby chronic
<FromGitter> <Blacksmoke16> mm not that i can think of
<FromGitter> <mixflame> ok
<FromGitter> <mixflame> I will make ban length in seconds
<FromGitter> <mixflame> today I implemented admin layer delete and brush size indicator
<FromGitter> <Blacksmoke16> what do you need to do with time?
<FromGitter> <Blacksmoke16> parse string like `today` into a `Time` instance?
<FromGitter> <mixflame> ban a user for a length of time
<FromGitter> <mixflame> yeah I was gonna allow like "5m" for 5 minutes
<FromGitter> <mixflame> "1h" 1 hour
<FromGitter> <Blacksmoke16> yea i didnt see any on the awesome crystal list either
<FromGitter> <mixflame> yeah
<FromGitter> <mixflame> its def somethin to think about for crystal
<FromGitter> <mixflame> i know thats a popular ruby gem
<FromGitter> <silasb> Hey guys/gals, forgive me but I'm new to Crystal. I'm trying to find out how to tell if a HTTP connection has been disconnected/terminated on the client end. I was hoping that I could use `response.closed?` but it doesn't appear to return `true` when my curl client disconnects. For the record, I'm working on server-sent events.
<FromGitter> <Blacksmoke16> Yea idt that's the right method
<FromGitter> <Blacksmoke16> That would return true after you call .close on the response
<FromGitter> <Blacksmoke16> However I'm not sure how you would determine that
<FromGitter> <silasb> If the client disconnects the socket on their end, either by closing it early or by getting interrupted, the only method that I can think of is catching the error when I try writing to the response.
<FromGitter> <Blacksmoke16> Does response.output.closed? Work?
<FromGitter> <Blacksmoke16> NVM, that's what normal .closed? d
<FromGitter> <Blacksmoke16> Does
<FromGitter> <silasb> I think you'd be able to get to the IO object of the request/socket to see if it's been closed. I've looked around and couldn't find out a way to do it.
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 260 seconds]
<FromGitter> <Blacksmoke16> not sure
<FromGitter> <Blacksmoke16> fwiw if you're using `HTTP::Server`, that should gracefully handle this case
rocx has quit [Ping timeout: 260 seconds]
rocx has joined #crystal-lang
sorcus has quit [Ping timeout: 272 seconds]
sorcus has joined #crystal-lang
rocx has quit [Ping timeout: 260 seconds]
<FromGitter> <wyhaines> Re detecting disconnection from the client, you can't know immediately when a client disconnects a TCP connection. That's part of the fun of TCP. ⏎ ⏎ You aren't even guaranteed to get an error when you write to the now-disconnected socket. From the POV of your code, it may write just fine, for a little while.
<FromGitter> <alexherbo2> What is the type when we want return or take a function for currying?
Vexatos has quit [Quit: ZNC Quit]
Vexatos has joined #crystal-lang
oddp has joined #crystal-lang
Human_G33k has quit [Remote host closed the connection]
oddp has quit [*.net *.split]
coderobe has quit [*.net *.split]
duane has quit [*.net *.split]
ua_ has quit [*.net *.split]
DTZUZU has quit [*.net *.split]
oddp has joined #crystal-lang
duane has joined #crystal-lang
coderobe has joined #crystal-lang
ua_ has joined #crystal-lang
DTZUZU has joined #crystal-lang
coderobe has quit [Max SendQ exceeded]
DTZUZU has quit [Max SendQ exceeded]
DTZUZU has joined #crystal-lang
coderobe has joined #crystal-lang
<FromGitter> <wyhaines> Is there a time/date parser hiding somewhere that provides a functional equivalent to Ruby's Time/Date parsing capabilities? I have been hunting but am not really finding anything.
<FromGitter> <ImAHopelessDev_gitlab> hai
<FromGitter> <j8r> hail @ImAHopelessDev_gitlab
<FromGitter> <ImAHopelessDev_gitlab> Hi @j8r how are you, what crystal project have you been working on?
<FromGitter> <j8r> I was in vacation last weeks, I need to go back to my game :)
<FromGitter> <wyhaines> @j8r I am aware of the main Time class, but it appears to lack Ruby's date/time parsing capabilites. ⏎ ⏎ Most specifically, I want to be able to pass in an arbitrary date/time string, and have a reasonable expectation that the library is going to figure it out and give me something useful after parsing. ⏎ ⏎ With `Time#parse`, I have to give it a specific format, and that format is all that it's going
<FromGitter> <Blacksmoke16> if you scroll up someone else was asking about that
<FromGitter> <Blacksmoke16> tl;dr I don't know of any
<FromGitter> <wyhaines> @Blacksmoke16 OK. Well, the positive there is that at least I didn't overlook anything too obvious when I was hunting for something. :)
<FromGitter> <ImAHopelessDev_gitlab> can you use just a timestamp?
<FromGitter> <asterite> @wyhaines I wouldn't use `Date.parse` in my life. The times I used it it was a disaster. For example "1/2/2020" will parse to February 1st, 2020, but in the US that would actually be January 2nd, 2020. It's always best to force a format and use that instead of trying to figure out things like that
<FromGitter> <Blacksmoke16> actually @wyhaines @mixflame https://github.com/krthr/ms.cr parses the string into milliseconds tho
<FromGitter> <Blacksmoke16> granted i never used it so i cant speak to how/if it still works
<FromGitter> <naqvis> Agree with what Ary said, but there are cases where one can't avoid parsing the dates, the use case which comes to mind is web scrappers or some similar tools, where they scan through variety of data, and apply different mechanism to parse the dates. ⏎ ⏎ @wyhaines below is what i can think of one possible way to try to parse dates in few different formats (granted this is not battle-tested :P) ⏎ ⏎
<FromGitter> ... ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f159022a874ff08d28963ad]
rocx has joined #crystal-lang
<FromGitter> <wyhaines> @asterite It's only best to force a time format if one has the freedom to do so. I'm quite aware of the limitations of the Ruby approach with regard to the invariably ambiguous representations, and the default preference for non-US interpretation in the case of ambiguity. However, on the plus side, the parser allows me to throw anything at it, and if it can figure it out, it will. ⏎ ⏎ I have data files
<FromGitter> ... that I have to parse for financial information. These data files are ultimately created by hand by somebody every day. And while they are usually consistent, sometimes they aren't. The Ruby code that I have for dealing with similar problems generally just-works. They can change minor things about how the dates are represented, a ... [https://gitter.im/crystal-lang/crystal?at=5f1591e3a874ff08d289694e]
<FromGitter> <j8r> @naqvis too bad there is no `parse?` :(
<FromGitter> <j8r> @wyhaines I think a shard doing this would be better
<FromGitter> <j8r> the stdlib provides the sane building blocks to do an opinionated library that can guess the time
<FromGitter> <naqvis> @j8r yeah, it should be part of stdlib to avoid exception catching
<FromGitter> <j8r> opinionated because it will decide if `1/2/2020`, like @asterite said, is 1st Feb or 2nd Jan
<yxhuvud> I'm slightly surprised there is no strptime though.
<yxhuvud> ah, it is the parse method on Time::Format.
<FromGitter> <wyhaines> @j8r I was just hoping that I wasn't going to have to implement it myself. Oh well. That's life. Zo is het leven.
<FromGitter> <Blacksmoke16> ☝️ July 20, 2020 8:32 AM (https://gitter.im/crystal-lang/crystal?at=5f158ec364b6213da14cca23)
<FromGitter> <wyhaines> @Blacksmoke16 It looks like it works with intervals, but not actual time/date strings.
<FromGitter> <Blacksmoke16> ah fair
chachasmooth has joined #crystal-lang
chachasmooth_ has quit [Ping timeout: 260 seconds]
deavmi has quit [Ping timeout: 260 seconds]
deavmi has joined #crystal-lang
rocx has quit [Quit: 👏 developers 👏 developers 👏 developers 👏 developers]
rocx has joined #crystal-lang
rocx has quit [Remote host closed the connection]
rocx has joined #crystal-lang
sagax has quit [Read error: Connection reset by peer]
<FromGitter> <wyhaines> I'm whipping up something that is probably suboptimal, as it takes the shotgun approach of just trying a bunch of formats to see if something sticks, but with the ability to inject one's own formats into it. I'll post a link when the first pass is done.
<FromGitter> <wontruefree> I was able to upload our initial podcast with Ary on youtube if you want to listen to Ary on the origin or Crystal or share it. https://youtu.be/4Bn1CMoT85k
sagax has joined #crystal-lang
rocx has quit [Ping timeout: 260 seconds]
rocx has joined #crystal-lang
rocx has quit [Client Quit]
rocx has joined #crystal-lang
<FromGitter> <andrewc910> @Blacksmoke16 I tried your suggestion for mapping methods to a procs in a hash. https://play.crystal-lang.org/#/r/9fm9 ⏎ ⏎ I wanted to ask, would this would be an improvement over a `case` statement?
<FromGitter> <Blacksmoke16> i think it would break if you subclass Event
<FromGitter> <Blacksmoke16> case is prob simpler
<FromGitter> <andrewc910> May i ask why you think that? Okay, the case will stay, just wanted to give it a whack!
<FromGitter> <Blacksmoke16> as then you could just pass the event name and be done with it, plus without the extra memory of the hash
<FromGitter> <andrewc910> Okay! Ill go modify what you provided to add the possibility of accepting event. Thanks for the input :)
<FromGitter> <Blacksmoke16> sorry i mean pass the method name to the class
<FromGitter> <Blacksmoke16> like `klass.invoke method`
<FromGitter> <Blacksmoke16> which would just noop if `method` doesnt match anything (or could have it raise if you wanted)
<FromGitter> <andrewc910> ```code paste, see link``` ⏎ ⏎ How about this? This is the case you provided before with the added event argument. [https://gitter.im/crystal-lang/crystal?at=5f15ecb18e9a3a6ef0a48df1]
<FromGitter> <Blacksmoke16> i think you could do something like `if args[0] && !args[0].restriction.resolve <= Event` or something like that
<FromGitter> <Blacksmoke16> to allow subtypes of it
<FromGitter> <andrewc910> Oh, that's where it would break with event subclasses! Thanks for pointing that out. Ill play around with your recommendation. Thanks, i greatly appreciate the help!
<FromGitter> <Blacksmoke16> naw the proc would i think
<FromGitter> <Blacksmoke16> `->(event : Event)` wouldnt allow you to pass a subtype of `Event` iirc
<FromGitter> <andrewc910> But this line `args[0].restriction.stringify != "Event"` is the current version wouldn't allow subtypes, right? Hence why the `resolve`?
<FromGitter> <andrewc910> Is that just a proc thing? Procs only allow the type specified and not subclasses of that type?
<FromGitter> <Blacksmoke16> no because if i define `class MyEvent < Event` `"MyEvent" != "Event"`
<FromGitter> <Blacksmoke16> oh sorry, yea as its stands it would handle sub types
<FromGitter> <Blacksmoke16> as you're just comparing string representations of the types
<FromGitter> <andrewc910> Of course, so `!args[0].restriction.resolve == Event` just allowed me to pass in `Click` which is a subclass of `Event`. Thanks for pointing that out.
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/9fmh
<FromGitter> <Blacksmoke16> hmm, i thought this would have blown up
<FromGitter> <andrewc910> Good to know it doesn't. Personally, i would find it strange methods can accept subclasses of a type but procs couldn't?
<FromGitter> <Blacksmoke16> there is a case that doesnt work tho
<FromGitter> <Blacksmoke16> sec
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/9fmk ah this was it
<FromGitter> <Blacksmoke16> trying to use the proc as an ivar with a type restriction on the procs argument as the parent
<FromGitter> <andrewc910> Ill have to go look at `record` but i believe i understand. Do you know why that happens? It looks like it would compile?
<FromGitter> <Blacksmoke16> @asterite could tell you more
<FromGitter> <Blacksmoke16> i *think* there is an issue somewhere about it but i dont remember the exact reasoning
<FromGitter> <andrewc910> Procs are a generic right? Does that apply to all generics? Like a method accepting `{} of String => String` would not accept `{} of Symbol => String`?
<FromGitter> <Blacksmoke16> they use generics, im pretty sure this is specific to procs
<FromGitter> <Blacksmoke16> but your example wouldnt work either because those are two distinct types
<FromGitter> <andrewc910> Better example: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ Doesn't compile. `Error: no overload matches 'Hash(String, Event)#[]=' with types String, Subevent` [https://gitter.im/crystal-lang/crystal?at=5f15f25000ae3b3d9901c1c7]
<FromGitter> <Blacksmoke16> `class Subevent < Event`
<FromGitter> <andrewc910> Im dumb. Compiles.
<FromGitter> <andrewc910> I will wait for @asterite xD
<FromGitter> <asterite> @andrewc910 In the general case, `Proc(U)` can't be automatically casted to `Proc(T)` where `U < T` because the way the type is represented might not match. For example for an abstract struct or a union. But for classes it should work. But it's still pending to decide whether we want that inconsistency in the language (only allow it for classes) or disallow it completely
<FromGitter> <asterite> But what are you trying to achieve?
<FromGitter> <andrewc910> This is what i was doing that got us on the topic: https://play.crystal-lang.org/#/r/9fn5
<FromGitter> <andrewc910> I opted for a creating a `case` instead as the classes, when properly designed, should only have a few methods. But blacksmoke pointed out the proc implementation i linked above may or may not support event subclasses due to the proc in certain circumstances.
<FromGitter> <Blacksmoke16> i think in this context it would ^
<FromGitter> <Blacksmoke16> but dont quote me :p
<FromGitter> <andrewc910> @asterite I don't understand this: `because the way the type is represented might not match`. Are you saying something like `U | String` is where this new type is not a type of `T` and things could break?
<FromGitter> <andrewc910> That @Blacksmoke16 guy gave me bad advice the one out of a hundred times I ask him. How dare he! ⏎ ⏎ Regardless, the problem is solved. I am just more curious on the language design of types. This is definitely an area i need more work on.
<FromGitter> <Blacksmoke16> to be fair I suggested the proc thing w/o knowing what you were doing exactly 😉
<FromGitter> <asterite> Mainly with structs. If you have `abstract struct Event` and `struct SubEvent < Event`, the representation of `Event` is something like `{Int32, value}` but the representation of `SubEvent` is just `value`
<FromGitter> <asterite> It's hard to explain in a chat box
<FromGitter> <asterite> You can think of this limitation as a language inconsistency or a planned feature, but it's really low priority because Procs aren't used that much, and they are not very necessary in my opinion, except for simple callbacks which can already be done with block capturing
<FromGitter> <asterite> In general I would avoid programming by creating manual `Proc`, there's always a better/simpler way to do it
<raz> the idea of creating one manually probably stems from ruby. i remember having been in that situation once. then i realized i could do it with a macro
<raz> (it as in solving the task at hand, not creating a proc)
<FromGitter> <andrewc910> @Blacksmoke16 Totally understand! That's why I am not too worried about wrong advice. I don't expect more than a few minutes. ⏎ ⏎ @asterite `In general I would avoid programming by creating manual Proc, there's always a better/simpler way to do it` I will keep that in mind! Thank you. ⏎ ⏎ I believe I have a better understanding. I am going to go play around with it & see if i can break things.
<FromGitter> ... Thanks for the through answer. I know i ask a lot of questions here but i do appreciate all the responses! :) [https://gitter.im/crystal-lang/crystal?at=5f160657564e6b39f56c2103]
<raz> orrrr i got my line numbers back, thank you spectator shard
* raz quietly disposes of the evil macro contraption he had used to shoehorn before/after hooks into specs
<FromGitter> <Blacksmoke16> im still not sold on the need for an external testing shard like that
<raz> you will be when you need before_each/after_each
<FromGitter> <Blacksmoke16> thats in the stdlib now
<FromGitter> <Blacksmoke16> so...
<raz> oh, i didn't know that
<raz> since 0.35?
rocx has quit [Ping timeout: 260 seconds]
* raz should check
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/master/Spec.html#after_each(&block)-class-method
<FromGitter> <Blacksmoke16> and ones under it ofc
<raz> oh noice
<raz> gonna give it a shot. maybe my rendezvous with spectator was a short one
<FromGitter> <Blacksmoke16> its been since `0.32.0`
<raz> hmm, no idea how i never saw that
<FromGitter> <Blacksmoke16> :p
<raz> i'd been using minitest cause i missed something in stdlib spec, but don't remember what it was
<raz> (thought it was the before/after stuff)
<raz> actually, i think also something with assertions... well, i'll know soon when i re-re-write my tests ;)
<FromGitter> <Blacksmoke16> imo my thought on that is it can be kinda risky, like oh my tests broke because of new version
<FromGitter> <Blacksmoke16> then have to wait for fix and new release
<FromGitter> <Blacksmoke16> and new people have to learn that lib
<FromGitter> <Blacksmoke16> :shrug:
<raz> yea, i'll prob go back to stdlib unless i rediscover what had put me off in first place
sagax has quit [Ping timeout: 260 seconds]
sz0 has quit [Quit: Connection closed for inactivity]
<FromGitter> <mattrberry> Ooh this is fun ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5f161e6c5ed1d5377472464b]
<FromGitter> <Blacksmoke16> gl
<FromGitter> <DoWhatThouWilt> I'm having trouble setting up the Scry language server with VSCodium on Manjaro. The marketplace is missing many extensions for some unknown reason, so none of the old crystal ones were available. I was able to build it using the instructions on the git page, but I cannot figure out how to preform this final step: ⏎ ⏎ > set your LSP client's scry binary path to point to scry/bin/scry.
<FromGitter> <Blacksmoke16> gl, is scry still maintained?
<FromGitter> <DoWhatThouWilt> last commit was April 26th, so sort of?
<FromGitter> <Blacksmoke16> needs other PR merged for latest crystal version tho
<FromGitter> <DoWhatThouWilt> I did just find out:
<FromGitter> <DoWhatThouWilt> VSCodium switched to an open source extension marketplace
rocx has joined #crystal-lang
<FromGitter> <j8r> @DoWhatThouWilt scry has a gitter channel, you can also ask there