qard has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
greengriminal has joined #crystal-lang
<FromGitter>
<watzon> What would be the easiest way to fix floating point math? I don't care about it being super accurate, but I don't want to have a number like 0.001000000000047740 when it should just be 0.001
<FromGitter>
<watzon> Is there a way to just format the float so that it only shows the amount of decimal places Floats are accurate to?
greengriminal has quit [Quit: This computer has gone to sleep]
redIcey has joined #crystal-lang
redIcey has quit [Client Quit]
aarongough has joined #crystal-lang
<FromGitter>
<watzon> I guess I can just do this `"%.10g" % 0.001000000000047740`
<aarongough>
Hey guys! I have what may be a dumb question, but googling for the answer has eluded me... What's the purpose of `Object#.not_nil!`?
<FromGitter>
<watzon> It asserts that something is not nil and allows you to bypass the compiler's nil checking
<FromGitter>
<watzon> But if the object does end up being nil it will throw an error
<aarongough>
Ah ok.. I might submit a PR for the docs to clarify, I am using a regex with named captures, and all the docs have code like `string.match(regex).not_nil!["capture"]
<aarongough>
It was very non obvious from the docs what it was supposed to do :D
<aarongough>
Thanks for the quick response!
<FromGitter>
<bew> You should handler the case where the regex does not match (will return nil)
<FromGitter>
<watzon> No problem. I like to help where I can haha.
<FromGitter>
<watzon> And @bew is correct. Definitely don't use `not_nil!` unless you have to. If something could be nil you should handle that possibility.
vivus has quit [Quit: Leaving]
<aarongough>
@bew Right so something like `string.match(regex).not_nil?["capture"]?` and then check for nil
<aarongough>
@watzon so the issue is that without `not_nil!` I always get the error: undefined method '[]' for Nil
<FromGitter>
<watzon> Right. You need to do a nil check instead. The problem is that `string.match` will return nil if nothing matches
<FromGitter>
<watzon> so first you have to check if the result is nil, and then handle that possibility. The easiest way to do so is to have a fallback value, but that doesn't work for every case. So `str.match(/some-regex/) || "default"`
<FromGitter>
<watzon> That way `my_var` is always of the type `String` and not (String | Nil)`
<aarongough>
Ok, so `"foo far".match(/(?<first>foo)/)["first"]` throws `undefined method '[]' for Nil` because the return type of `match` is (MatchData|Nil)
<aarongough>
I think I understand a bit better now, thanks!
<FromGitter>
<marksiemers> The compiler is smart enough to know that `match` won't be `nil` in the if branch
<aarongough>
Interesting! Makes sense that I'd have to handle both possible return values, just trying to bridge the cognitive gap to the new language :D
duane has quit [Ping timeout: 256 seconds]
jnyw has joined #crystal-lang
aarongough has quit [Ping timeout: 260 seconds]
sz0 has joined #crystal-lang
qard has joined #crystal-lang
qard has quit [Remote host closed the connection]
qard has joined #crystal-lang
qard has quit [Quit: qard]
qard has joined #crystal-lang
sz0 has quit [Quit: Connection closed for inactivity]
qard has quit [Read error: Connection reset by peer]
qard_ has joined #crystal-lang
qard_ is now known as qard
qard has quit [Quit: qard]
qard has joined #crystal-lang
<FromGitter>
<watzon> Yeah, really what we need in Crystal is good patten matching. Rust and Elixir both have very good pattern matching and it makes dealing with that stuff a breeze.
<FromGitter>
<watzon> The Bool struct should definitely have a `to_i` method
Ven`` has joined #crystal-lang
Ven`` has quit [Ping timeout: 252 seconds]
<FromGitter>
<watzon> So how can I take an object with the type `JSON::Any` and parse it into an object with a `JSON.mapping` on it?
<FromGitter>
<watzon> Doing `MyJSONObject.as(OtherObject)` doesn't seem to be yielding results.
<FromGitter>
<watzon> Got it working with `from_json` and `to_json`. Seems really inefficient to convert JSON to a string and then parse it again though.
<FromGitter>
<HCLarsen> Hey everyone. My newest Crystal Blog entry. I tackled TDD in Crystal with minitest.
<FromGitter>
<watzon> Is it possible to compose objects with JSON::Any? For instance I have one object that has 10 fields and another object that shares 8 of those same fields. Can I combine them somehow?
Yxhuvud has quit [Read error: Connection reset by peer]
Yxhuvud has joined #crystal-lang
<FromGitter>
<asterite> watzon: why don't you parse directly into the final object? maybe you need to parse to a different type depending on something else. In that case I I recommend using `{type: String, converter: String::RawConverter}`. That will keep the raw string and from there you can parse it normally, and it should be the most efficient way (it's just parsed once)
sz0 has quit [Quit: Connection closed for inactivity]
<FromGitter>
<watzon> @asterite yeah I figured it out haha
<FromGitter>
<watzon> How do you compile with no gc? I'm trying to get a hello world as small as possible for size comparison.
<linuksz>
Doesn't the generic define both Array(String) and Array(Nil), similarly how RX14 did it with the 'add' method in https://play.crystal-lang.org/#/r/3gp0?
<RX14>
yes, that's the bug
<RX14>
that it doesn't see "both" overloads
<RX14>
even though they're voth there
<RX14>
both*
<linuksz>
So should we create an issue?
<RX14>
i guess
<crystal-gh>
[crystal] MakeNowJust opened pull request #5648: Don't use heredoc inside interpolation (master...fix/crystal/dont-use-heredoc-inside-interpolation) https://git.io/vNMVT
<linuksz>
oprypin: what do you think about RX14's examples?
<oprypin>
[14:48:09] <oprypin> RX14, OK good example, I had the same thought and I thought it wouldn't work
<oprypin>
[14:48:16] <oprypin> so you proved it
<linuksz>
oprypin: oh, ok.
<linuksz>
RX14: Could you create the issue? You have proved that it is a bug with your examples.
<FromGitter>
<Dillybob1992> "non-switchable non-generational Boehm GC. There is a way to live without allocations (use structs, slices and other value types), but all classes are GC-d. " what does this user mean by this? isn't classes being GC'd a good idea??
<oprypin>
Dillybob1992, garbage collection is a known performance sacrifice but it makes the language much easier to use
<oprypin>
and the currently used GC seems to be showing some problems
<FromGitter>
<Dillybob1992> rx14 and paberiero explained to me some gc stuff yesterday. i still am quite confused on why the memory stays the same and doesn't go down, when it gets garbage collected. does the garbage collection just make it so that memory can be "used again", but doesn't "free the memory"?
<oprypin>
sure
<FromGitter>
<Dillybob1992> ok makes more sense
<FromGitter>
<Dillybob1992> so it's very different "freeing memory" compared to "letting it be used again"
<RX14>
"paberiero"
<FromGitter>
<Dillybob1992> couldn't remember his name :P
aroaminggeek has joined #crystal-lang
<RX14>
it's Papierkorb
<oprypin>
Dillybob1992, it's "letting the current process use it again" vs "letting the OS use it again"
<RX14>
@Dillybob1992 you can think of it as "pools" of memory
<FromGitter>
<Dillybob1992> is there a way to ever de-allocate the memory though? i remember rx14 saying something about a method u can call
<RX14>
obviously you're limited to the amount of ram in your system
<RX14>
thats the pool of memory available to the OS
<RX14>
and the kernel dishes out parts of RAM to itself and applications that want it
<RX14>
applications can say "I need some memory"
<RX14>
and "I don't need this memory any more"
<RX14>
and all is well
<RX14>
however, in crystal, we use a GC
<RX14>
this GC maintains a seperate private pool of memory for itself
<RX14>
it allocates objects out of this smaller seperate pool of memory that it asks the OS for
<RX14>
so the GC asks the OS for larger chunks of memory
<RX14>
then gives little bits of those chunks out for objects
<RX14>
this increases performance because we don't want to go to the OS for every tiny object allocation
<RX14>
(asking the kernel for more memory is expensive)
<RX14>
the GC knows what part of it's internal pool of memory is unused, and which parts are used
<RX14>
so it knows which parts of it's internal pool it can reuse for new objects
<RX14>
when there's no more memory it asks the OS to expend it's pool
<RX14>
however, the specific GC we're using never tells the os "i'm not using this part of my memory pool any more"
<FromGitter>
<Dillybob1992> ohhhh... i see
<RX14>
and so the amount of memory in the GC pool of memory never goes down, it always goes up or stays the same
<RX14>
this means the GC sees large parts of it's internal memory pool as free and can allocate those to crystal objects
<RX14>
however the OS never sees it as free again
<RX14>
and so you don't see it when you look in say htop
<RX14>
but there is a large portion of the "reserved" memory of the process that's free
<RX14>
it's not that the OS doesn't know that
<RX14>
does that help?
<FromGitter>
<Dillybob1992> yes, just took a s/s of message log, appreciate it
<RX14>
np
<FromGitter>
<Dillybob1992> so just because crystal has that "reserved memory" some of it is still free to be used for other things. so it's not necessarily "actual ram being used", if you will? if i got that right
<RX14>
it has the reserved memory -and it's reserved in that only crystal can use it
<RX14>
however it's free for crystal to use even if you can't see that in htop
<RX14>
htop doesn't know about the GC
<RX14>
it can only tell you the pool size
<RX14>
not how much of the GC memory pool is used
<FromGitter>
<Dillybob1992> is it possible to tell the GC "i'm not using this part of my memory pool any more"? or would that be really expensive / void the entire use of a GC
<RX14>
but you don't know about the memory pool
<FromGitter>
<Dillybob1992> to the os***
<RX14>
as far as you're concerned you just magically allocate objects and they're cleaned up
<RX14>
the thing is, the memory pool is really fragmented
<RX14>
so the memory pool has bits and pieces of it used all over the place
<RX14>
and small holes in between which are unused
<RX14>
you can't just tell the OS "these holes are free", you can only tell the OS that larger chunks of memory are free
<RX14>
so its very difficult for the GC to do
<RX14>
and due to... reasons the GC can't defragment the heap easily
<FromGitter>
<Dillybob1992> i think i got it...
<FromGitter>
<Dillybob1992> i hope
chaser93 has joined #crystal-lang
<FromGitter>
<l3kn> @Dillybob1992 There is a rubyconf talk about why moving objects is so hard (in ruby, but the problems are probably the same), might be interesting for you https://youtu.be/8Q7M513vewk?t=18m28s
<RX14>
@Dillybob1992 you don't reeally need to worry about any of this though
<RX14>
it's super interesting
<RX14>
but it's unlikely to affect how you use crystal much
<Papierkorb>
Rather, it shouldn't affect you much
<Papierkorb>
An optimization can easily turn into a deoptimization and/or worse code without necessity
<FromGitter>
<Dillybob1992> im just thinking about if i get a peak of high users, crystal will need to allocate that memory for those new connections. then, when they all log off, the allocation will still be there. so now the Hosting provider will look at my server (has 96% ram usage), while i have 5 players online. i just don't know what i'm not getting
<Papierkorb>
The hosting provider doesn't care, if you use 96% of your 512MiB, it's not their problem. If it's a problem to you is a different matter
<FromGitter>
<Dillybob1992> true. its all my ram just feels weird thinking about that
<Papierkorb>
But are you really already using half a gig of ram with 5k lurking connections?
<FromGitter>
<Dillybob1992> that's what i dont get, since it's garbage collected im not
<FromGitter>
<Dillybob1992> but the usage stays the same!
<FromGitter>
<Dillybob1992> what is the Difference...
<Papierkorb>
As RX explained above. My question goes towards why you need that RAM in the first place. Is the game state huge?
<Papierkorb>
Are you storing *tons* of data per connection?
<FromGitter>
<Dillybob1992> well, for my masterserver not so much, gameserver one will though. Example, the Player class has properties (hp, mana, level, rpg stats, etc) that all get memory allocated on Player.new. and increase if a lot of players connect. then, when the players log off, that memory will NOT be used because it'll be garbage collected, but it will show the amount of ram allocated? ⏎ ⏎ So, there is a difference
<FromGitter>
... between memory allocation, pool, and usage? so when you look at the "reserved ram" for crystal, that's just its memory pool, not necessarily actual "memory being used"?
<FromGitter>
<bew> What do you want to use this for?
vivus has joined #crystal-lang
<FromGitter>
<Dillybob1992> is there a way to deallocate the ram that class is used via a method? i can then just call it in finalize (when it gets gc'd)
vivus has left #crystal-lang [#crystal-lang]
<FromGitter>
<bew> No, not from Crystal
<FromGitter>
<bew> It would be the responsability of the GC to do that, but as explained before it is very difficult
<FromGitter>
<Dillybob1992> i see, yeah was just thinking of finalize never saw that until now :O
<FromGitter>
<PlayLights_twitter> Why would be EMail?
<FromGitter>
<codenoid> cuz he from kwnofguc land
<FromGitter>
<codenoid> i prefer Email
<FromGitter>
<codenoid> it's more beautiful
<FromGitter>
<marksiemers> I was reviewing a PR and the author has `EMail` and another reviewer asked if it should be `Email`. I think `Email` looks better but I wanted to see if there was a definitive answer. ⏎ If it were `ElectronicMail` I would expect a capital 'M' and for other hyphenated words, I would expect camelcase: `StateOfTheArt`
<FromGitter>
<marksiemers> So, I would guess the rule for hyphenated words is camelcase, but it doesn't look good for `EMail`.
<FromGitter>
<codenoid> also `class Email` is more /ɛsˈθɛtɪks/
<FromGitter>
<marksiemers> For the PR, before asking someone to change there code, I wanted to see if there was an agreed standard, so I could reference that, instead of just offering "I think `Email` looks better"
<FromGitter>
<codenoid> +1 `class Email`
<FromGitter>
<marksiemers> In the PR, it is actually used as a namespace, if that makes any difference: `EMail::Message.new`
<chaser93>
is there any way to send an email with crystal? in ruby theres SMTP
dragonkh has joined #crystal-lang
<dragonkh>
hi - if I have an instance of a class - and the class has an instance variable e.g. @name - is there any way I can get the content of the @name from the instance? e.g. myClass = MyClass.new ; puts myClass.instance_variables(:name) - or some such thing?
<dragonkh>
oh - myClass.@name works
<FromGitter>
<Dillybob1992> myClass.@name wat, looks like sorcery
<FromGitter>
<Dillybob1992> "secret syntax"? got any more sauce on that
<RX14>
@Dillybob1992 no because it's undocumented
<RX14>
and you should *never* use it
<dragonkh>
oh dear
<RX14>
you 100% of the time want to define a getter
<FromGitter>
<Dillybob1992> :(
<dragonkh>
well I just wanted to access it for testing purposes
<RX14>
not break the protection of OO and manually reach into an object
<FromGitter>
<Dillybob1992> i feel like a cool hippy when i use sorcery code though
<RX14>
dragonkh, that's one of the few times where it's acceptable
<FromGitter>
<Dillybob1992> lolz
<RX14>
you really need to print an ivar for puts debugging
<RX14>
thats fair enough
<RX14>
but never actually commit that code
<RX14>
@Dillybob1992 debugging code is swice as hard as writing it
<RX14>
so if you write code that you're just about smart enough to understand
<RX14>
you'll need someone twice as smart as you to debug it
<RX14>
so don't
<RX14>
write simple and easy to understand code
<dragonkh>
I really agree on that point
<dragonkh>
engineers love to "engineer" solutions hehe
<FromGitter>
<Dillybob1992> i agree...
greengriminal has joined #crystal-lang
greengriminal has quit [Client Quit]
<FromGitter>
<jwaldrip> What happens if I set a version in my shard.yml that does not match the tag?
<RX14>
stuff breaks
<RX14>
"undefined behaviour"
<FromGitter>
<jwaldrip> figured it wasn't good.
<RX14>
ideally it'd just error out
<FromGitter>
<watzon> Is it possible to fork a process by pid? Or to convert a process not created by Crystal to an instance of `Process`?
<frojnd>
Was just wondering... is there a nice way to populate an array into hash in crystal? Like in ruby I would do smth like this: Hash[["A","B","C"].map.with_index.to_a] and I would get following hash: {"A"=>0, "B"=>1, "C"=>2} Is there any one liners for crystal?
<RX14>
not really
<RX14>
the types don't work out
<RX14>
you can do
<RX14>
Hash.zip(arry, array.each_index.to_a) though
<FromGitter>
<Dillybob1992> brainf-word demo, crystal is a monster
<FromGitter>
<Dillybob1992> and rank 2-3 in most others too. wtf is kotlin btw?
<FromGitter>
<watzon> Kotlin is a language that runs on the JVM
<FromGitter>
<imonmyown> one of officials for android
<FromGitter>
<j8r> made by JetBrains, named from a russian city
<FromGitter>
<watzon> Much better language than Java
<FromGitter>
<watzon> But still runs on the JVM, so not really for me
<FromGitter>
<Dillybob1992> thx, never heard of it until now
alex`` has joined #crystal-lang
<FromGitter>
<imonmyown> guys if I use a generic class, say SomeClass(T), and if T is either Float32 or Float64, how do I specify a suitable T of zero?