ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
zorp has quit [Ping timeout: 240 seconds]
kerframil has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 260 seconds]
_whitelogger has joined #crystal-lang
asterite_ has joined #crystal-lang
daemonwrangler has quit [Ping timeout: 240 seconds]
asterite has quit [Ping timeout: 240 seconds]
asterite_ is now known as asterite
wmoxam has quit [Ping timeout: 240 seconds]
wmoxam has joined #crystal-lang
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 272 seconds]
kerframil has quit [Quit: WeeChat 3.0.1]
<FromGitter> <acook> I ran into a fun bug earlier where I had an if statement inside a case statement and the compiler refused to believe the nil was handled until I moved everything into the case. Had me chasing my tail for a minute there though.
<FromGitter> <Blacksmoke16> got an example?
f1reflyylmao is now known as f1refly
maxpowa has quit [Ping timeout: 272 seconds]
maxpowa has joined #crystal-lang
_ht has joined #crystal-lang
<FromGitter> <> Hi! I am still working on my macros, what am I missing here?
<FromGitter> <HertzDevil> `instance_vars` must be inside a def
<watzon> Beat me to it
<watzon> Common pitfall
<FromGitter> <> wow, ok thanks
<watzon> Question, what's the online tool that can be used to convert JSON to serializable objects in a bunch of languages?
<watzon> Can't remember the name
<FromGitter> <> why that restriction for instance_vars?
<watzon> The object has to be fully defined before its instance vars can be accessed
<watzon> Or something like that
<FromGitter> <HertzDevil> ivars materialize after macro expansion
<FromGitter> <> argh
<FromGitter> <> ok
<FromGitter> <> so my idea what to use ivar to generate a new type from another one
<FromGitter> <> I have SomeType, I want to generate SomeType2 using a macro, and copying most of SomeType's fields
<FromGitter> <> if instance_vars works only in a def, I am a bit screwed
_whitelogger has joined #crystal-lang
<FromGitter> <HertzDevil> ```code paste, see link``` []
<FromGitter> <HertzDevil> i did it
<FromGitter> <watzon> Ooh nice!
alexherbo2 has joined #crystal-lang
<FromGitter> <alexherbo2> how to transfer stdin to a named pipe?
<FromGitter> <alexherbo2> I tried `STDIN.reopen("a.fifo", "w"))` but I did not received data
<FromGitter> <alexherbo2> I ended up doing `"tee", { fifo.path.to_s }, input: STDIN)` :/
<FromGitter> <Daniel-Worrall> Watzon quicktype
<watzon> That's it! Thanks
<FromGitter> <Daniel-Worrall> I'm always shilling it :D
<FromGitter> <alexherbo2> why `each.with_index` does not work with `map`?
<FromGitter> <alexherbo2> I cannot chain it, I have to fill a `.to_a` between the two
<FromGitter> <HertzDevil> ```x, y, z = "abcde" ⏎ [x, y, z] # => ['a', 'b', 'c']``` []
<FromGitter> <HertzDevil> just noticed you can do this in crystal but not ruby (because `String` doesn't define `#to_ary` there)
zorp has joined #crystal-lang
<FromGitter> <asterite> Interesting!
<FromGitter> <asterite> And so cool you managed to implement splat on left hand side
<FromGitter> <asterite> The only thing we are missing regarding splats is being able to put them in tuple, array, and generally in any "array-like" structure. And I think that's even simpler than anything else (for starters it can just translate to an `each` loop appending each of them to the result, and later on we could check if the target type responds to `concat`)
<FromGitter> <asterite> And I say this just for completeness!
<FromGitter> <HertzDevil> that's also probably not very hard but i'd wait until crystal-lang/crystal#10009 is merged
<yxhuvud> hertzdevil: that make me wonder exactly why string implement to_ary, as that is not exactly expected behaviour (at least not by me)
<FromGitter> <HertzDevil> no, `#to_ary` is an exclusively ruby thing that the language calls whenever something is being (single) splatted
<FromGitter> <HertzDevil> and we don't have `String#to_a` either???
<FromGitter> <asterite> I think the main issue there is defining what that is... is it bytes? It it codepoints? Is it graphemes? That's why probably Ruby doesn't have it. Same reason why there's no `each` for String
<FromGitter> <asterite> I *think* it should be graphemes, but we don't have that concept yet...
<yxhuvud> asterite: I think the main issue there is accidental parallel assignment. I'd expect an error.
avane has joined #crystal-lang
<yxhuvud> in ruby the string ends up assigned to x, which at least follows the internal logic of parallel assignment there
<repo> Blacksmoke16: hey there! i'm trying to work not being able to define regexes for the allow origin config of athena
<repo> ah i think i'm getting somewhere
<FromGitter> <asterite> yxhuvud: you mean, if you have `x, y = exp` and you expected `exp` to be an array but it turned out to be a string?
<yxhuvud> indeed. Similar to how I wouldn't expect `x, y = 5` to destruct the integer into internal bits I wouldn't expect something like that out of string assignment.
<FromGitter> <asterite> That's true... but I'm more inclined to think that if that failed and you didn't notice, you are missing a test
<FromGitter> <asterite> Or maybe we do need a `to_ary` or similar... maybe `to_splattable`, I don't know
<FromGitter> <> I'd normally be super excited about these developments ⏎ but the fact that `a, b = [1, 2, 3]` is not an error makes all of this useless
<FromGitter> <asterite> Why it would be an error? `a, b` means you are only interested in the first two elements
<yxhuvud> Not certain how it could be. perhaps for `a, b = {1, 2}`
<FromGitter> <> where does it indicate first elements?
<FromGitter> <asterite> I guess maybe you thought you had two elements and you got 3 and you have a latent error...
<FromGitter> <asterite> that's what the syntax means :-)
<FromGitter> <asterite> but I agree that it can be error-prone
<FromGitter> <> how do you decide that it means "first" not "last" elements. could've been the other way and would've made exactly as much sense
<yxhuvud> I could see an argument for being explicit and require `a, b, * = [1, 2,3]` or something. :shrug:
<FromGitter> <> yes please
<yxhuvud> But it is hard to do the general case in a nice way for compiletime checks of dynamic things like arrays. For tuples or the like with fix amount of fields it would make more sense
<FromGitter> <> it doesn't need to be compile time
<FromGitter> <> if no asterisk, assert size first
<FromGitter> <> then you can have both `*, a, b =` and `a, b, * =` making sense
<FromGitter> <asterite> you mean `*, a, b` expects exactly three elements?
<FromGitter> <> without `a, b =` being an alias to one of them arbitrarily
<FromGitter> <> no no no that's 2 or more, discard others
<FromGitter> <asterite> Oh, you mean `*, a, b` means "get the last two elements"
<FromGitter> <> for anything "exactly" there is no asterisk involved, that's how you tell them apart
<FromGitter> <asterite> I think that could work... it's a breaking change, though, but it's probably a minor one
<FromGitter> <asterite> I think that will also make `x, y = "hello"` fail at runtime... though it will work for `x, y = "ha"`
<FromGitter> <> that's great!
<FromGitter> <Blacksmoke16> repo: there's a to-do to support that, atm probably best off just enumerating all the options
<yxhuvud> asterite: gah.
<FromGitter> <> btw i would say strings should not be unpackable like that
<repo> Blacksmoke16: yeah that's not a possibility for me. I'm using review apps in gitlab ci
<yxhuvud> Why does it work in the first place? Is it because string implement #each or something like that?
<repo> so basically my frontend is deployed to subdomain that reflects the current branch name
<FromGitter> <> it doesn't implement each though
<repo> *to a
<FromGitter> <> it's because it implements [0]
<FromGitter> <asterite> `x, y = exp` translates rougly to `x, y = exp[0], exp[1]`, that's why it works
<FromGitter> <Blacksmoke16> Should actually be a lot easier now. Problem before was there wasn't a way to instantiate a regex from yaml. I'll put together a pr this afternoon
<repo> Blacksmoke16: i found a workaround though:
<FromGitter> <asterite> Maybe it's not bad that you can do `x, *y, z = "hello"` and get `x = 'h', y = "ello" and z = 'o'`
<oprypin> oh what, that works? :o
<FromGitter> <asterite> meant `y = "ell"`
<FromGitter> <Blacksmoke16> Someone needs to upgrade :p
<repo> asterite: waaat?
<FromGitter> <> well nice! now just need to not implicitly ignore things at the end and im super duper excited
<repo> does crystal have destructuring now?!
<yxhuvud> oprypin: wait, didn't you just say you didn't want destructuring strings? :D
<FromGitter> <> uhh 😅😅😅
<repo> where is this described?
<repo> release notes for 0.36.0?
<oprypin> >> x, *y, z = "hello"
<DeBot> oprypin: Error: unexpected token: * -
<FromGitter> <> i think it's in pending pull requests
<oprypin> >> x, y, z = "hello"; p! x, y, z
<DeBot> oprypin: x # => 'h' - more at
<FromGitter> <asterite> I guess string destructuring is fancy but probably unexpected and inconvenient
<yxhuvud> rather than inconvenient I would say not very commonly useful. It is probably quite convenient the few times it is useful :)
<repo> mmh
<repo> but we have no support for named tuple destructuring, right?
<repo> or even objects :P
<repo> also what about nested tuple destructuring?
<FromGitter> <naqvis> i would say instead of hardcoding de structuring inside compiler, it would be more better to provide Extractors. The way Scala handles it
<FromGitter> <naqvis> that will make it useful for people and allow them to provide Extractors even for their custom objects
<FromGitter> <naqvis> just my two cents
<yxhuvud> be that as it may with string destructuring, I'm really hyped for getting support for `x, *y, z = {1, 2, 3, 4, 5}` and the like
<repo> is that planned?
<FromGitter> <> could we do `x, _, *y, _, z`?
<FromGitter> <HertzDevil> yes
<repo> what about `z, {y, z} = {1, {2, 3}}`?
<repo> *x
<repo> or `{foo, bar: {baz}} = {foo: 1, bar: {baz: 2}}`? :)
<FromGitter> <HertzDevil> pattern matching is stricter than splat assignments and i don't think we should impose the former's semantics on the latter
<repo> mhm
<FromGitter> <HertzDevil> ruby does those with `=>`
<FromGitter> <> even the simple `x, y = ary` is not that used
<FromGitter> <> It is convenient, but I don't mind when I don't have it
<FromGitter> <HertzDevil> great the array literal rewrite is merged
<FromGitter> <HertzDevil> time for crystal-lang/crystal#3718
<FromGitter> <HertzDevil> i don't see a general pattern matching proposal on either github or the forum
<FromGitter> <alexherbo2> @Blacksmoke16 do you know how to parse multiple json objects like `jq`? ⏎ ⏎ `````` []
<FromGitter> <alexherbo2> ```jq .[] <<EOF ⏎ ["a", "b", "c"] ⏎ EOF``` []
<FromGitter> <alexherbo2> I would like the JSON parser to be able to slurp the data in an array
<FromGitter> <Blacksmoke16> not sure i follow, what output are you wanted from that that @alexherbo2 ?
Human_G33k has quit [Remote host closed the connection]
Human_G33k has joined #crystal-lang
alexherbo2 has quit [Remote host closed the connection]
rymiel has joined #crystal-lang
rymiel has quit [Client Quit]
rymiel has joined #crystal-lang
rymiel has left #crystal-lang [#crystal-lang]
rymiel has joined #crystal-lang
rymiel has quit [Client Quit]
rymiel has joined #crystal-lang
rymiel has quit [Client Quit]
<watzon> @BlackSmoke16 does Athena have a middleware system? And if so, does it have some kind of extendable context?
<FromGitter> <Blacksmoke16> yes, its in the form of events, versus `HTTP::Handler` stack
<FromGitter> <Blacksmoke16> extendable context in what regard? Like how you'd normally monkeypatch things into `HTTP::Server::Context`?
<watzon> Basically. I'm thinking along the lines of how most frameworks in more dynamic languages do it. For instance, express.js. They have a context object included with each request which can be extended (by yourself or third party libraries) usually via middleware to pass information along.
<watzon> The reason I ask is because I'm trying to think of a clean way to do a similar thing with my Tourmaline bot library. I want to have a middleware stack, but middleware is mostly useless unless you have some way to pass information from the middleware to the actual controller that's handling the response.
<watzon> All I've managed to come up with so far is basically what you said. Have a `Context` object that can be monkey patched
<FromGitter> <Blacksmoke16> tl;dr i added a instance to the request that can be used to store stuff on the request
<FromGitter> <Blacksmoke16> then part of knowing which args should be passed to the controller action, is checking if they're in the request's attributes
<FromGitter> <Blacksmoke16> like the example in the API docs, it can be used to store custom stuff too
<watzon> Ok that's basically what I had tried at first, but data that can be stored on it is limited to certain types right? Generally primitives
<watzon> Which is the problem I ran into
<FromGitter> <Blacksmoke16> naw, it can handle whatever
<FromGitter> <Blacksmoke16> data is stored as a `Hash(String, Param)` where `Parameter(T) < Param)`
<watzon> Hmm interesting. I may have to steal this.
<FromGitter> <Blacksmoke16> which makes use of implicit generic type instantiation, or allows passing `T` explicitly to be more type safe
<watzon> I originally tried to imitate `Log::Context` I believe, end it ended up being pretty limited.
<FromGitter> <Blacksmoke16> depending on what/how exactly you want this to work, having dedicated properties or something might be better
<watzon> Unfortunately due to the nature of the problem I have 2 options as I see it. Have a base object that can be monkey patched, or do something like `ParameterBag`. I hate the idea of monkey patching as an API requirement, so I hope I can get the `ParameterBag` thing to work.
<FromGitter> <Blacksmoke16> both have their pros and cons. Like `ParameterBag` you cant really document *what* things you could get from it as its dependent on how you use it, and more complex.
<watzon> Right
<FromGitter> <Blacksmoke16> alternative is you could have a `Context` option that accepts some other obj where your lib defines the base type
<FromGitter> <Blacksmoke16> something like
<FromGitter> <Blacksmoke16> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> so you kinda just define the interface and let users implement what it could be?
<FromGitter> <Blacksmoke16> main challenge there would be how to provide the custom type, and some stuff would need to be nilable given it wont all be set at once
<watzon> Yeah there's that, and it wouldn't be very extendable. What happens if someone has a library with a custom middleware and wants to add to that custom type?
<watzon> They wouldn't know what to monkey patch
<FromGitter> <Blacksmoke16> ah so it kinda needs to be a global thing yea? I.e. not specific to a specific implementation
<watzon> Yeah
<watzon> I'm going to try and make the `ParameterBag` thing work. If it doesn't I'll stick to monkey patching a base object.
<watzon> Thanks!
<FromGitter> <Blacksmoke16> 👍 g
<watzon> Knew you'd be the person to talk to haha
<FromGitter> <Blacksmoke16> gl*
r0bby has quit [Remote host closed the connection]
sz0 has quit [Remote host closed the connection]
<FromGitter> <> is there some kind of "standardized" benchmark for http routers?
<FromGitter> <> uhh doesn't stress the router very much
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <Blacksmoke16> i cant think of anything router specific, i.e. to test a bunch of paths
<FromGitter> <> I'd want some real-looking routes, like 20 of them
<FromGitter> <> the good thing about this code is that it's a perfect starting point to get that done
<FromGitter> <Blacksmoke16> if you really want to bench the router, versus the entire framework too, could do something like
<FromGitter> <Blacksmoke16> which outputs like
<FromGitter> <> omg that's perfect
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <> thanks
r0bby has joined #crystal-lang
<FromGitter> <> u know, the benchmark is basically going to be libpcre vs radix
<FromGitter> <Blacksmoke16> pretty much
sz0 has joined #crystal-lang
<FromGitter> <alexherbo2> is it out of scope to a fixed argument with the option parser?
<FromGitter> <alexherbo2> to add*
<straight-shoota> I'm curious about the outcome @oprypin
<straight-shoota> @alexherbo2 What do you mean?
<FromGitter> <Blacksmoke16> probably positional arguments ^
<FromGitter> <alexherbo2> ```kcr init kakoune``` ⏎ ⏎ on `init and on `kakoune` []
<FromGitter> <Blacksmoke16> you can do subcommands, but each subcommand would then need to parse `ARGV` for positional based args iirc
<FromGitter> <alexherbo2> it's quite difficult to tweak the option parser when it does not handle a param
<FromGitter> <alexherbo2> such as `+<line>` and `+<line>:<column>`, we cannot teach the option parser to handle it
<FromGitter> <Blacksmoke16> could look into a diff cli parser
<FromGitter> <Blacksmoke16> there are quite a few out there
<watzon> Well this works pretty well
<watzon> Added multiple different types of data to the context to simulate a more real world situation
<FromGitter> <Blacksmoke16> nice one! good to hear
<FromGitter> <Blacksmoke16> try interacting with them, im not 100% sure that they wont be a union
<FromGitter> <Blacksmoke16> might need to add a `T.class` arg to help with that
<watzon> Using the `get(key, type)` syntax seems to work
<FromGitter> <Blacksmoke16> oh, you already have `type`
<FromGitter> <Blacksmoke16> 👍
<watzon> Underneath I'm just doing a `forall T` and then `get(key).as(T)`
<FromGitter> <Blacksmoke16> yup
<watzon> Wish it wasn't necessary, but it's not a huge deal
<FromGitter> <Blacksmoke16> depending on what you're doing it might not be
<FromGitter> <Blacksmoke16> only really a problem if you wanted to do like `.get("bob").post "/foo"`
<watzon> Well yeah haha
<FromGitter> <Blacksmoke16> but yea, not a big deal imo
<watzon> Nah, could be worse
<FromGitter> <Blacksmoke16> keeps things *pretty* type safe so ill take it
<watzon> In fact, it was much worse before
<watzon> I'm happy
<FromGitter> <Blacksmoke16> 👍 good to hear
<straight-shoota> today's bugception
<straight-shoota> #10413 exposed a bug in downcasting float infinity
<DeBot> (Implement rounding mode for `Number#round`)
<straight-shoota> fixing that exposed a bug in json parser
<straight-shoota> let's see what's next
<watzon> You're on a roll man
<straight-shoota> well it's kind of depressing when a bug-fixing session ends with more bugs than less
<watzon> Par for the course lol
<FromGitter> <Blacksmoke16> @straight-shoota is also prob related
<straight-shoota> yup
_ht has quit [Remote host closed the connection]
r0bby has quit [Remote host closed the connection]
sz0 has quit [Remote host closed the connection]
<FromGitter> <> omg i'm a genius
<FromGitter> <> a router can be based on StringInterpolation literals
r0bby has joined #crystal-lang
<straight-shoota> opyrpin, yeah that should work
<straight-shoota> bruce perens works with that in his i18n shard
sz0 has joined #crystal-lang
<FromGitter> <lirossarvet> Hm, now I have a testing question that I think I have an answer to but want to check with y 'all. We have a CLI that, at the moment, does a lot of calls to just shell commands with ``. It seems like the best way, in Crystal, to test that we're doing the right thing is pass in a `runner` argument that defaults to `Process` but could be overridden into something else that just stores the arguments
<FromGitter> ... given. Still kinda makes the return value a little tricky, but some harnessing and force-returns based on specific argument values may work. ⏎ ⏎ Does anybody have any thoughts about how best to test for `` calls?
<FromGitter> <Blacksmoke16> could you test the output of your binary? It's possible to run your binary with `IO::Memory` IOs, then just ensure they contain what you'd expect?
<FromGitter> <Blacksmoke16> depends on what you want to test exactly
<FromGitter> <lirossarvet> I'd...rather not run the binaries given what side-effects they may have
<oprypin> Blacksmoke16, i think you got the question in the reverse direction
<FromGitter> <> @lirossarvet: seems like you got it
<FromGitter> <Blacksmoke16> ohh, wants to ensure the right args are passed to the ``
<FromGitter> <Blacksmoke16> how bad of an idea would it be to do like `class NoopProcess < Process`, which just collects the stuff then can run assertions within `.run`
<FromGitter> <lirossarvet> That's more or less what I want to do 😅 Either run assertions within `run` or let me inspect after.
<FromGitter> <lirossarvet> Nice to know this is at least the right path, so I can poke around and figure out what specific approach will be easiest to follow for others.
<FromGitter> <Blacksmoke16>*%22,level:Severity=Log::Severity::Trace,*,builder=Log.builder,&)-class-method works pretty great for the `Log` side of things
<FromGitter> <Blacksmoke16> similar concept, not directly useable for this context tho
<FromGitter> <lirossarvet> yeah. :D Alright, thanks for the help. Guess I know what I'll end up doing this weekend
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<FromGitter> <> @Blacksmoke16: how to use catchall in amber router? `r.add("/get/*", :catch_all); r.find("/get/foo")` - so how to get this foo?
<FromGitter> <Blacksmoke16> hmm
<FromGitter> <Blacksmoke16> wouldnt it just be in the `params` or `args` or whatever hash?
<FromGitter> <> it's not in params as i see.
<FromGitter> <> it is empty
<FromGitter> <> oh youre supposed to specify some name
<FromGitter> <Blacksmoke16> ah yea that makes sense
<FromGitter> <> wow exceptions are expensive as heck
<FromGitter> <> benchmark is ⏎ ⏎ ⏎ @straight-shoota ⏎ the super slow ones are because it currently raises an exception for "not found". guess i gotta change that, huh []
<FromGitter> <> but mine has the most features :3
deavmi has quit [Ping timeout: 272 seconds]
<straight-shoota> that's some serious macro spaghetti code
<straight-shoota> :D
<FromGitter> <wyhaines> It's not surprising that Exceptions are expensive. It isn't Ruby, but building that backtrace is still expensive.
deavmi has joined #crystal-lang
<FromGitter> <> straight-shoota, there's nothing particularly bad about that code, just the pesky `{%{%{%{%{%{%` on every line
<straight-shoota> it'sjust incredibly hard to read
<straight-shoota> but yeah, it's not that bad
<FromGitter> <> LOL i can remove the {% easily
<FromGitter> <> nevermind
<FromGitter> <> straight-shoota, is this better xD
<straight-shoota> hehe
<FromGitter> <> but i'll change it to StringInterpolation anyway. omg it'll be so amazing