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
postmodern has joined #crystal-lang
<FromGitter> <mwlang> Greetings! It's been a while since I've had the privilege of coding up some Crystal. I am upgrading a project I last worked on in Crystal 0.35.1 and am wondering what exactly is the "upgrade process" these days for bringing a project forward?
<FromGitter> <mwlang> just starting with Crysal 1.1.1 and `crystal spec` on my project leads to webmock shard having some issues: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=61219ab195e9341de035dc86]
<FromGitter> <Blacksmoke16> is that shard up to date?
<FromGitter> <mwlang> I seriously doubt it. that's what I'm after. In Ruby, I would run `bundle update webmock --conservative` but I'm not sure if shard does the same
[R] has quit [Quit: No Ping reply in 180 seconds.]
[R] has joined #crystal-lang
<FromGitter> <mwlang> about to try `shards update` but that just got me wondering if Crystal has a guide somewhere for jumping from the 0.35.x days to 1.x release.
<FromGitter> <Blacksmoke16> would need to look at your lock file and compare it to what upstream
<FromGitter> <mwlang> hmm...I just went ahead and updated the whole thing. picked up the latest and `crystal spec` runs, albeit with some failures now.
<FromGitter> <Blacksmoke16> nice
postmodern has quit [Read error: Connection reset by peer]
<FromGitter> <mwlang> should I leave the `crystal` entry at 0.35.1 or just go ahead and bump it to 1.1.1? (presumably that forces anyone using my shard to have to bump crystal version as well...) https://github.com/mwlang/binance/blob/master/shard.yml
<FromGitter> <Blacksmoke16> if its not compatible could do something like `crystal: '>=1.0.0, < 2.0.0'` or something
<FromGitter> <mwlang> as far as I know, it's gonna be compatible, but I'll certainly no longer be testing that far back myself.
<FromGitter> <mwlang> I'll bump it your suggestion... that seems to be a fair middle ground.
[R] has quit [Ping timeout: 240 seconds]
<FromGitter> <mwlang> it may be my imagination, but crystal compile times sure seem a lot faster than last time around.
<FromGitter> <Blacksmoke16> i would doubt it :P
<FromGitter> <Blacksmoke16> historically it gets slower
<FromGitter> <mwlang> it's probably that I'm working on the shard and not yet in the lucky project where I do spend my time. :-/
<FromGitter> <mwlang> but then again, I also cleaned a lot of cruft off my laptop (8 years worth!) and starting with a fresh homebrewed environment
<FromGitter> <mwlang> Interesting...when I hit Binance's ping api endpoint with curl, I very clearly get `{}` as the body. But HTTP::Client::Response reports `""` as the response body.
<FromGitter> <mwlang> `(response.as(HTTP::Client::Response)).body # => ""`
<FromGitter> <mwlang> I'm guessing the body's content is in body_io, since I see `read_remaining=2` but I'm unsure exactly how I should read the body_io stream.
<FromGitter> <mwlang> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=6121a89e404bc13a105da96d]
<FromGitter> <mwlang> going down a rabbit hole, I am. https://github.com/crystal-lang/crystal/issues/9444
<FromGitter> <mwlang> ```ex # => #<IO::Error:Closed stream> ⏎ hold # => nil``` ⏎ ⏎ The body's nil, so it's empty. the body_io has 2 characters in it, but I cannot read 'em. I'm at a loss what to do here. [https://gitter.im/crystal-lang/crystal?at=6121aba9404bc13a105dae7f]
ur5us has joined #crystal-lang
<FromGitter> <Blacksmoke16> what are you wanting to do?
<FromGitter> <Blacksmoke16> `body_io` only works with the block version
<FromGitter> <mwlang> I think I figured it out. The response's body is being held in the body_io of the `HTTP::Client::Response` But webmock is closing the stream before I can access it. If I comment out the line in webmock that closes the stream, then I can read the body_io where the response's body is held: https://github.com/manastech/webmock.cr/blob/master/src/webmock/core_ext.cr#L37
<FromGitter> <Blacksmoke16> but isn't it yielding the response, cant get it from there?
<FromGitter> <Blacksmoke16> before that happens*
<FromGitter> <mwlang> hmmm...that's yielding into my shard's implementation. The `after_live_request` callback is where I record everything to fixture, so we don't hit the external endpoint again.
<FromGitter> <Blacksmoke16> could you use a https://crystal-lang.org/api/master/IO/MultiWriter.html
<FromGitter> <Blacksmoke16> so while you're streaming the output it writes to both locations
ur5us has quit [Ping timeout: 250 seconds]
<FromGitter> <mwlang> That's a cool idea, but seems like a rabbit hole.
<FromGitter> <mwlang> I forked webmock and moved the close to *after* calling the callback and this solves it. I'll submit a PR for it as well.
<FromGitter> <Blacksmoke16> would it make sense to have it in an `ensure` block as well?
<FromGitter> <mwlang> probably? I'm not entirely sure -- webmock may be doing more than it needs to? It may not even make sense that it's closing the stream -- seems like that would be the responsibility of the HTTP::Client libraries
<FromGitter> <mwlang> I'll mention also placing in an `ensure` block as well on the PR I submit. The maintainer likely has a better clue than me.
<FromGitter> <Blacksmoke16> prob not a huge deal, but it would ensure its closed if an exception were to be raised before it was closed
<FromGitter> <mwlang> yeah, I think you're right. I decided to go ahead and do that.
<FromGitter> <mwlang> LOL -- now that I fixed the vcr recording, I could then go fix the code that consumes the body by calling `response.consume_body_io` and that ends up essentially fixing the callback's original problem in recording the cassette because now body_io has been dumped into the response.body as the side-effect.
<FromGitter> <mwlang> even so, without the working code, the vcr couldn't capture the response correctly, so the body saved to fixture was always empty.
<FromGitter> <Blacksmoke16> Welp, least you figured it out
SamantazFox has quit [Ping timeout: 268 seconds]
<FromGitter> <mwlang> Thanks for the talk-through, @Blacksmoke16 - helpful as always. PR here: https://github.com/manastech/webmock.cr/pull/48
hightower2 has joined #crystal-lang
ur5us has joined #crystal-lang
hightower3 has joined #crystal-lang
hightower2 has quit [Ping timeout: 252 seconds]
SamantazFox has joined #crystal-lang
ur5us has quit [Ping timeout: 240 seconds]
[R] has joined #crystal-lang
<FromGitter> <Blacksmoke16> 👍
HumanG33k has quit [Ping timeout: 248 seconds]
HumanG33k has joined #crystal-lang
<FromGitter> <mwlang> How do I track down the source of where this message is originating in my code? ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=61225b46cff4797d184a7aa2]
<FromGitter> <Blacksmoke16> gl
<FromGitter> <mwlang> gl?
<FromGitter> <Blacksmoke16> good luck :P
<FromGitter> <mwlang> I thought you were about to tell me about some newfangled `garbage locator` tool.
<FromGitter> <Blacksmoke16> might be helpful
<FromGitter> <mwlang> yeah, that gets me pointed in the right direction, I think. Most likely because I'm downloading a ton of JSON and parsing it, so I'm guessing there's either failure on my part to memoize or cache and parse same JSON more than once.
<FromGitter> <Blacksmoke16> are you not parsing the stream?
<FromGitter> <Blacksmoke16> versus loading it all into memeory and dumping it somewhere
<FromGitter> <mwlang> that's what I'm wondering. You taught me how to do that a while back and I made a few fixes in that direction along the way...there's probably a couple stragglers not yet converted. I only have a few thousand lines of code to poke through.
<FromGitter> <mwlang> ah, ha! `crystal spec -v` will show me what test is running when that message is emitted.
<hightower3> Hey I have a bunch of places where I accept some instances of objects and just lookup properties in them (i.e. doing things read-only). And I guess it would be just as fine if users passed structs instead of classes, at their option. So my first question is, is there some good advice from practice how to name such classes/structs where just type is different and they are otherwise identical, and second, what's a good pattern to then use in
<hightower3> method definitions, to specify that both are accepted?
<FromGitter> <tenebrousedge> yes, use overloads
<FromGitter> <Blacksmoke16> use an interface
<FromGitter> <Blacksmoke16> e.g. a module with abstract defs
<FromGitter> <Blacksmoke16> then the user could pass whatever as long as it fulfills that contract
<hightower3> Hm, well ok, for the first part of definitions, this would put the ball in users' court to define their own types which implement the interface. Originally I was more thinking of making real modules (with implementation) and then just include them from a 'class' and a 'struct'. So the user doesn't have to do anything other than just pick one or another by name when creating instances.
<FromGitter> <Blacksmoke16> do you have more context?
<FromGitter> <Blacksmoke16> e.g. of what these types represent, and what the use case is to support both class and struct
<hightower3> I don't have a pressing need to use structs at the moment, I was just thinking if there was a way to allow both classes and structs in a semi-generic way.
<FromGitter> <Blacksmoke16> an interface would be the way to go then imo
<FromGitter> <HertzDevil> you cannot share implementation between a class and a struct by subclassing, that's for sure
<FromGitter> <HertzDevil> because they have different roots (`Reference` and `Value`)
<FromGitter> <Blacksmoke16> could use a module that acts as both the interface and shares common logic
<hightower3> yes, sure, not by subclassing but by 'include'ing a module with implementation in both
<FromGitter> <HertzDevil> where does naming come into play, though
<hightower3> I mean there can't be a class and struct of the same name
<hightower3> So I was asking if there was anything seem from existing practice, like (wild example) naming a class just 'Xyz' and an equivalent struct 'XyzStruct' or something...
<hightower3> s/seem/seen/
<FromGitter> <HertzDevil> a `Box(XyzStruct)` more or less has the same semantics as `Xyz` but obviously their apis are different
<hightower3> OK, probably won't do anything right now, will consider the advice received. Thanks as always
<hightower3> Like, this is the closest to what I was thinking about: https://play.crystal-lang.org/#/r/bsvw
<FromGitter> <HertzDevil> that looks perfectly fine
<hightower3> Right, yes, the only thing I don't like in that example is that either a class or a struct is always named somewhat awkwardly. That was the reason for my initial question re. whether some naming examples for such cases exist in practice.
<FromGitter> <HertzDevil> doesn't seem awkward to me
<hightower3> ok great, that's good to know, thanks
ur5us has joined #crystal-lang
deavmi has quit [Read error: Connection reset by peer]
deavmi_ has joined #crystal-lang
<FromGitter> <rishavs> Has anyone written a lexer/parser in crystal? I am interested in seeing how I can represent a simple grammar using crystals type system.
HumanG33k has quit [Remote host closed the connection]
HumanG33k has joined #crystal-lang
<FromGitter> <syeopite:matrix.org> I've written one for my i18n shard in order to process a subset of C for Gettext's plural-forms https://github.com/syeopite/lens/blob/master/src/backend/gettext/plural-forms/lexer.cr but for a more complex example you should check out Crystal's: https://github.com/crystal-lang/crystal/blob/master/src/compiler/crystal/syntax/lexer.cr
<FromGitter> <oprypin:matrix.org> wow, sounds impressive! maybe you should publicize it more
<FromGitter> <syeopite:matrix.org> Thanks! I don't think I can do much on the advertising side though, pretty much just have to wait for people to find it on the major shard indexes