ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Crystal 0.21.1 | Fund Crystal's development: | Paste > 3 lines of text to | GH: | Docs: | API: | Logs:
txdv has joined #crystal-lang
akwiatkowski has quit [Ping timeout: 260 seconds]
<FromGitter> <khepin> What’s a good way to make an insert statement to insert an undefined number of rows in a database with crystal-db? ⏎ I can prepare a statement that looks like: ⏎ ⏎ ```code paste, see link``` ⏎ ... []
<FromGitter> <khepin> I mean I would need to build that tuple if I want to be able to call ⏎ ⏎ ```db.exec query, *values``` ⏎ ⏎ I didn’t see a method in crystal-db that would take an array of arguments for a prepared statement []
sz0 has joined #crystal-lang
<FromGitter> <asterite> @khepin as far as I know you can pass an array
<Renich> Hey, Personas, where can I find a list of types?
sz0 has quit [Ping timeout: 240 seconds]
sz0 has joined #crystal-lang
<Renich> Ah, found the Literals section
<Renich> Sorry for asking dumb questions
snsei has joined #crystal-lang
<Renich> I need to pass a very long get to HTTP::Client. What should I do?
<Renich> It has like 12 parameters
<FromGitter> <fridgerator> `HTTP::Params.from_hash` ?
snsei has quit [Remote host closed the connection]
mjago has left #crystal-lang ["ERC (IRC client for Emacs 25.1.1)"]
mjblack has quit [Ping timeout: 268 seconds]
sz0 has quit [Quit: Connection closed for inactivity]
mjblack has joined #crystal-lang
snsei has joined #crystal-lang
snsei has quit [Remote host closed the connection]
kubaxvx has quit [Read error: Connection reset by peer]
kubaxvx has joined #crystal-lang
<Renich> @fridgerator: thanks!
<Renich> Are we, ever, going to see hashes like: [ a: "apple", b: 4, c: "yeah" ] ??
<Renich> Short form is so cool in hashes... It would rock
<FromGitter> <fridgerator> you mean short form like `a: "a"` instead of `:a => "a"` ?
<Renich> @fridgerator: yes
<FromGitter> <fridgerator> well the short form is named tuple syntax, but I still use them and then just `.to_h` at the end
<FromGitter> <fridgerator> *shrugs*
<Renich> @fridgerator: hmm... will RTFM
<FromGitter> <fridgerator> `{a: "a", b: 4}.to_h`
<FromGitter> <fridgerator> `{a: "a"}` still works, its just a NamedTuple not a hash
<Renich> @fridgerator: Ok
<Renich> @fridgerator: so, just append .to_h
<FromGitter> <fridgerator> yeah thats what I do
<Renich> @fridgerator: it works and all. Stii, wouldn't it be nice to have the good old: { a: 70, b: "stings" } syntax? I mean, I would dig it.
<FromGitter> <fridgerator> well then named tuples syntax would have to change, lol
<Renich> @fridgerator: yeah... oh well. Which is faster? Tuples or hashes?
<FromGitter> <fridgerator> probably named tuple, becuase they're immutable
<FromGitter> <fridgerator> and stack allocated
<Renich> @fridgerator: OK. Cool
<FromGitter> <khepin> @asterite indeed, it accepts an array ! Thanks.
<FromGitter> <khepin> Is Crystal’s JSON parsing going to be faster if I am parsing to a class with fully specified JSON.mapping than if I just call JSON.parse ? ⏎ I am receiving a little bit large JSON doc (6.5MB) and using `JSON.parse` is getting quite slow at this point. ~400ms to parse this.
<FromGitter> <matrixbot> `kodo 🌍` How do people install c libraries that they bind when they deploy to heroku?
<FromGitter> <matrixbot> `kodo 🌍` ah looks like you gotta create a custom buildpack
<FromGitter> <schoening> Sorry for the unrelated question, but are people here coding on macbooks? I never owned anything apple and am considering one, coz iphone development, and starting a new job. Good keyboard and overall experience? I may have to use windows at work due to visual studio :|
<FromGitter> <matrixbot> `kodo 🌍` coding on macos is comparable to linux
<FromGitter> <matrixbot> `kodo 🌍` some quirks but largely similar
<FromGitter> <schoening> And is the keyboard good?
<wmoxam> good compared to what? :p
<wmoxam> IMO all laptop keyboards are bad
<wmoxam> I'm not fond of the new Macbook keyboards vs the previous one, but I've only used it for a few minutes
<wmoxam> maybe it would grow on me
<FromGitter> <matrixbot> `kodo 🌍` I use external mechanical keyboard
<FromGitter> <matrixbot> `kodo 🌍` those sweet charry mx reds
<FromGitter> <matrixbot> `kodo 🌍` cherry*
<wmoxam> same, though with ALPS
<FromGitter> <matrixbot> `kodo 🌍` wmoxam: Why alps over cherry?
<wmoxam> why not? ;)
<FromGitter> <matrixbot> `kodo 🌍` dunno never used alps before
<FromGitter> <matrixbot> `kodo 🌍` im asking for serious
<FromGitter> <matrixbot> `kodo 🌍` do you like the response profile better?
<wmoxam> Old Apple mechs used alps. I have an Apple Extended II
<FromGitter> <matrixbot> `kodo 🌍` ah
<FromGitter> <schoening> well currently I am using a thinkpad from 2010
<FromGitter> <schoening> I think its that old. bought refurbished
<wmoxam> I do have a Cherry brown kb too
<FromGitter> <matrixbot> `kodo 🌍` wmoxam: TIL old apples used alps. I guess I have used them then, it's been awhile though
<wmoxam> @matrixbot Matias makes modern versions of Apple mech kbs (I also have one of those lol)
<wmoxam> the point is: I have too many keyboards. Send help
<FromGitter> <matrixbot> `kodo 🌍` you can never have too many mechs.
Qchmqs has joined #crystal-lang
akwiatkowski has joined #crystal-lang
<FromGitter> <phoffer> @schoening macs are great but some people don't like the new keyboards. I have a 2014 and I really like the keyboard. If you are interested in older models, Apple has an outlet with some good deals and a range of different model years
<FromGitter> <schoening> Yeah here in Denmark we got a "premium reseller" a lot of places so I can try the different ones. Thx.
<FromGitter> <schoening> Can you use the newest firmware or are you abandoned with a 3-4 year old macbook? @phoffer
<FromGitter> <phoffer> No mine will handle each new OS until probably 2019 at least. Apple is good about long support (whether the upgrades are worth it is another question lol)
<FromGitter> <schoening> Cool. Good to know.
<FromGitter> <schoening> Right now I'm trying to find some good sdl2 / opengl tutorials coz I would like to eventually try my luck at porting some of threejs to crystal. It's such a nice js library. Long way off tho
mark_66 has joined #crystal-lang
sija[m] has joined #crystal-lang
Kug3lis has joined #crystal-lang
akwiatkowski has quit [Ping timeout: 260 seconds]
Kug3lis has quit [Quit: Textual IRC Client:]
akwiatkowski has joined #crystal-lang
<crystal-gh> [crystal] ysbaddaden closed pull request #3875: Macro ancestors (master...macro_ancestors)
<crystal-gh> [crystal] ysbaddaden pushed 1 new commit to master:
<crystal-gh> crystal/master 857743a David Kuo: [Compiler] Get all ancestors of a type in macro
gloscombe has joined #crystal-lang
bjz has joined #crystal-lang
<travis-ci> crystal-lang/crystal#857743a (master - [Compiler] Get all ancestors of a type in macro): The build passed.
sija[m] has quit [Remote host closed the connection]
braidn[m] has quit [Write error: Connection reset by peer]
MatrixTraveler[m has quit [Read error: Connection reset by peer]
MatrixTraveler[m has joined #crystal-lang
<FromGitter> <domgetter> I'm trying to interface with the freeglut c library to make a small game engine, and I wasn't sure if this was the best way to call the C function from Crystal. Here is the docs on the function: and here is how I'm calling it:
<FromGitter> <domgetter> It didn't seem like a particularly "clean" way to do it, so I figured I'd ask if there was a better way to call a function that takes a char**
<Papierkorb> domgetter, `[ "foo", "bar" ].map(&.to_unsafe).to_a` produces a `Array(UInt8*)`, whose #to_unsafe will turn it into a `UInt8**`
<FromGitter> <domgetter> I will try that out, thank you!
<FromGitter> <domgetter> awesome, that feels way better
bjz has quit [Remote host closed the connection]
bjz has joined #crystal-lang
<RX14> @khepin yes, JSON/mapping is faster
<crystal-gh> [crystal] asterite pushed 1 new commit to master:
<crystal-gh> crystal/master 9be7840 Ary Borenszweig: Fixed #4202: missing debug location for pointer malloc primitive
gewo has quit [Remote host closed the connection]
<travis-ci> crystal-lang/crystal#9be7840 (master - Fixed #4202: missing debug location for pointer malloc primitive): The build passed.
<DeBot> (Module validation failed: inlinable function call in a function with debug info must have a !dbg location)
braidn[m] has joined #crystal-lang
sija[m] has joined #crystal-lang
sb89 has joined #crystal-lang
<sb89> Hi, a quick question, is it possible to specify the type of a splat in a method definition e.g I want this splat to be all strings?
snsei has joined #crystal-lang
jthecrystalfan has joined #crystal-lang
jthecrystalfan has quit [Client Quit]
sb89 has quit [Ping timeout: 260 seconds]
snapcase has quit [Remote host closed the connection]
<FromGitter> <asterite> sb89: yes, `*foo : String`
leonardschuetz has joined #crystal-lang
leonardschuetz is now known as KCreate
bjz has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<FromGitter> <domgetter> I'm trying to interface with a c function which returns a pointer to a struct, but I don't know that struct's members. If I try to define the struct in Crystal without members, the compiler complains that I can't make an empty struct. Any idea on where/what to read up on?
<FromGitter> <sb89> Thanks! There isn't anyway to specify a default value for splats, is that correct? I guess I'll just have to change it the type to an array, so that I can default it.
<KCreate> @domgetter How would you work with that struct in C then if you don't know the fields?
<FromGitter> <asterite> @domgetter Just use Void*
<FromGitter> <asterite> type MyStruct = Void*
<FromGitter> <domgetter> KCreate: Here's the struct in question:
<FromGitter> <domgetter> and here is a function which returns a pointer to it:
<FromGitter> <domgetter> asterite: that seems to have worked, thank you :)
<FromGitter> <asterite> \o/
<KCreate> Took a quick look at the library you showed, also couldn't find the struct definition
<KCreate> Maybe it's some kind of super class for all different window type you are supposed to cast?
<FromGitter> <domgetter> The library is cross-platform, so I presume the implementation is set when it compiles. You're just supposed to pass the pointer to the utility functions
<crystal-gh> [crystal] asterite pushed 1 new commit to master:
<crystal-gh> crystal/master ab4bed3 Ary Borenszweig: Removed extra `clone` from `NamedTuple#to_h`. Fixes #4203...
mark_66 has quit [Remote host closed the connection]
olek_poz has joined #crystal-lang
akwiatkowski has quit [Ping timeout: 260 seconds]
KCreate has quit [Read error: Connection reset by peer]
olek_poz has quit [Read error: Connection reset by peer]
<travis-ci> crystal-lang/crystal#ab4bed3 (master - Removed extra `clone` from `NamedTuple#to_h`. Fixes #4203): The build passed.
<DeBot> (Can't use Time in NamedTuple with .to_h conversion)
onionhammer has quit [Read error: Connection reset by peer]
onionhammer has joined #crystal-lang
Raimondii has joined #crystal-lang
Raimondi has quit [Ping timeout: 268 seconds]
Raimondii is now known as Raimondi
KCreate has joined #crystal-lang
Qchmqs has quit [Ping timeout: 260 seconds]
<FromGitter> <gettalong> Hey everybody! I was lurking on IRC last June because I was trying to see how much faster Crystal was for my use case, parsing PDF. You guys and gals helped a lot but there was something off bc the performance was not that great. Turns out the simply reading the file into memory and the parsing it is *much* faster: 0.31s vs 7.29s (Ruby version 6.44s which also read the file into memory) :smile:
<BlaXpirit> ok
<KCreate> How did you parse it before without reading into memory first?
<BlaXpirit> KCreate, means reading it little by little vs all at once
<KCreate> Ah okay
<FromGitter> <gettalong> The code uses `def initialize(io : (IO::Memory | File))`, so the parsing code is the same, the data is just already in the memory
<BlaXpirit> :)
<FromGitter> <gettalong> Didn't think that would make such a difference because of buffered IO but it actually does
<FromGitter> <gettalong> But on to the question I wanted to ask: In Ruby world one uses strings with the BINARY encoding when working with binary data. What would be the correct way in Crystal? Slices of UInt8 (a.k.a Bytes), Array of UInt8, String, ...?
<KCreate> Slices of UInt8
<KCreate> You could also use IO::Memory
<FromGitter> <gettalong> Is there any performance difference between those two?
<KCreate> Slice is just a pointer with bound checking and IO::Memory is an IO layer over a slice
<KCreate> Oh and IO::Memory automatically doubles it's capacity once it's full
<FromGitter> <gettalong> @KCreate Thanks!
<FromGitter> <gettalong> So basically one would use IO::Memory if working with IO capabilities on the data is needed and Bytes otherwise
<KCreate> yea
<RX14> Bytes is pointer and a length, it describes a "window" of emmory you can access but doesn't move the memory or resize without you asking
<RX14> IO::Memory (and Array, etc) will resize so it does have to use realloc/move the memory around
<KCreate> Also IO::Memory can be used whenever an IO is expected, whereas a Slice can't
<RX14> in that sense Slice doesn't own it's memory, Array and IO::Memory do
<FromGitter> <gettalong> Thanks, that helps a lot! I'm not used to so much specialized classes as in Ruby you only have a handful of them :wink:
<RX14> yeah crystal is a bit more low level so we have some additional low-level tools
<RX14> though you don't have to worry about them if you don't want to
<FromGitter> <matrixbot> `kodo 🌍` after programming crystal it's hard to be to write ruby heh
<FromGitter> <matrixbot> `kodo 🌍` hard for me*
<FromGitter> <schoening> why? :p that should be the easiest to switch between :p I gotta be careful that I don't get sick of javascript if I type too much crystal xD
<FromGitter> <matrixbot> `kodo 🌍` because i wish i was writing crystal instead of ruby heh
<FromGitter> <schoening> haha!
<FromGitter> <schoening> Gotta say. I do like a type system. Never had that before
snsei has quit [Remote host closed the connection]
Renich has quit [Remote host closed the connection]
<BlaXpirit> oh no..
<BlaXpirit> who did this? running 2 independent bots is not sustainable
gloscombe has quit [Ping timeout: 256 seconds]
<RX14> yeah, please work together to orchestrate a 3-way bot
<RX14> it's painful
KCreate has quit [Ping timeout: 264 seconds]
<RX14> how about we all just use IRC :)
<RX14> provide a good enough anonymous access and we can replace gitter
<FromGitter> <domgetter> I vote we all use vim and carrier pigeons.
<RX14> i'm ok with the first, less on the second
<RX14> and does evil-mode count?
KCreate has joined #crystal-lang
<FromGitter> <domgetter> Only if I hear random cooing
snsei has joined #crystal-lang
<FromGitter> <fridgerator> lol
<BlaXpirit> kodo, in any case adding a bot is not your decision to make
<RX14> why not?
<BlaXpirit> well it's intrusive and people did not agree to this
<RX14> gitter and IRC are both public
<RX14> i see no problem with it
<FromGitter> <matrixbot> `kodo 🌍` it's not my bot
<FromGitter> <matrixbot> `kodo 🌍` this is the matrix bridge
<FromGitter> <matrixbot> `kodo 🌍` im not on gitter or irc
<FromGitter> <matrixbot> `kodo 🌍`
<RX14> you don't run the bridge?
<BlaXpirit> kodo, why don't you just join the crystal IRC channel from matrix -_-
<FromGitter> <matrixbot> `kodo 🌍` it's managed by the people
<RX14> ..?
<RX14> and it can join any gitter room?
<FromGitter> <matrixbot> `kodo 🌍` yeah
<RX14> thats terrible
<FromGitter> <matrixbot> `kodo 🌍` i'll just join the irc channel if people are gonna QQ
<RX14> i don't mind the bot personally to be honest
<RX14> I just mind that it's doubled up
kodo[m] has joined #crystal-lang
<kodo[m]> This better?
<RX14> yes
<kodo[m]> Still using matrix just the irc bridge instead of gitter bridge heh
<kodo[m]> figured i would use gitter bridge since that is the canonical community
<kodo[m]> but it seems people on irc are more vocal ;P
<RX14> it's hardly canonical, just more popular
<RX14> the irc was definitely first
<FromGitter> <mverzilli> at least from Gitter, it seems matrixbot's irc bridge is less noisy, so :thumbsup:
<BlaXpirit> and then you look at the home page of crystal
<RX14> the thing is that the gitter bridge has a single username and embeds the username in the message
<FromGitter> <matrixbot> `kodo 🌍` > The Gitter room is the official chat room for Crystal.
<RX14> the matrix irc bridge just joins a new client with a nick
<RX14> so it's better for all
<FromGitter> <tjgillies> I wonder why the gitter bridge for matrix doesn't create a virtual user like it does on irc
<RX14> just because gitter is official doesn't mean IRC isn't official
<FromGitter> <tjgillies> maybe it's against their TOS or something
<RX14> because gitter needs a user account
<RX14> and would probably be against ToS
<FromGitter> <tjgillies> ah right, irc is more lenient for users
<RX14> yes because you need no account
RX14 is now known as RX14-foo
<RX14-foo> I can change my name at any time
RX14-foo is now known as RX14
<RX14> the only account I have is a nickserv one, which is optional
<Papierkorb> To be honest, if Crystal was only on gitter and not IRC, I wouldn't participate.
<BlaXpirit> tjgillies, please do not compare to matrix, because using matrix-irc bridge is one user's initiative while making a bridge for everyone means you have a pool of people using the same channel and blah. though matrix people still run into the same problem in the long run but hey, they're big
<kodo[m]> matrix-irc is officially supported by
<kodo[m]> it was written by one of their core team members
<kodo[m]> and is in their official repo
<kodo[m]> so not sure what you're saying
<BlaXpirit> i am saying that you are one person who caused matrix to create a nickname on irc
<RX14> it's the same BlaXpirit, just that the bridge format is different
<BlaXpirit> if i were to make a similar thing on the gitter bot, i would be managing 100 nicknames on irc at once
<RX14> in that the bridge multiplexes 1 connection per user
<RX14> but thats what the gitter thing does BlaXpirit
<RX14> sorry
<RX14> matrix
<BlaXpirit> > though matrix people still run into the same problem in the long run but hey, they're big
<kodo[m]> what problem?
<BlaXpirit> managing hundreds of IRC nicknames and connections in a centralized manner
<kodo[m]> ah
<RX14> but I still don't get the "please do not compare to matrix" comment
<RX14> compare what?
<BlaXpirit> gitter-irc bot
<kodo[m]> gitter-irc?
<BlaXpirit> sorry, i wasnt clear
<kodo[m]> there is a gitter-matrix bot that is also supported by
<BlaXpirit> we noticed
<RX14> kodo[m], BlaXpirit runs the gitter bridge
<RX14> which bridges IRC and gitter
<kodo[m]> oooh
<kodo[m]> I get it now
<RX14> the matric-irc bridge plays much better with that bridge than the matrix-gitter one
<kodo[m]> you're the bot maintainer heh no wonder you have an opinion :P
<RX14> well i'm an IRC op so i get an opinion too
<BlaXpirit> i hate my own bot, that was a pandora's box that shouldn't have been opened
<FromGitter> <domgetter> Can I have an opinion too?
<RX14> well it's useful
<kodo[m]> RX14: This is why we need matrix. you and your police state :P
<BlaXpirit> it was useful in making gitter the primary channel
<kodo[m]> heh so it backfired is what you're saying?
<RX14> sure, it made gitter more popular than IRC
<RX14> but thats because gitter is more user-friendly
<RX14> it's probably helped more beople than it hurt
<RX14> even though it's a plain in the ass
<BlaXpirit> kodo[m], not really backfired, that was just a separate effect, not entirely unexpected. it was made to connect 2 parts of the community, and so it did
<BlaXpirit> but the numbers of participants on those parts have switched
<RX14> because gitter is easier to get started with
<RX14> lets be honest
<Papierkorb> never got that argument. there've been web irc clients for ages
<FromGitter> <mverzilli> at this time it seems we're 50/50 on IRC and Gitter so it would really hurt the community to stick to just one of them. BlaXpirit your bot has been a blessing, looks like it is a bit of an inconvenience for those of you who use IRC but the benefits of having connected both tools seem to offset the annoyances
<RX14> but Papierkorb we don't run one
<RX14> or link to one
<Papierkorb> RX14: Freenode should have a public one
<BlaXpirit> it does but it's bad
<RX14> ^
<RX14> using a modern irc thingy (they exist and are really nice now) and using a hosted instance would be nice
<RX14> and then linking to that
<BlaXpirit> RX14, only owners of the IRC server can do it reasonably, we cant change that
<RX14> not really true
<RX14> increasing the IRC connections limit from 1 IP is easy
<RX14> you just ask and provide reason
<RX14> i've done it many times in espernet for my znc bouncer instance
<Papierkorb> Can confirm
<RX14> which has 20 uers
<RX14> the limit form 1 ip is 5
<kodo[m]> or just proxy your connections through an ip randomizer :P
<RX14> how do you think the matrix people did it?
<BlaXpirit> RX14, get many IPs
<RX14> i doubt that
<BlaXpirit> and ask freenode about the limit anyway
<kodo[m]> matrix people have permission from freenode
<RX14> they contact the ops in a nice way and agree to work together
<RX14> the ircops aren't going to kick your ass
<kodo[m]> matthew did a private lap dance for the ircops
<jhass> looking at kodo[m] host mask it's an agreement with freenode staff
<BlaXpirit> i'm sure they're not running it all on one IP anyway
<BlaXpirit> of course it has to be agreed
<RX14> why are you so sure it's not on one IP BlaXpirit ?
<kodo[m]> it's not on one ip address
<kodo[m]> they run a cluster
<kodo[m]> but that's a trivial point heh
<Papierkorb> Maybe it's from multiple IPs, or rather machines, but that has more to do with redundancy than with messing with Freenode
<RX14> it might not be but it probably could be with less than 60k users
<RX14> 65k limit being 16bit port number
<FromGitter> <elorest> Is there a good reason that we don't have Int128/UInt128 available like rust? My understanding is that llvm supports it just fine.
<RX14> just not been added yet
<FromGitter> <elorest> ok.
<RX14> it's on the todo list... somewhere
<Papierkorb> RX14: you could just connect to all freenode servers, giving you way more possible concurrent connections into the Freenode
<FromGitter> <elorest> Good to know.
<RX14> Papierkorb, indeed
<RX14> i was going with the smallest limit
<RX14> well the smallest limit is the ircops' limit
<RX14> but assuming thats lifted
<kodo[m]> > I tried to do the same in Crystal and it was pretty easy and worked well, I just didn't committed it or told anyone because I wanted to discuss it first
<kodo[m]> He is a true diplomat heh
<RX14> well
<RX14> he's still the bdfl
<FromGitter> <Sija> > for example I don't know if 128-bits integers are supported in all platforms (if LLVM does the transforms in all of them).
<FromGitter> <Sija> I’m pretty sure we’ll see Int128 pretty soon if some1 would assert it’ll compile for all platforms :)
<RX14> ci's coming soon...
<RX14> I've got an AWS account with proper access now, i just need some time to set it up
<RX14> which will be next weekend probably
<RX14> (busy week :/)
<kodo[m]> RX14: What are you going with?
<RX14> jenkins
<RX14> jenkins 2.0 is great
<FromGitter> <Sija> @RX14 sweet, I’m curious how them ARM builds r performing…
<kodo[m]> I think it's kinda odd we use the master/slave paradigm in the tech community
<kodo[m]> or at least odd that we call it that
<jhass> primary / secondary ;)
<Papierkorb> secondary master?
<jhass> just switch
<jhass> active / passive, master / replica(nt), ... there's easily enough alternatives if you want
<kodo[m]> i like replica
<kodo[m]> isn't that what mongo uses?
<kodo[m]> looks like replica is what's being adopted now
<Papierkorb> "diversity"
<Papierkorb> bingo
olek_poz has joined #crystal-lang
<kodo[m]> meh BigInt breaks heroku buildpack :(
sauer2 has joined #crystal-lang
snsei_ has joined #crystal-lang
<sauer2> Hi, can sometell me how to do the "union" part in tagged unions correctly in Crystal? I have a class with a constructor signature like initiate(type : NType, value : String | Nil), however, when I try to, | Nil)) I get -> can't cast Nil:Class to (String | Nil)
<sauer2> How do you do this correctly?
<RX14> Nil != nil
<RX14> Nil is the class, nil is the value
snsei has quit [Ping timeout: 256 seconds]
<RX14> nil should workj without the .as()
<sauer2> @RX14 Dayum, thank you.
KCreate has quit [Ping timeout: 240 seconds]
<RX14> the compiler's telling you that if you read closely
<RX14> but it is a bit confusing for newcomers
<RX14> the types of classes have :Class on the end
<RX14> it's something to watch out for
<FromGitter> <crisward> also string nil types can be written as `String?`
<sauer2> thanks. I thought that was some general internal stuff.
<sauer2> Does that get confused often? In which case: Should I file a request ticket so the compiler says Nil (a class) instead?
KCreate has joined #crystal-lang
<kodo[m]> wonder if we had NilClass and made Nil an alias to NilClass
snsei_ has quit [Remote host closed the connection]
<kodo[m]> or just made any instance of nil throw an exception and not use nil :P
<kodo[m]> >I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because
<kodo[m]> it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
inancgumus has joined #crystal-lang
<jhass> nil != null
<KCreate> Who's that quote from?
<kodo[m]> Tony Hoare
<jhass> a null reference is the absence of value, nil is a replacement value
<kodo[m]> also the guy behind crystal's concurrency paradigm
<RX14> the thing is that crystal doesn't have null by default in types
<RX14> thats what the quote is talking about I'm pretty sure
<jhass> null has no type while nil has a type ;)
<jhass> crystal has no null
inancgumus has quit [Client Quit]
<RX14> well whatever you call it, the difference is whether it's there implicitly or explicitly
<RX14> and in whether the compiler forces you to handle it or not
<sauer2> How comes nil has a type that is different from its literal? Does that make parsing easier?
<jhass> it doesn't?
<Papierkorb> sauer2: It improves semantics of the language
<RX14> typeof(nil) => Nil
<RX14> typeof(Nil) => Class
<jhass> ah now I get what you mean. Every value is an object, every object has a type
<RX14> everything has a "meta type"
<RX14> even Class
<RX14> nil is no exception
<sauer2> ah, ok, so I take it nil for both would have been too many special cases
<KCreate> Int32.class.class.class and so on...
<kodo[m]> Class is a Class man
<Papierkorb> sauer2: say `nil` was both a value and a type. then you'd do `def foo(bar : String | nil)` which is weird, as now you're saying "I want a string, or the value nil", complicating language rules: A user could now assume, that you could put arbitrary values there, allowing `def foo(bar: "foo" | "bar")`, but that's exactly not what Crystal allows to do
<kodo[m]> it's classes all the way down
<RX14> yes, and that types start witha capital in crystal
<RX14> that's just the convention
<kodo[m]> I name my constants with singal capital too because I'm lazy :P
<RX14> PascalCase please
<jhass> also it's a good thing that nil.class != nil
<sauer2> fair enough
<RX14> yeah
<RX14> nil is one of the few falsey values
<RX14> Nil:Class being falsey would be buggy
<sauer2> Does that mean that if() takes (Boolean | Nil) ?
<jhass> on that note I'm still not sure I like that Pointer.null is falsey
<sauer2> I mean, without the parenteses
<RX14> if() isn't a method
<RX14> it takes anything
<RX14> you can do `if var` and as long as var isn't nil or false, it'll run the clause
<Papierkorb> jhass: Pointer(T).null is indeed falsy
<RX14> oh, and Pointer.nil
<Papierkorb> sauer2: for conditions, don't think in terms of types, but truthiness and falsiness
<RX14> kodo[m], that's macro code, it's set by the compiler
<Papierkorb> kodo[m]: @type is a magic variable in macros
<RX14> it's magic and doesn't follow the rules
<RX14> you can't create or write @var or @@var in macros
<sauer2> @Papierkorb: I see, thanks. Good thing falsey values are just 3 kinds.
<RX14> it's just reused syntax
<jhass> wonder whether we should switch that to $type given it's kinda free now
<RX14> unlike JS, heh
<Papierkorb> sauer2: Yes. Especially if you don't come from Ruby, you could be confused at first that e.g. `if 0` is true in Crystal
<kodo[m]> where does the compiler get @type?
<jhass> it just knows it
KCreate has quit [Ping timeout: 240 seconds]
<RX14> @type is the type of the class the macro is in
<jhass> it's the current type's AST node
<RX14> if thats what you're asking
<kodo[m]> How does it create a new class? I don't see an initialize method
<kodo[m]> I love languages that are written in themselves
<RX14> Class instances are created by the compiler
<RX14> they're singletons I think
<jhass> not sure they're even really there in codegen
<jhass> or if all methods on them aren't just expanded to literals
<RX14> just writes the binary representation to ELF I think
<RX14> and then provides the pointer where required
Renich has joined #crystal-lang
<FromGitter> <Sija> iirc that’s the place where defining initializers happen
<Renich> guys, I want a method to take a named tuple in. So: `def createOrder( order: { id : UInt32, amount : Int32 } }
<Renich> how do I do that?
<RX14> `def createOrder(order : {UInt32, Int32})`
<Renich> OH!
<RX14> on
<Papierkorb> `def create_order(order: NamedTuple(id: UInt32, amount: Int32))`
<RX14> sorry
<RX14> namedtuple
<RX14> i'm wrong
<RX14> `def createOrder(order : {id: UInt32, amount: Int32})`
<RX14> that works
<Renich> RX14: OK
<RX14> or use Papierkorb's syntax
<Renich> Thanks
<RX14> it's a tad longer but more universal
<RX14> the "short" syntax simply expands to the long one
<Renich> RX14: which is more crystalized ;)
<Renich> ?
<RX14> asterite wouldn't have added the short syntax if he didn't want you to use it
<Renich> RX14: right
<Papierkorb> Renich: my_naming but RX14's argument type
<Renich> Papierkorb, RX14: thanks guys
<FromGitter> <Sija> long: `NamedTuple(key: ValueType)` vs short: `{key: ValueType}`
<RX14> Renich, crystal is pre-1.0, we can simply remove any syntax we don't want you to use
<Renich> RX14: LOL. OK.
<Papierkorb> Renich: Also, consider using e.g. a struct instead of a plain named tuple. if you don't want to write that struct by hand, use the `record` macro
<RX14> we've removed a huge lot of ruby thats for sure
<Papierkorb> Renich: `record OrderInfo, id: UInt32, amount: Int32 \ create_order, 456)`
<Papierkorb> Renich: saves you headaches later on
<RX14> oh and yeah, please use this_style for method names
<Renich> Papierkorb: I thought about it but am not that versed with those. It will be on the improvement list for now since I am in a hurry.
<Renich> Papierkorb: but I appreciate the comment. I wanna become proficient and learn the idiom
<Renich> the awesome thing is that crystal is writen in crystal, so I can learn a ton from it. For example, learned about the getter macro by reading the code
<Yxhuvud> papierkorb: wrong syntax. it is id : UInt32, amount : Int32 etc. Not having the space there gives you funny errors.
<Renich> RX14: will
<Yxhuvud> unless record have changed it's implementation
<Papierkorb> Yxhuvud: ah dang, if I'd typed that in the editor it'd have told me
<RX14> it's one for JSON.mapping and the other for record
<Yxhuvud> but it is valid syntax, it just gives you funny compilation errors.
<RX14> I get why but I think this: Format should work for record
<kodo[m]> what do people think about records supporting named vars like ` "bar")` ?
<Yxhuvud> record is just a macro after all.
<RX14> kodo[m], they do
<Papierkorb> kodo[m]: they do
<RX14> every method supports named args
<RX14> by default
<Papierkorb> thank god they do
<RX14> thats's just how crystal works
<kodo[m]> oh derp
<kodo[m]> I have a typo
<kodo[m]> nevermind
<Papierkorb> a really good improvement over ruby
<RX14> indeed
<RX14> any method with more than 1 argument should be named in my opinion
<RX14> but I never stick to that
<RX14> so yeah
<RX14> ignore me
<kodo[m]> lol
<kodo[m]> do as I say. not as I do
<Papierkorb> I use named if it's either not obvious what they're for, or for builder-esque methods
<Papierkorb> no one needs stuff like `build_vm(name: name)`
<RX14> ANY boolean argument should be named honestly
<RX14> otherwise it just gets messy
<RX14> ok, almost any
<Renich> I like the Struct idea. I just need to understand it first
<RX14> foo(true, false) what does it mean?
* Renich also needs to read the coding style chapter
<kodo[m]> What about this?
<kodo[m]> Any way to not has to pass x?
<kodo[m]> have to*
<RX14> it doesn't add a default for you
<kodo[m]> i tried to add a default but it complained
<Renich> Papierkorb: I just saw your struct recommendation. Thanks! The example really helps.
<Papierkorb> cheers
<RX14> you need to reorder the args so that defaut ones come after non-defaults
<RX14> otherwise calling the method wouldn't work
<RX14> well, not really
<Renich> RX14: thanks
<kodo[m]> wat?
<Renich> I need to do some mapping as well.
<Renich> Will get into that later
<kodo[m]> why does order matter? I thought that was the whole point of naming them
KCreate has joined #crystal-lang
<RX14> kodo[m], because you can call it without names too
<kodo[m]> ah
<RX14> in that case, it doesn't make sense to have names with defaults after args without defaults
<kodo[m]> we should force people to call by name :P
<sauer2> BTW: Why is it that in many modern languages there are two kinds of Types for stack and heap based values instead of declaration keywords?
<RX14> you can if you add "*" as a argument
<RX14> you can force the args that exist afterwards to be used named
<RX14> then that warning wouldn't happen
<RX14> but the record macro doesn't do that
<RX14> sauer2, because stack/heap changes the semantics
<RX14> to be pass-by-value or pass-by-reference
<RX14> so you need to be aware of which when writing the class
<kodo[m]> someone was talking about that the other day in order to get tighter GC constraints
<sauer2> @RX14 wouldn't the compiler catch that?
<RX14> no, neither are an error
<RX14> it's just a choice
<RX14> we have some structs, some classes and thats why we let people choose
<sauer2> @RX14 no, I mean, instead of having class and struct, why can't that be decided by the user of the type by typing something like
<sauer2> heap a = 2
<RX14> because as I said, it changes the implementation of the class
<RX14> all structs in crystal's stdlib are immutable
<sauer2> Well, it would technically be two incompatible types...
KCreate has quit [Ping timeout: 268 seconds]
<RX14> but if you as a user "decided" to allocate use pass-by-value semantics on a String, it just wouldn't work
<RX14> it'd break horribly and behave weirdly
<sauer2> because those are immutable?
<RX14> string isn't internally immutable
<RX14> it has a lazilly-calculated size
<Renich> I need some help to use HTTP::Params.from_hash()
<RX14> it's the fact that String isn't immutable which would break it
<sauer2> so they are dynamic arrays and making them stack-based would copy the whole array..
<jhass> I think there's an easier argument: think about anything that manages resources, like a connection pool. You wouldn't want that state to get out of sync as you pass it around
<sauer2> internally
<RX14> sauer2, string's a terrible example
KCreate has joined #crystal-lang
<RX14> because it's not obvious what the problem would be
<RX14> (they'd perform way worse)
<RX14> but any mutable class would break
<sauer2> and C++ gets away with it, because std::string is a wrapper anyway?
<jhass> the other angle is: when do you really need it, what kind of types are equally useful in both scenarios?
<RX14> i don't know about C++ sauer2
<RX14> so I can't really say
<sauer2> fair enough
<RX14> eventually the compiler will be able to perform escape analysis and allocate classes on the stack, but it'll still pass by reference
<jhass> iirc the little C++ I did you quickly end up always using one or the other exclusively depending on the type for most stuff, because it breaks otherwise
<RX14> just perform that optimization in the background
<RX14> and ensure there's no dangling pointers
<sauer2> seems about right. Guess I'm biased, because whenever I think about it I remember that D has that separation as well and it also tries to have C++ ABI compability and that will be a pain point.
<sauer2> Or that C# has structs and it seems they don't ever get used.
<jhass> not sure we ever should aim for C++ ABI compatibility tbh
<sauer2> you are right, it sounds like a real pain, because there isn't one single C++ ABI as far as I understood
<jhass> I think it's absolutely fair if you default to classes and then optimize bottlenecks as you discover them, one of those optimizations being turning a class into a struct
<jhass> as long as the stdlib gets it right you already gain 90% there's to gain
<RX14> plus the escape anlysis optimization will be great when it happens
<jhass> because that's usually the kind of objects that have a high churn
<sauer2> @jhass, so basically, I just need to remember this when implementing stuff like tokens or particle effect
<jhass> yeah
<jhass> or rediscover then really
<RX14> the thing is that structs have to be immutable, classes don't
<kodo[m]> I usually use structs for data structures and classes for behaviours
<RX14> thats the way to go
<Renich> I am passing the order():to_h to it
<Renich> errr... order().to_h
<Renich> sorry
<jhass> >> {foo: "bar"}.to_h
<DeBot> jhass: # => {:foo => "bar"} -
<RX14> wow that works
<jhass> so that doesn't work, sorry
<sauer2> @RX14 how good is escape analysis in reality? Is it what I'd call a 100% technique or is it usually less effective than expected, like say computed gotos?
<sauer2> *computed gotos in interpreter loops
<RX14> i think it'll win us quite a bit
<jhass> we probably should make HTTP::Params.from_map and let it accept NamedTuple directly
<RX14> because the amount of classes that don't ever escape is quite high
<RX14> so we've got a lot to gain from reducing GC pressue
<sauer2> that sounds neat
<RX14> Renich, what are you trying to do, in a more general sense
<Renich> RX14: I am trying to pass a namedTuple to create_orders() and have the namedTuple be transformed into the parameters so it genearates a proper request
<Renich> something.tld/api?method=PARAMS
<RX14> you want to use HTTP::Params to generate URL params
<RX14> not URI.escape
<Renich> or, rather, something.tld/api?method=create.order?PARAMS
<Renich> let me post the code for you
<RX14> do you want to use that for a HTTP request right away or generate that to a string?
<RX14> because the former is a lot easier
<Renich> I don't ming generating a string
<RX14> >> require "http"; uri =; = "something.tld"; uri.path = "/api"; uri.params = HTTP::Params.from_hash({"method" => "create.order"}).to_s; uri.to_s)
<DeBot> RX14: Syntax error in eval:17: unexpected token: ) -
<RX14> >> require "http"; uri =; = "something.tld"; uri.path = "/api"; uri.params = HTTP::Params.from_hash({"method" => "create.order"}).to_s; uri.to_s
<RX14> damn
<RX14> >> require "http"; uri =; = "something.tld"; uri.path = "/api"; uri.params = HTTP::Params.from_hash({"method" => "create.order"}).to_s; p uri.to_s
<RX14> >> require "http"; uri =; = "something.tld"; uri.path = "/api"; uri.query = HTTP::Params.from_hash({"method" => "create.order"}).to_s; p uri.to_s
<DeBot> RX14: "something.tld/api?method=create.order" - more at
<RX14> there
<RX14> you need a scheme = "https" in there too
<RX14> well, probably you want that
<sauer2> Wikipedia says about escape analysis -> In traditional static compilation, method overriding can make escape analysis impossible, as any called method might be overridden by a version that allows a pointer to escape.
<RX14> but if you only want to do a HTTP request thats a lot easier
<sauer2> That is outdated, right?
<RX14> sauer2, doesn't apply to crystal as all method overrides are known to the compiler
<Renich> RX14: well, I don't quite understand it. Let me read if for a bit.
<RX14> for C++ that's not the case i guess?
<Renich> This is odd:
<RX14> Renich, if you just want to DO a http request it's a lot easier
<Renich> RX14: ok. Thanks for the example, man. I appreciate it
<kodo[m]> what is difference between carc and crystal playground?
<RX14> kodo[m], crystal playground is local and has more features
<RX14> works globally
<Renich> RX14: ah! much better!
<RX14> or do you mean
snsei has joined #crystal-lang
<RX14> because that's the same thing
<sauer2> @RX14 no idea, but it could be. At least, C++ has method pointers, whatever they are good for.
<kodo[m]> RX14: why 2 domains I mean?
<kodo[m]> just cause?
<RX14> kodo[m], essentially
<RX14> jhass probably can tell the background on that
<RX14> he wrote it
<jhass> is a general service, filters the available languages down to crystal
<jhass> also the former ran for two or three months before the latter domain was setup
<RX14> is it the same instance/vm jhass?
<jhass> yes
<RX14> why remove the C and gcc options...
<RX14> it seems kinda pointless lol
<jhass> dunno, ary or so wanted it back then ;)
<RX14> i guess
<RX14> heh
<RX14> Renich, this is what you want for just making the request right away:
<Renich> RX14: thanks a lot
<kodo[m]> Oh! I didn't noticie used other languages than crystal
<kodo[m]> makes sense now
<Renich> I am adding the key, the secret and some other stuff
<jhass> tbh I'm not maintaining the other languages too well
<RX14> show me the final code and i'll have a look at it Renich
<jhass> partly because I need a way bigger VM for it finally
<Renich> RX14: thanks, man
<RX14> jhass, get manas to host it lol
bjz has joined #crystal-lang
sauer2 has quit [Quit: Page closed]
<crystal-gh> [crystal] jhass opened pull request #4205: Rename HTTP::Params.from_hash to HTTP::Params.from and add an overload for NamedTuple (master...feature/http_params_from)
<crystal-gh> [crystal] jhass opened pull request #4206: Use well known non-existent name for socket specs (master...feature/socket_spec_hostnames)
<crystal-gh> [crystal] rjkaes opened pull request #4207: Fix Spelling Mistake in Compiler Documentation (master...spelling/crystal-compiler)
<crystal-gh> [crystal] jhass pushed 2 new commits to master:
<crystal-gh> crystal/master 1097270 Jonne Haß: Merge pull request #4207 from rjkaes/spelling/crystal-compiler...
<crystal-gh> crystal/master 57ab1cf Robert James Kaes: Fix Spelling Mistake in Compiler Documentation...
bjz has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
<jhass> protip: a gist can have more than one file ;)
<Renich> I think my problem is that the named tupple is using Symbol as keys. :S
<Renich> jhass: oh... OK... sorry, hehe
* Renich doesn't use gist much
<RX14> Renich, yeah thats the problem
<RX14> you need to use strings as keys
<Renich> Ahhh... too bad
<Renich> I liked the symbols
<RX14> so you need to use hash syntax
<Renich> oh well
<Renich> will do that
<kodo[m]> do people say /tupl/ or /tʌpl/ ?
<Renich> I live in México so I say "toopleh"
<RX14> i wish I knew IPA
<RX14> I say tupl I think
<kodo[m]> Renich: so /tuple/ ?
<Renich> ... I dunno :D
<kodo[m]> that page has an audio file for /e/
<Renich> kodo[m]: to me, "e" sounds like "i"; in Spanish
<Renich> kodo[m]: "e", in spanish, sounds like everything before "x" in exoplanet
<Renich> elephant as well
<Renich> How do I tell a class to accept a Hash?
<kodo[m]> Renich: That sounds like /ɛ/
<Renich> ok
<Renich> yep, it does
<RX14> "tyoo-pl" is how I pronounce it
<RX14> /tjʊpl/ according to my resident IPA expert
<kodo[m]> RX14: Are you in the UK?
<RX14> yes
<RX14> i speak the queen's english
<RX14> :P
<Renich> those are always well received
KCreate has quit [Quit: leaving]
<RX14> values need to be strings too
<RX14> invote to_s on your values
<RX14> invoke*
<Renich> RX14: yeah, will
<RX14> kodo[m], [tju:pl] aparrently is how I say it
sz0 has joined #crystal-lang
<travis-ci> crystal-lang/crystal#1097270 (master - Merge pull request #4207 from rjkaes/spelling/crystal-compiler): The build passed.
<DeBot> (Fix Spelling Mistake in Compiler Documentation)
<Renich> OK. I have create_order( order : Hash ). The order gets created. I want to add id that the API returns to order. How can I do this?
<jhass> order["id"] = id ?
<jhass> might be worth to return a modified copy though
<Renich> jhass: yes, but order lives outside the function. I want to add to that.
<Renich> jhass: ok, I get your idea
<jhass> hash is pass by reference
<jhass> the latter suggestion is just for sanity
<jhass> since modifying the argument is usually unexpected by the caller
<Renich> jhass: you're right. Thanks.
sz0 has quit [Quit: Connection closed for inactivity]
<kodo[m]> Is there anything in crystal like in clojure where I can assign a property to something and then update it later like a ref?
snsei has quit [Remote host closed the connection]
olek_poz has quit [Ping timeout: 260 seconds]
<kodo[m]> I want the performance and immutabilty of a struct but I want to be able to change it. IIRC clojure has datastructures that are immutable but can be updated later using some fancy mechanism
<FromGitter> <fridgerator> before I do this, do any options exist for calling ruby from crystal other than `\`ruby somefile.rb\``
<FromGitter> <fridgerator> I need to use the aws api / sdk (for which there is already a ruby gem). Up until now I've been manually building requests with the help of one of the crystal aws signer libraries, but I'm going to have to make a decision to either switch and write in ruby or some hack to call ruby from crystal with the above approach
<kodo[m]> you could use sinatra and listen to requests in the ruby app
<kodo[m]> or use some sort of rpc language
<kodo[m]> like msgpack
<FromGitter> <fridgerator> hrmm
<kodo[m]> depends on how frequently you're making calls
<FromGitter> <fridgerator> well it would work for sending emails through SES for sure, but in one instance I'm trying to get a pre-signed expring url from an S3 object
<FromGitter> <fridgerator> there will be other use cases also
<FromGitter> <fridgerator> the AWS sdk is huuuuge, a crystal version would be nice, but thats a really time consuming project
<FromGitter> <fridgerator> should be standard library imo
<FromGitter> <fridgerator> lol just joking
<kodo[m]> I was asking because if you're sending something out every second or something, spinning up a new ruby instance doesn't seem performant
<kodo[m]> but if you're just sending something out every once in a while it probably doesn't matter
<FromGitter> <fridgerator> yeah