<FromGitter>
<watzon> Ok shouldn't this `"Abc_one_two_three".gsub(/_(\w)/, "\\1".upcase)` return `"AbcOneTwoThree"`? It doesn't, and I'm wondering why not.
<FromGitter>
<watzon> Maybe there's a better way to do this, but I basically just want to replace any underscore + letter with a capital letter
<FromGitter>
<tenebrousedge> `"\\1".upcase` isn't a proc
<FromGitter>
<tenebrousedge> it's an upcased string
<FromGitter>
<tenebrousedge> pass a block
<FromGitter>
<Blacksmoke16> Isn't that what camelcase is
<FromGitter>
<tenebrousedge> plus I think you want `capitalize`
<FromGitter>
<gdotdesign> I'm looking for intersperse method for arrays but I cannot find one, is there one with an other name or it's just not in the stdlib?
<FromGitter>
<ImAHopelessDev_gitlab> 4:34 LOL :D
<FromGitter>
<grkek> oprypin thats some wonderful news
<oprypin>
:>
<FromGitter>
<grkek> Props to you for such nice work
<FromGitter>
<ImAHopelessDev_gitlab> wow, linking crsfml is nice. this is a great foundation
<FromGitter>
<ImAHopelessDev_gitlab> i just installed the vs build tools last night too (had to fiddle around with some godot source code). this is like perfect timing. i'm pumped to fiddle around with this all day, thanks @oprypin !
<jhass>
the feature was intended like that, it's just abusing an implementation detail
<jhass>
*was not, duh
<FromGitter>
<grkek> Yeah, I see
<FromGitter>
<grkek> as fast as I change the int to string
<FromGitter>
<grkek> it fails
<jhass>
yeah, since a, b = c is really just a syntax level rewrite to a = c[0]; b = c[1]
<jhass>
what would you expect the result to be anyhow with string keys?
<FromGitter>
<grkek> I wanted something like the elixir pattern matching
<FromGitter>
<ImAHopelessDev_gitlab> i tried elixir, then took an arrow to the brain. i can't comprehend functional languages :(
<FromGitter>
<grkek> It is really comfy
<FromGitter>
<ImAHopelessDev_gitlab> i don't understand how objects and states exist. in crystal, we have a class/struct/hash to hold values. in those languages, i can't comprehend what holds what, it seems like nothing holds anything and it's just functions returning values 24/7.
<yxhuvud>
I think that is the point!
<FromGitter>
<grkek> That sums it up 90% of the time
<FromGitter>
<grkek> You just push data around until you get results
<FromGitter>
<ImAHopelessDev_gitlab> that's where my brain goes blank. let's say you have a player, they need to store `user_id`, `x`, and `y` values. throw in an inventory too (2d array). how in the world do you keep track of that stuff if you're in a quantum vacuum of functions
<FromGitter>
<grkek> if yes can you link the source where you found that?
<FromGitter>
<alex-lairan> Dude, you just broke the internet :p
<FromGitter>
<grkek> It's basically functions with the same return type just recursing into eachother
<FromGitter>
<grkek> You can call it function orgy if you want to
<FromGitter>
<ImAHopelessDev_gitlab> sounds like a possible new fetish
<FromGitter>
<grkek> MMM OH YEAH RECURSE RIGHT THERE OOOH IM COOOMING
<FromGitter>
<grkek> just about right
<FromGitter>
<ImAHopelessDev_gitlab> rofl
<FromGitter>
<naqvis> rofl
<FromGitter>
<ImAHopelessDev_gitlab> "can you go get that abstract lube bottle, honey? thanks", i need some pattern matching and recursive down there, i'm about to statically allocate some structs. we can use the heap later
<FromGitter>
<grkek> Jesus man
<FromGitter>
<ImAHopelessDev_gitlab> .. we really need to clean up all this memory the gc left behind
<FromGitter>
<grkek> COME ON MAN
<FromGitter>
<ImAHopelessDev_gitlab> 😆
<FromGitter>
<naqvis> girng you are a genius lmao
<FromGitter>
<naqvis> rofl
<FromGitter>
<grkek> All of this context switching is hurting my back :^)
<oprypin>
straight-shoota: did u really just rebase 10 commits and force push instead of simply merging
<FromGitter>
<straight-shoota> yes
<FromGitter>
<straight-shoota> why not?
<FromGitter>
<straight-shoota> IMO the changes are easier to track that way
<FromGitter>
<ImAHopelessDev_gitlab> :D :D :D Crystal time all day today
<oprypin>
@straight-shoota: no they're not?
<oprypin>
you literally change what some other user made and now we're supposed to trust you that it's the same
<oprypin>
a merge conceptually represents what's happening. rebase is like doing 10 merges and discarding the originals
<FromGitter>
<naqvis> Just posted crystal-fnv (https://github.com/naqvis/crystal-fnv). Crystal implementation of Fowler–Noll–Vo hash (FNV) hash. Provide 32, 64 and 128bit implementation of FNV-1 and FNV-1a ❤️
<FromGitter>
<straight-shoota> Yeah, conceptually that's right. But I find it hard to track in the GitHub UI. The changes are supposed to be applied on current master, not on some ancient state.
<FromGitter>
<straight-shoota> An insanely huge diff and you can't tell which parts of the changes are simply representing the advanced head and what's merge conflict resolution. With rebase the conflict resultion is in every single commit which can be compared to the previous commit before the rebase, if you want to verify.
<FromGitter>
<straight-shoota> But I actually don't think attribution matters much. The PR needs to be approved in total, no matter who wrote the changes. And it will be squash merged an attribute both the original author and me.
<FromGitter>
<j8r> Good job @naqvis — always ready to crush new algos 😮
<FromGitter>
<j8r> You know, you can just put all *.cr file in `src/`
<FromGitter>
<naqvis> thanks @j8r
<FromGitter>
<naqvis> yeah true, but i kind of like organizing files in sub-folders 😆
<FromGitter>
<naqvis> just a personal preference
<FromGitter>
<j8r> Lol – you're the boss of your projects at the end :P
<FromGitter>
<j8r> May intereset @ImAHopelessDev_gitlab – I won't use it yet
<FromGitter>
<j8r> Just use raw UDP, then see for further optimizations
<FromGitter>
<naqvis> sounds interesting, won't hurt to look into the details of how they have achieved the reliability of tcp over udp
<FromGitter>
<ImAHopelessDev_gitlab> I gave my life to TCP a few years ago
disruptek has joined #crystal-lang
<FromGitter>
<ImAHopelessDev_gitlab> why use UDP when i can just take a plane to the recipient's house? *taps head*
<FromGitter>
<tenebrousedge> the best thing about UDP jokes is I don't care if you get them
<FromGitter>
<ImAHopelessDev_gitlab> LOL!
<disruptek>
i need to make a desktop app similar to adobe premiere but with higher performance and low memory footprint with gui as beautiful as premiere. this would be the only selling point for us. this would be my first cross platform desktop app development and i don't want to fail. seeking help. please guide me.
<FromGitter>
<ImAHopelessDev_gitlab> if i were you, i'd use winforms with visual basic, then bind it to rust
<disruptek>
what are my options for gui?
<FromGitter>
<Blacksmoke16> that thread goes over the current state of things, id read thru that
<FromGitter>
<tenebrousedge> Windows support is also mostly aspirational at this point
<disruptek>
we will have a large team of developers.
<FromGitter>
<Blacksmoke16> are always free to try to put together a prototype to see how things go
<disruptek>
my job is to choose the tech stack.
<FromGitter>
<Blacksmoke16> but GUI + windows im not sure will fair to well
<FromGitter>
<Blacksmoke16> too*
<disruptek>
it needs to have a low memory footprint as well.
<disruptek>
i5 cpu with 8gb of memory.
<FromGitter>
<Blacksmoke16> well to be clear, crystal doesnt fully support windows atm. so if thats a requirement then its a non starter
<disruptek>
it's okay; we expect development to take at least 6 months.
<FromGitter>
<tenebrousedge> okay, so I did laugh out loud at that
<FromGitter>
<Blacksmoke16> im happy you want to/are looking into using Crystal, but assuming windows will be supported fully in 6months is unfortunately not really realistic
<FromGitter>
<Blacksmoke16> maybe it will, but who knows
<FromGitter>
<Blacksmoke16> but for if a good GUI lib and window are requirements for your project, i just dont think its the best option
<disruptek>
what should i use?
<jhass>
> We gonna be better than adobe in one of their core products that they have 30 years experience on. In 6 months.
<jhass>
I'm sorry, but...
<FromGitter>
<Blacksmoke16> i dont know, thats your job to figure out :p
<FromGitter>
<Blacksmoke16> does go have any good ui libs?
<FromGitter>
<naqvis> nah, go touts itself more on server side, that's why major player in cloud world are built on top of golang
<FromGitter>
<ImAHopelessDev_gitlab> not sure why you just don't write this in html 5 and ship it with electron
<FromGitter>
<tenebrousedge> that's probably not a high-performance path
<FromGitter>
<Blacksmoke16> other requirement was low memory usage :trollface:
<FromGitter>
<ImAHopelessDev_gitlab> give your developers a run for their money
<FromGitter>
<tenebrousedge> the best option is probably to use C++, which is what Adobe did
<FromGitter>
<tenebrousedge> there is no best option for duplicating the 30 years of work that went into that codebase though
<FromGitter>
<naqvis> agree and use any of the GUI toolkit as almost all of them are built on C/C++
<FromGitter>
<tenebrousedge> this is a terrible idea and a waste of whoever's money is funding it
<FromGitter>
<tenebrousedge> but if the money is already committed and the developers are hired, pick whatever technology you want to work with at your next job
<FromGitter>
<ImAHopelessDev_gitlab> @Blacksmoke16 Actually, the more memory an application uses means it has higher performance. This is why a lot of AAA games are shipped with Electron, and also high quality IDEs like VSCode too. (backed by a multi-billion-dollar company)
<FromGitter>
<watzon> I hope LibUI keeps going strong. It would be nice to have a sane, cross platform GUI lib.
<FromGitter>
<tenebrousedge> low memory use is not necessarily correlated with performance, but saying higher memory use == higher performance is overstating the case somewhat
<oprypin>
i am surprised though. github has a condensed view of merges but for some reason it's not kicking in there
<oprypin>
the condensed view would show *at most* the files that were changed in both master and that branch
<FromGitter>
<tenebrousedge> ah. Well VSCode is a pretty good editor, but what's the saying about pigs and sufficient thrust?
<FromGitter>
<ImAHopelessDev_gitlab> @watzon has left the chat
<oprypin>
btw just use qt
<oprypin>
qt5.cr project got literally everything right
<oprypin>
it's just abandoned, no biggie
<disruptek>
that's what i should use for the ui?
<FromGitter>
<Blacksmoke16> it sounds like you just want to use Crystal
<disruptek>
well, i have to decide.
<FromGitter>
<Blacksmoke16> yes and im pretty sure the consensus is that for your needs Crystal isnt the best option
<FromGitter>
<Blacksmoke16> maybe a few years from now it'll be different but :shrug:
<FromGitter>
<tenebrousedge> Crystal GUI is WIP. Crystal on Windows is WIP. Writing a cross-platform GUI Crystal app is not practical, definitely not in six months
<FromGitter>
<ImAHopelessDev_gitlab> do what oprypin says
<FromGitter>
<ImAHopelessDev_gitlab> qt got a nice WYSIWYG form designer too
disruptek has left #crystal-lang ["-twitch #disruptek"]
disruptek has joined #crystal-lang
<disruptek>
oops.
<disruptek>
i can't find the qt library for crystal.
<oprypin>
it's the best but it's not currently in a working state
<FromGitter>
<lagerfeuer> back with another question: I've been working on something where I use a lot of subclasses, and I came across an issue. How would I get something like this to work? https://play.crystal-lang.org/#/r/8xip
<FromGitter>
<lagerfeuer> I could change the initialize method, but is there another way?
<FromGitter>
<lagerfeuer> ahhh, I see, thanks guys. Still pretty new, but apparently there is an issue for everything already :D
<FromGitter>
<lagerfeuer> the first solution will change the return type of the function tho: https://play.crystal-lang.org/#/r/8xp6, where the second doesn't.
<FromGitter>
<kinxer> What I came up with was `new_size = 4 * (slice.size // 4 + 1)` (otherwise the same), but that doesn't work if it's not a `Bytes`.
<jhass>
are you sure?
<FromGitter>
<kinxer> Well, I'm pretty sure `slice.size` gives the number of elements, not the number of bytes.
<FromGitter>
<kinxer> I did just find `slice.bytesize`, though, so that should work.
<jhass>
but pointer is generically typed too, why wouldn'T realloc operate on its type sizeof?
<jhass>
open an issue, I'll tag it with bug,formatter and MakeNowJust will send a pull request 10 minutes later :D
<oprypin>
😂
<FromGitter>
<kinxer> Re `realloc`, I think it still depends on `T` (and so won't reallocate that many bytes, but space for that many elements; see https://crystal-lang.org/api/master/Pointer.html#realloc(size:Int)-instance-method ). It's probably not an issue, though, except if you're using 16-bit-width elements, since anything larger will already align at multiples of 4 bytes and anything smaller (i.e. 1-byte data) will work with
<FromGitter>
... the `realloc`. I guess you'd have to check the size to determine what to do, though, which isn't particularly simple.
<FromGitter>
<watzon> Yeah it's `Bytes` @kinxer
<FromGitter>
<kinxer> Oh. With bytes, just do what @jhass originally suggested.
<jhass>
with anything do it!
<jhass>
it's fine
<jhass>
I mean I never tested this
<jhass>
or used realloc in my life in any language
<jhass>
but I'm pretty sure it's fine!
<FromGitter>
<naqvis> jhass that will break on numbers below 4
<FromGitter>
<kinxer> @jhass I guess you'd just have to turn it into `Bytes` and do the alignment before serializing it (or whatever you're doing that requires the alignment).
<jhass>
but would it always match up to the full a valid item length in the last element?
<FromGitter>
<kinxer> Oh, certainly not always.
<FromGitter>
<kinxer> If, for example, you need the byte alignment so you can encrypt your data, you'll just need to know what format the data should be in when you decrypt it and trim off that extra.
<FromGitter>
<ImAHopelessDev_gitlab> how the heck do i change my avatar on gitter
<FromGitter>
<Blacksmoke16> prob update it on gitlab
<jhass>
come too the IRC side of things, no bothering with avatars!
<FromGitter>
<ImAHopelessDev_gitlab> last time went on irc, they got my ip and ddos'd me hard
<FromGitter>
<ImAHopelessDev_gitlab> my xfinity router exploded
<jhass>
didn't happen to me in like 14 years now, but ok. get a cloak
<FromGitter>
<sardaukar> is there any way to render a template with Kilt using a dynamic name?
<FromGitter>
<sardaukar> `Kilt.render` is a macro so it runs at compile time, right? so it's impossible?
<jhass>
oh, the mIRC tripped me off :D
<FromGitter>
<tenebrousedge> @sardaukar I don't know anything about Kilt, but from what you just said, yes, that's not possible. But you should be able to do something else maybe?
<FromGitter>
<sardaukar> I just want to render an `.ecr` file with a name given by a config settings on a TOML file
<FromGitter>
<sardaukar> I guess I could make a macro that renders *all* present `.ecr` files and then pick the right one...
<FromGitter>
<tenebrousedge> could be a thing
<FromGitter>
<ImAHopelessDev_gitlab> @tenebrousedge removed gitlab's avatar (default's to gravatar). setup an avatar on gravatar. did hard cache reload, now i see it, thanks
<FromGitter>
<tenebrousedge> :plus1:
ur5us has joined #crystal-lang
ur5us has quit [Ping timeout: 256 seconds]
<FromGitter>
<ImAHopelessDev_gitlab> guard clauses are one of the best things i've ever experienced in a programming language
<FromGitter>
<ImAHopelessDev_gitlab> i just found out about them when istarted using crystal
<FromGitter>
<tenebrousedge> <__<
<FromGitter>
<ImAHopelessDev_gitlab> they are an aesthetic improvement as well, along with readability
<FromGitter>
<tenebrousedge> they are for sure a good idea
ur5us has joined #crystal-lang
_ht has quit [Quit: _ht]
<hightower2>
Hey folks, could you shed some light on the following problem (using Crystal 0.34 if it matters at all)...
<hightower2>
I call a function with 3 arguments, of which the last one is literal integer 20. And the function that I call simply returns a fixed value, that's the only thing it does. Like, return 600
<hightower2>
(this is because I've removed all code just to test this problem)
<hightower2>
now, using Benchmark module, I see this function call executes over 700M times per second
<hightower2>
But, if instead of this int 20 I call it with 20+1
<hightower2>
then performance drops to only ~24M calls per secon
<hightower2>
second*
<hightower2>
what could be the underlying reason for that?
<FromGitter>
<tenebrousedge> does it make a difference between `20 + 1` and `20.succ` ?
<hightower2>
.succ too reduces performance to ~30M/s
<FromGitter>
<Blacksmoke16> whats the code?
<hightower2>
ok let me try extract into a play example
<FromGitter>
<tenebrousedge> I'm suspicious of just about any results from `Benchmark`
<FromGitter>
<Blacksmoke16> could just be the overload of overflow checking
<hightower2>
(same argument types are used as in my real code)
<hightower2>
but the play example does not exhibit this problem... it is lower performance in general, but does not show drastic difference
<FromGitter>
<Blacksmoke16> using `--release` in your actual code?
<hightower2>
yes yes, of course
<hightower2>
the only difference is arg being 20 versus 20+1
<FromGitter>
<Blacksmoke16> `try with &+`
<FromGitter>
<Blacksmoke16> `20 &+ 1`
<hightower2>
Using that form gets performance back to ~700M/s
<FromGitter>
<tenebrousedge> o.o
<FromGitter>
<Blacksmoke16> so yea, is just the overhead of overflow checking
<hightower2>
how could I "fix" that? by possibly defining an explicit type of that function arg or something?
<hightower2>
and/or how would I be able to tell when this check would kick in and when not?
<FromGitter>
<Blacksmoke16> anytime you dont use the `&` prefixed operator
<jhass>
it really doesn't have to do with the method call, benchmarking `20` vs `20+1` should show the same issue
<jhass>
the overflow check adds enough code for LLVM to not eliminate or precompute
<jhass>
also these kind of microbenchmarks are less than useful, I don't know why you spend on time on that
<FromGitter>
<tenebrousedge> ^
<hightower2>
jhass yes but I just did benchmark x = 20 vs x = 20 + 1 and it was nowhere near that severe... in fact 20+1 was faster than 20, so the difference is within measurement error
<jhass>
probably eliminated
<hightower2>
but 35M vs 770M drop in performance is not a micro benchmark, this is significant
<FromGitter>
<tenebrousedge> the question is whether that 770M number represents anything real
<FromGitter>
<tenebrousedge> which I doubt
<hightower2>
it does... my complete function was running ~700M+ times per second.. compared to ~30M if I sent variable+1 as argument
<hightower2>
that's how I noticed it...
<FromGitter>
<tenebrousedge> bounds checking isn't a wildly intensive operation. If what your code is doing is less work for the CPU than bounds checking, then what exactly is it doing?
<FromGitter>
<tenebrousedge> what non-noop thing can your CPU do 770M times per second?
<hightower2>
well that's what it tells me... It runs the test for 5 seconds before reporting the results
<hightower2>
the function calls LibC.strstr a couple times, and does some simple math
<hightower2>
let me undo all the code removal that I did to test this problem, and then I'll tell you exactly what's the difference for the complete function
<jhass>
add x.report("empty") { ) to your benchmarks and you see you're wasting your time really
<FromGitter>
<tenebrousedge> the only thing that matters to me is how code performs under real-world conditions. Profiling > benchmarks
<jhass>
^
<FromGitter>
<tenebrousedge> the odds that this apparent bottleneck is actually a real-world limiting factor are next to nil
<jhass>
700M iterations seems to be about the overhead of the IPS benchmark harness, you're not testing anything at that point
<hightower2>
hmm..
<FromGitter>
<tenebrousedge> `0.0B/op` is another good sign that your tests are not effective
<jhass>
well... allocation free code is nice code :D
<jhass>
but there too as for anything. Don't worry. Identify the bottlenecks in your application. Spend time on optimizing there
<jhass>
making some micro thingy 10x faster is completely useless if some other part of your application take 10x the time and everything has to wait for it anywayss
<FromGitter>
<tenebrousedge> "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our
<FromGitter>
... opportunities in that critical 3%."
<hightower2>
maybe the Benchmark module isn't accurate when functions do LibC calls, is that possible?
<jhass>
unlikely
<jhass>
why do you care about this? Did you identifiy a bottleneck? How, why? Is the total runtime of your program slower than you expected? How did you come up with that expectation?
<hightower2>
I tested different algorithms through the benchmark module, to decide which one I'm gonna use
<jhass>
and why did you decide to different algorithms? How did you decide that performance is more important for this algorithm over qualtitative measures like clarity and (being sure of) correctness?
<jhass>
*to try
<hightower2>
well that's theoretical discussion, I did not find that clarity of correctness were affected. It is only possible that Benchmark's results were misreporting actual values for reasons unknown to me
<FromGitter>
<tenebrousedge> I don't want to say that the Benchmark module should be renamed the BS module, but testing algorithms on large real-world data sets is probably a better idea
<hightower2>
I used that module in Ruby (I think it's called the same) with good success
<FromGitter>
<tenebrousedge> Crystal is not Ruby
<FromGitter>
<tenebrousedge> Ruby doesn't have LLVM to lie to you about what it's doing
ur5us has quit [Ping timeout: 256 seconds]
zorp has quit [Read error: Connection reset by peer]
return0e has quit [Read error: Connection reset by peer]
<hightower2>
but what can it do that'd be unexpected? apply optimizations somewhere to e.g. not even call the function when the result is not used?
<hightower2>
or what?
<FromGitter>
<tenebrousedge> yes
zorp has joined #crystal-lang
<FromGitter>
<tenebrousedge> it can absolutely do that
return0e has joined #crystal-lang
Liothen has quit [Read error: Connection reset by peer]
Liothen has joined #crystal-lang
commavir has quit [Ping timeout: 265 seconds]
<hightower2>
well, I see your point, but... maybe I just don't understand why in e.g. two identical lines like benchmark(func1(arg)) and benchmark(func2(arg)), it'd choose not to call one but optimize away the other
<hightower2>
s/not to/to/g
commavir has joined #crystal-lang
<jhass>
well of course it needs to prove the call is side effect free
<FromGitter>
<tenebrousedge> understanding exactly how LLVM is going to interpret your benchmark is a complicated subject, that I don't have a great handle on personally. Writing effective benchmarks using `Benchmark` is frequently much harder than it seems
<jhass>
Writing effective benchmarks is hard, period. `Benchmark` does not and does not try to make it any easier. It only tries to make writing benchmarks in general less repetitive. That's all
zorp has quit [Ping timeout: 250 seconds]
ur5us has joined #crystal-lang
tane has quit [Quit: Leaving]
ur5us has quit [Read error: Connection reset by peer]
ur5us has joined #crystal-lang
alexherbo2 has quit [Remote host closed the connection]