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
<raz> hmmm, is there (perhaps with a macro) a way to access the current return value? (as if the method would "end now")
<FromGitter> <tenebrousedge> why?
<raz> i need to save it, do something else, then return it later
<raz> inside a macro
<FromGitter> <tenebrousedge> I don't think that's really a thing
<FromGitter> <Blacksmoke16> Macros don't exist at runtime so no
* raz sad macro noises
<FromGitter> <Blacksmoke16> Better off with a method and maybe yield it or something
<FromGitter> <tenebrousedge> what are you trying to do?
<FromGitter> <tenebrousedge> I'm really curious now
<raz> oh, all my db transactions are also automatically events and added to an audit table
<raz> works fine, i only wish i could also get the return value from the tx
<FromGitter> <tenebrousedge> can the db log that somewhere?
<raz> err no, i need the return value from {{block.body}} ;)
<raz> like, as if {{block.body}} was at the end of the macro
<raz> but i can't put it there, cause then the db magic doesn't work
* raz sad db noises
<oprypin> raz, Object#tap is a thing
<FromGitter> <tenebrousedge> this is very true
<raz> hmm!
<hightower3> Blacksmoke16 what was the decision in the end re. HTTP::Params and access to raw_params? Is it to be allowed? I have a need to retrieve the names of all passed params as a list, and I wanted to use `context.request.params.raw_params.keys` for that.
<raz> oprypin: my understanding though is that {{block.body}} in a macro pretty much just "pastes" the block code. how would i tap on that?
* raz scratches head
<oprypin> raz, wait why are we talking about macros
<raz> because i'm in a macro!
<oprypin> "access the current return value" is nonsense / dead end btw
<oprypin> `( {{pastes}} ).tap` works
* raz tries it
<raz> 'Bool#tap' is expected to be invoked with a block, but no block was given
<raz> nu-uh
<oprypin> no but thats just wrong usage of tap, do u even know it?
<raz> no i didn't, ahh, it wants a block itself
<oprypin> btw i was so surprised to find out that not only `do / end` | `{ / }` are aliases but also `begin / end` | `( / )` -- and uh also `\n` | `;` ofc
<FromGitter> <tenebrousedge> ```foo.tap {|f| foo.bar = "baz" } # returns foo```
<FromGitter> <tenebrousedge> er
<FromGitter> <tenebrousedge> `f.bar = "baz"`
<oprypin> anyway, `tap` *is* "save it, do something else, then return it later"
<FromGitter> <tenebrousedge> it's kinda similar to `then` / `yield_self` / `try`
<FromGitter> <Blacksmoke16> hightower3 you mean like form data?
<hightower3> well, in my case all query params... I don't see how I would get a list of all params that were specified (e.g. ?a=1&b=2) through HTTP::Params, other than by using its #raw_params.keys. (Well I know I can call #to_h on HTTP::Params, but why create a new hash if raw_params is already there)
<FromGitter> <Blacksmoke16> what are you doing that you need the keys?
<raz> oprypin: Error: unterminated parenthesized expression :(
<oprypin> raz, try `begin; {{stuff}}; end` instead. or show what youre doing
<oprypin> raz, try `begin; {{stuff}}; end .tap do; end` instead. or show what youre doing
<Andriamanitra> tenebrousedge: nice catch on that bitwise spell for AoC day 5.. this is now about 5x faster than my original optimized version https://github.com/Andriamanitra/adventofcode2020/blob/main/day05/benchmarks.cr#L90
<hightower3> @Blacksmoke16 the API which I am replacing and need to replicate takes all specified params and checks if any of them are not on the list of allowed/valid params.
<raz> w00t!
<raz> oprypin: made my day, thx! (i pasted what i'm doing above in the carc.in)
<FromGitter> <tenebrousedge> Adriamanitra yay! It probably took me longer than it should ^^;
<raz> begin/end was the magic formula
<Andriamanitra> tenebrousedge: oh you have no idea how long i spent debugging this :D unsafe world is scary!
<FromGitter> <Blacksmoke16> ```keys = [] of String ⏎ params.each { |k, _v| keys << k }``` [https://gitter.im/crystal-lang/crystal?at=5fcc320e67bf4438e128ff3b]
<FromGitter> <Blacksmoke16> would prob do it
<FromGitter> <Blacksmoke16> or yea, just monkey patch a getter to the raw hash
<FromGitter> <Blacksmoke16> prob similar perf given both would new up an array
<FromGitter> <Blacksmoke16> sounds like you should consider a framework πŸ˜‰
<hightower3> ah yes, simpler though to just allow access to it myself. thanks++
<hightower3> no this is the end of my meddling with the http part :) the rest is redis and rabbit
<FromGitter> <Blacksmoke16> fair enough
<FromGitter> <tenebrousedge> Andriamanitra neat, it's cool to see all those solutions, and also that unsafe code scares me πŸ˜†
<FromGitter> <Blacksmoke16> also fwiw, could you do like `a = params.fetch("a") { raise "Required param a is missing" }`
<hightower3> Yes, already do that but there's a nuance - the code also checks whether any param is specified which is neither on the required nor the optional list of params
<FromGitter> <Blacksmoke16> gotcha
f1refly has joined #crystal-lang
f1refly- has quit [Ping timeout: 264 seconds]
<hightower3> Any reason why building with --release doesn't strip the binary?
<FromGitter> <Blacksmoke16> `--no-debug`
<hightower3> hm, doesn't seem identical. `strip` still finds around 200KB to remove from a binary compiled with --no-debug
<FromGitter> <Blacksmoke16> its not, but strip prob is getting rid of more than just debug sybols
<FromGitter> <Blacksmoke16> symbols
avane has quit [Quit: ZNC - https://znc.in]
avane has joined #crystal-lang
chachasmooth has quit [Ping timeout: 260 seconds]
<FromGitter> <Daniel-Worrall> Went with a simple approach to Day 6 https://github.com/Daniel-Worrall/advent-of-code-2020/blob/main/src/crystal/6.cr
<FromGitter> <tenebrousedge> more or less the same
<Andriamanitra> oh, there's #to_set
<Andriamanitra> otherwise almost identical to mine
<FromGitter> <tenebrousedge> `&.` is nice
<FromGitter> <tenebrousedge> oh, you can skip the first arg to `reduce`? well meows
<Andriamanitra> yeah, i'm just too used to ruby where it's pretty limited what you can do with &:
<Andriamanitra> time to refactor and make it nice
<FromGitter> <tenebrousedge> in Ruby I think you might even be able to pass `reduce(:&)`
<FromGitter> <tenebrousedge> yup
<FromGitter> <tenebrousedge> `reduce` has special cases for various operators so you don't have to do `&:&`
<FromGitter> <Daniel-Worrall> I tried `&.&` and just stopped trying to fight syntax and write what I know works
ua has quit [Ping timeout: 256 seconds]
<FromGitter> <Daniel-Worrall> yeah, tene, the arg to reduce is the initial accumulator set. Otherwise, it'll be `Class#zero` iirc
<FromGitter> <Daniel-Worrall> oh no, that's `#sum`, it just takes the first element and starts from 2
<FromGitter> <mattrberry> ```code paste, see link``` ⏎ ⏎ Is this known / intended, or should I open an issue on github? [https://gitter.im/crystal-lang/crystal?at=5fcc74e6ed6fe038e56c3a49]
<FromGitter> <mattrberry> This is fine though ⏎ ⏎ ```puts [1, 2, 3].sum { |i| i }``` [https://gitter.im/crystal-lang/crystal?at=5fcc75492b3e824d8c2a2659]
<FromGitter> <mattrberry> Oh lordy, this is valid ⏎ ⏎ ```puts ([1, 2, 3].sum do |i| ⏎ i ⏎ end)``` ⏎ ⏎ Just a space after the `puts` [https://gitter.im/crystal-lang/crystal?at=5fcc781267bf4438e1298c64]
bazaar has quit [Ping timeout: 240 seconds]
bazaar has joined #crystal-lang
<kevinsjoberg> My solution: https://github.com/KevinSjoberg/aoc-2020/blob/main/06/day06.cr. Have not tried to make it pretty yet just make it pass.
<Andriamanitra> hey finally one that doesn't use sets! :D
<kevinsjoberg> haha, I'd have to admit using sets for p2 is a lot cleaner than what I did.
<kevinsjoberg> and really like using set intersection as well. That's sweet.
<kevinsjoberg> I think I have fairly poor performance characteristics on p2 given I rely on tally.
<Andriamanitra> i'm trying to resist going into the benchmarking rabbit hole today.. i spent way too many hours yesterday
<kevinsjoberg> I can imagine. I updated my solution to reduce instead, a bit cleaner in my opinion.
bazaar has quit [Ping timeout: 256 seconds]
bazaar has joined #crystal-lang
ua has joined #crystal-lang
<yxhuvud> benchmarking solutions get more interesting later on
<Andriamanitra> yeah, for sure, but i'm doubtful i'll even have working solutions when it gets interesting so better get it done early :p
<yxhuvud> todays exercise make me wish for destructive operations on sets. It is pretty bad with reduce creating lots of sets that are then just thrown away.
<Andriamanitra> Set#subtract ?
<yxhuvud> no I mean of | and &.
<Andriamanitra> ..oh, i guess there's no nice way to turn intersection into something that uses subtract
<Andriamanitra> we need &!
<kevinsjoberg> Isn't the reduce faster without the sets to begin with?
<kevinsjoberg> I did them without convert each char array to a set
<kevinsjoberg> s/convert/converting
<Andriamanitra> could be, it seems Array actually has its own implementation for &.. for some reason i assumed it's just using sets for the implementation
<yxhuvud> No real difference. If you look into how Array#& and #| is implemented, you will see that they are using hashes under the hood, just like Set.
<Andriamanitra> at the very least you get the benefit of not converting into set
<yxhuvud> There is no noticable difference in performance that I can see.
<Andriamanitra> went from 600-ish per second to 1000-ish per second
<Andriamanitra> although using only *one* set is faster still
<Andriamanitra> something along these lines https://play.crystal-lang.org/#/r/a2gs
chachasmooth has joined #crystal-lang
psydroid has quit [Ping timeout: 260 seconds]
ryanprior has quit [Ping timeout: 246 seconds]
return0e[m] has quit [Ping timeout: 240 seconds]
<FromGitter> <Morantron> hi! is there a similar mechanism of RSpec "let" in crystal lang spec?
<jhass> No :)
<FromGitter> <Morantron> just found https://gitlab.com/arctic-fox/spectator, suits my needs
ryanprior has joined #crystal-lang
return0e[m] has joined #crystal-lang
<raz> hmm, it's probably an ancient pattern, but these 6 lines have saved me so many not_nil! checks, it's not even funny https://carc.in/#/r/a2gt
* raz wiggles in joy
<jhass> in favour of as many .is_a? checks :P
<raz> no, in favor of the glamorous.... *drumroll* exhaustive case!
<jhass> I don't see how that's any shorter than checking for nil
<jhass> you still need to assign to locals
<raz> but on the call-site i don't have to care about nils, that's where the not_nil's kept getting on my nerves
<jhass> you just renamed nil to something else
psydroid has joined #crystal-lang
<jhass> I think you just have been handling these wrong, .not_nil! is a last resort solution for sure
<jhass> after .try, if foo = ...; etc
<raz> well, when dealing with ORMs you either deal with exceptions or with nil all over the place
<raz> in all those places where i need to deal at least with the "found, here it is" vs "not found" case (plus usually a bunch others), the above pattern plus exhaustive case helps nicely
<jhass> I can sort of see it for more than two values
<raz> (because it also gives all those cases a name)
<jhass> but for found or not it seems pretty redundant
<raz> yea, should maybe have clarified that. there's always at least 3. found, not found and... blargh, error.
<oprypin> raz, use exceptions then
<raz> oprypin: i don't want ORM exceptions in the call site
<oprypin> catch them
<raz> that's what i do, and they become a NoValue ;)
<oprypin> should become nil
<oprypin> or raise another exception
<raz> NoValue is nicer to handle
<oprypin> no
<raz> in the view layer it's certainly nicer to have just another case, than a rescue Β―\_(ツ)_/Β―
<FromGitter> <asterite> Matthew: it's by design. In Ruby you would think the do is for sum, but it's for puts. puts doesn't accept a block and so it's silently ignored in Ruby. "Silently ignored" in Crystal is not an option
<raz> hmm
<FromGitter> <erdnaxeli:cervoi.se> I ran some benchmarks on today AoCΒ solutions I've seen (spoiler alert):Β https://github.com/erdnaxeli/adventofcode/blob/master/2020/benchmarks/06.cr => iterators are fast, creating a Set is faster than `uniq`, and Hash.select! is faster than Hash.select
<FromGitter> <HertzDevil> why must `Val` be an abstract struct instead of a module
<raz> hmm interesting question, gonna try with a module
sagax has quit [Remote host closed the connection]
<FromGitter> <asterite> won't work
<FromGitter> <asterite> what you want is the Sealed annotation I proposed but it wasn't liked
<FromGitter> <HertzDevil> well it looks like https://carc.in/#/r/a2ht works
<FromGitter> <HertzDevil> one thing i don't like about crystal is that if i try to run any semantic/codegen specs and have firefox open at the same time my laptop will most certainly freeze
<FromGitter> <HertzDevil> need to download more ram
<jhass> some zswap also can do wonders
<jhass> and IME if you limit stuff a bit with prlimit or systemd-run's memory limiting options the GC won't get as greedy
<FromGitter> <HertzDevil> it flattens the curve a bit
<FromGitter> <HertzDevil> gonna try more tomorrow
<jhass> with systemd-run there should in theory be some way to have its cgroup be lowest prio and not stall anything else on the system, but I don't remember the details
sagax has joined #crystal-lang
<raz> HertzDevil, asterite: thx for the tips (sry had to run off for a bit). i ended up realizing that a plain old `record` actually works best for my case. https://carc.in/#/r/a2ik
<FromGitter> <asterite> yes, I usually end up doing that and then an alias with all of the types... but I'd also like it to work with inheritance
<hightower3> Hey how do I do that lazy initialization, like @array = Array(String) { fill later }
<FromGitter> <Blacksmoke16> Use the getter macro with a block
<hightower3> aha must be gette rok
<hightower3> getter, ok, thanks
oddp has joined #crystal-lang
<hightower3> ehm, how to pass value by reference of sorts? I want to pass a reference to Atomic(Int64) rather than itself
<jhass> wrap the whole affair into a class
<hightower3> could probably pass a block with that value in it, then yield
<hightower3> not :)
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/master/Box.html ?
<FromGitter> <Blacksmoke16> prob not the intended use case but would prob work...
<hightower3> interesting, let's try
<hightower3> hm, not sure, seems like I get a copy
<hightower3> yeah, seems confirmed it's still a copy. Trying the class approach then
<hightower3> yep, class thing worked, thanks for the discussion
<FromGitter> <mattrberry> > Matthew: it's by design. In Ruby you would think the do is for sum, but it's for puts. puts doesn't accept a block and so it's silently ignored in Ruby. "Silently ignored" in Crystal is not an option ⏎ ⏎ Ah, that's right, I forgot. It's been a couple years since I read this part of the reference ⏎ ⏎ > The difference between using do ... end and { ... } is that do ... end binds to the left-most
<FromGitter> ... call, while { ... } binds to the right-most call [https://gitter.im/crystal-lang/crystal?at=5fcd14994b6e8f2d3c823404]
<FromGitter> <Blacksmoke16> hightower3 but isnt `Box` also a class? not sure how thats any different
<FromGitter> <mattrberry> > Oh lordy, this is valid ⏎ > ```crystal ⏎ > puts([1, 2, 3].sum do |i| ⏎ > i ⏎ > end) ... [https://gitter.im/crystal-lang/crystal?at=5fcd14c5fb7f155587aa9be2]
<hightower3> @Blacksmoke16: not sure, I extracted the object with box.object and thought it wasn't the same obj.
<FromGitter> <Blacksmoke16> and what does your class do?
<hightower3> (rather, didn't think, I tested and it wasn't manipulating the same counter)
<hightower3> I have a counter in one class and need to pass it to another. both places call counter.add() then. But after passing it simply as counter or (Box.new(counter) and then box.object), it's not the same object
<FromGitter> <Blacksmoke16> and thats not what you're doing with the class?
<FromGitter> <Blacksmoke16> `Klass.new(object) ... klass.object`?
<hightower3> it is. But with Box.new and box.unbox it didn't work, while with passing MyClass instance, it did
<hightower3> yes, right
<FromGitter> <Blacksmoke16> to be clear you should pass box around like your class
<hightower3> yes I did
<hightower3> but the way to get to the value is to call box.object
<FromGitter> <Blacksmoke16> i dont see how thats any different ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5fcd15e14b6e8f2d3c823688]
<FromGitter> <Blacksmoke16> looks just like your class no?
<hightower3> yes. well, I can try one more time..
<hightower3> let's try a carc example
<FromGitter> <ImAHopelessDev_gitlab> hello
<hightower3> Blacksmoke16 is it possible that the difference is in Box.new accepting that value as argument (where it's already passed by value?), while in my class it's a property and always the same ?
<FromGitter> <Blacksmoke16> not sure
<FromGitter> <Blacksmoke16> either way id expect when you call the getter it returns a copy anyway
<hightower3> well it worked. I add(1) in one place, add(-1) in another and it's 0. Whereas with any other option they were counting separately
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <ImAHopelessDev_gitlab> Why is Box.box is used
<FromGitter> <ImAHopelessDev_gitlab> Where is the method `box`?
<FromGitter> <ImAHopelessDev_gitlab> is it from the `T` you pass in?
<FromGitter> <Blacksmoke16> i didnt copy the whole file
<FromGitter> <ImAHopelessDev_gitlab> oh gotcha
<FromGitter> <ImAHopelessDev_gitlab> nvm me then
<FromGitter> <mattrberry> ```code paste, see link``` ⏎ ⏎ I feel like this has to be a bug.. [https://gitter.im/crystal-lang/crystal?at=5fcd246accac732a3a04cf81]
<FromGitter> <erdnaxeli:cervoi.se> Hi, why is this not possible ?Β https://carc.in/#/r/a2je
<FromGitter> <erdnaxeli:cervoi.se> it does not work either with `self.class_test`, but `Test.class_test` is ok
<FromGitter> <erdnaxeli:cervoi.se> the reference says "When called from within the same class or module scope the receiver can be self or implicit (like encrypt(string))."
<FromGitter> <Blacksmoke16> `self` and without `self` is referring to the instance
<FromGitter> <Blacksmoke16> you'd have to do like `self.class.class_test`
<FromGitter> <Blacksmoke16> since its an instance method, it would have worked fine if `instance_test` was also a class method as then `self` would be referring to the class scope
<FromGitter> <erdnaxeli:cervoi.se> ok
<FromGitter> <erdnaxeli:cervoi.se> I think the doc is a bit confusing here
<FromGitter> <erdnaxeli:cervoi.se> IΒ would have expected that as class_test is not found for the instance, it look up at the class level
oddp has quit [Quit: quit]
renich has joined #crystal-lang
renich has quit [Quit: Leaving.]
<FromGitter> <erdnaxeli:cervoi.se> I just found out about Iterator.zip(other, &block) not being implemented. It actually use Enumerable.zip(other, &block), which can raises an IndexError. I found this very confusing. https://carc.in/#/r/a2js
<FromGitter> <erdnaxeli:cervoi.se> but looking at what is implemented for the Iterator type, it makes sens… maybe… not sure πŸ˜…
<FromGitter> <erdnaxeli:cervoi.se> well actually having two different behavior of zip and zip with a block is confusing
<FromGitter> <erdnaxeli:cervoi.se> but maybe that's ok with iterators because there is `each` to give a block?
trepanger has joined #crystal-lang
<FromGitter> <Blacksmoke16> > Raises an IndexError if any of others doesn't have as many elements as self. See #zip? for a version that yields nil instead of raising.
<FromGitter> <erdnaxeli:cervoi.se> Yep, but as zip without a block (the Iterator's implementation) does not, that's confusing
<FromGitter> <Blacksmoke16> it should
<FromGitter> <Blacksmoke16> thats what the docs say
<FromGitter> <Blacksmoke16> id say thats a bug?
<FromGitter> <Daniel-Worrall> Who would I talk to for permssion for a 2-way bridge between gitter and the unofficial discord? Specifically a single channel in there
<oprypin> Daniel-Worrall, i'd probably be the person. i would block existence of multiple 2-way bridges outright. 3-way or bust
<FromGitter> <Daniel-Worrall> Wouldn't the irc bridge forward anything sent?
<oprypin> for an example of how "amazing" that looks, see https://gitter.im/nim-lang/Nim
<oprypin> anyhow, with Gitter now having native clients and bridges, there's little reason for the discord
<hightower3> Hey what's the situation re. some profiling tools?
<raz> hmm, in a macro, is there a way to iterate over all values of an enum? (i want to generate a method for each)
<oprypin> raz, ::Constants
<hightower3> thank you kindly oprypin
<raz> oprypin: merci beaucoup! πŸ™‡β€β™‚οΈ