<FromGitter>
<jonnypetraglia> Hey, I'm getting an error: "instance variable @muh_var of MuhClass must be `Array(...)+`, not `Array(...)". Can someone point me to the docs or "+"? It's kind of difficult to search for...
<FromGitter>
<watzon> Tourmaline has a new logo and header :)
<FromGitter>
<digitalextremist> Hello all... Getting an unexpected behavior. Anyone have an idea on how to work around these behaviors? ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ That will fail with `no overload matches 'Array(Generic)#<<' with type Specific1.class` ... [https://gitter.im/crystal-lang/crystal?at=5cd513e75a887e1cd9c13118]
<FromGitter>
<digitalextremist> Edit: And if that didn't fail, the `add self` line would fail with `no overload` for the add class method, expecting it to be `Specific2.class`
<FromGitter>
<watzon> As far as I know you can't do that
<FromGitter>
<digitalextremist> Ah, I worried that might be so. Hmmm. Thank you @watzon
<FromGitter>
<watzon> The `add self` has to be in the initialize method, otherwise `self` is of type `Specific2.class` instead of `Specific2`
<FromGitter>
<digitalextremist> So it's only going to treat instances as part of `Generic` and not the classes themselves
<FromGitter>
<digitalextremist> Ah, I see.
<FromGitter>
<watzon> What are you trying to accomplish?
<FromGitter>
<watzon> You just want to keep track of all instances of the subclasses inside of the parent class?
<FromGitter>
<digitalextremist> Rather than store blocks, in a `Kemal` type way ( copying `Sinatra` ) ... I want to save a reference to an individual class, expecting to instantiate a new class of that type at the point of a request
<FromGitter>
<digitalextremist> So I am probably going to just save `"#{self}"` and weep
<FromGitter>
<watzon> Hmm interesting
<FromGitter>
<digitalextremist> Yeah that stringifying approach seems to work, unhappily
<FromGitter>
<watzon> What does your code look like now?
<FromGitter>
<digitalextremist> Yeah this is a good workaround
<FromGitter>
<digitalextremist> Thanks again @vladfaust
<FromGitter>
<vladfaust> @watzon the biggest macro knowledge boost I got was from implementing an ORM. This is when I learned the "always have plan B with Crystal" rule 😈
<FromGitter>
<vladfaust> I mean, internals knowledge is born in battles
<FromGitter>
<digitalextremist> Agreed. New to `Crystal` myself, only a month or two in, so this is the kind of thing that'll really build intimate knowledge
<FromGitter>
<watzon> Haha macros can definitely be pretty handy. As much as it pains me to say so though, I prefer Nim's macro system. It gives you so much control 😈
<FromGitter>
<watzon> I can't remember, Crystal doesn't have a `class << self` parallel right?
<FromGitter>
<digitalextremist> Nope
<FromGitter>
<watzon> I didn't think so
<FromGitter>
<digitalextremist> They all have to be `def self.`
<FromGitter>
<watzon> Yeah. Oh well haha.
<FromGitter>
<vladfaust> Anything in Crystal may be changed, even macros. If you, @watzon, work hard on formalizing an issue and building proposal... This may lead to macros improvements
<FromGitter>
<watzon> I remember bringing up the issue, but I think some of the core devs didn't like the idea of making macros that powerful
<FromGitter>
<watzon> Maybe I'll look into putting together an RFC
<FromGitter>
<vladfaust> It would be good to have a point of view from less experienced (say, regular) macro user
<FromGitter>
<watzon> Haha, that's me!
<FromGitter>
<vladfaust> Johannes and Kevin (and maybe me) are working on https://github.com/shardbox, you can help us building a nice shards catalog service
<FromGitter>
<vladfaust> For example. @watzon, you could build a telegram bot which would send a daily/weekly digest of new shard additions
<FromGitter>
<vladfaust> I'd definitely use it
<FromGitter>
<watzon> That is a brilliant idea
<FromGitter>
<watzon> I would definitely do it
<FromGitter>
<vladfaust> I'd also put it into our chat of 200 people so it puts the digest publicly and we all can see the ecosystem progress and discuss it
<FromGitter>
<watzon> I also just started a new (very ambitious) project which would probably help a lot
<FromGitter>
<vladfaust> It could be a channel, also, though (still needs to be controlled by a bot). Find what's best
<FromGitter>
<digitalextremist> eeek. There's no `.send` equivalent, to send a method name as a `Symbol` and have that invoked on an instance?
<FromGitter>
<vladfaust> Regarding to GitHub API wrapping... I'm currently working on a weekend project which uses GitHub and Stripe APIs extensively. And I found it more comfortable to implement those API clients per se, i.e. serializing only those fields which I need for an application. Thus said, wrapping the whole third-party API is non-rewarding, requires maintainability and lots of initial work to cover all methods/objects
<FromGitter>
<vladfaust> I'm thinking of some kind of skeleton API wrapper where you add methods and objects you need for your application by yourself, but the core functionality (client, auth) is implemented
<FromGitter>
<watzon> Probably true, but I'm bored lol
<FromGitter>
<watzon> I've got a "github stars high" from my Cadmium project and now I need another very star-able project
<FromGitter>
<vladfaust> @digitalextremist Crystal has to know the exact method to call, in compilation. You could achieve the same functionality with macros
<FromGitter>
<vladfaust> @watzon think of that ⏎ ⏎ > I'm thinking of some kind of skeleton API wrapper where you add methods and objects you need for your application by yourself, but the core functionality (client, auth) is implemented ⏎ ⏎ Some kind of common APIs framework applicable to many REST APIs [https://gitter.im/crystal-lang/crystal?at=5cd521725d48a24fd0a1aafc]
<FromGitter>
<watzon> As is typically the case. If it's not against the tenants of the language you can probably macro it
<FromGitter>
<watzon> I'll definitely think on that @vladfaust
<FromGitter>
<watzon> It would be nice
<FromGitter>
<vladfaust> > Some kind of common APIs framework applicable to many REST APIs ⏎ ⏎ Chris mentioned that we need such a tool, BTW
<FromGitter>
<watzon> Ahh I didn't know that RX was a Chris lol
<FromGitter>
<watzon> I am too
<FromGitter>
<vladfaust> So many Chrises in our world. I always remember that Lonely Island oscars song
<FromGitter>
<watzon> Haha I've never heard that
<FromGitter>
<watzon> But now I need to look it up
<FromGitter>
<vladfaust> More context, please. What you want and what is `Test`
<FromGitter>
<watzon> Test is a module. I just want to create an array of arrays, each of which has a key (string) and value (class variable with the same name as the key)
<FromGitter>
<watzon> Basically like Ruby's `instance_variable_get`
<FromGitter>
<vladfaust> Why would you think `.keys` would work?
<FromGitter>
<j8r> you know, you will need a case when at runtime
<FromGitter>
<vladfaust> +1 fro case
<FromGitter>
<watzon> Haha I see what you did there
<FromGitter>
<digitalextremist> You're saying use `case / when / end` set, with a `when` for every case?
<FromGitter>
<j8r> yes @digitalextremist . The whens can be generated by macros
<FromGitter>
<vladfaust> Yes, and those `when`s could be generated in macros
<FromGitter>
<vladfaust> Damn
<FromGitter>
<j8r> at the same time @vladfaust 😆
<FromGitter>
<digitalextremist> Wow. This became semi-rocket science
<FromGitter>
<vladfaust> It looks complicated now, but it's pretty transparent really
<FromGitter>
<digitalextremist> But I guess I am on the right track because I did that for the other *case* where this failed, since I thought that was more predictable... but this does need to be dynamic now
<FromGitter>
<digitalextremist> Is there an example somewhere of creating dynamic `case` statements in macros?
<FromGitter>
<vladfaust> @j8r I understand you. Got no luck with that AFAIK
laaron has quit [Remote host closed the connection]
<FromGitter>
<digitalextremist> ohhh woww... also figured out all this might've been unnecessary because I could have just converted `StringLiteral` into `String` -_-
laaron has joined #crystal-lang
<FromGitter>
<mwlang> Thanks @vladfaust
ua has joined #crystal-lang
<FromGitter>
<j8r> how can I use blocks with macro?
<FromGitter>
<digitalextremist> I think you want a `typeof`
devil_tux has quit [Ping timeout: 244 seconds]
<FromGitter>
<MrSorcus> @bew i mean how can i call function with `LibC::VaList`? ⏎ ⏎ ```lib Test ⏎ fun test(num, args : LibC::VaList) ⏎ end ⏎ ⏎ pp Test.test(1, ???)``` ⏎ ⏎ What should i paste instead of `???`? [https://gitter.im/crystal-lang/crystal?at=5cd55558e7f42160fa652a03]
<FromGitter>
<vladfaust> I expect the code to return two `"foo"`s. It's simplified; original regex includes named groups and kinda big
<FromGitter>
<vladfaust> Wow, TIL, @Blacksmoke16! Thank you very much!
<FromGitter>
<Blacksmoke16> np
<FromGitter>
<tenebrousedge> I wish `scan` returned `Array(String)` :/
<FromGitter>
<vladfaust> No, `MatchData` works perfectly for me, as I have named captures
<FromGitter>
<bigeasy> Is there any place where I can read about what appears to be compiler enforced tests for `nil?`.
<FromGitter>
<Blacksmoke16> hm?
<FromGitter>
<bigeasy> I'm trying to write a doubly linked list and I'm getting all kinds of compiler errors.
alexherbo2 has joined #crystal-lang
<FromGitter>
<Blacksmoke16> any examples?
<FromGitter>
<MrSorcus> What's right and why `type Callback = (UInt8*, Int32) -> Bool` or `type Callback = (UInt8*, Int32 -> Bool)`? Thanks.
<FromGitter>
<bigeasy> None yet. It's kind of a general question. I see the compiler giving off errors. They go away when I check `nil?`.
<FromGitter>
<Blacksmoke16> `Error in line 1: no overload matches 'Int32#+' with type (Int32 | Nil)` like this?
<FromGitter>
<bigeasy> Basically, if I have a member that is `@m : T?` than in each method have to `@m && @m.foo` or else I get an error that `undefined method 'foo' for Nil`.
<FromGitter>
<bigeasy> And this is expected?
<FromGitter>
<tenebrousedge> you can use `.try &.foo` depending on what you're after
<FromGitter>
<r00ster91> yes. the ? means that it can be `Nil`
<FromGitter>
<bigeasy> @tenebrousedge `.try &.foo` made things less ugly, thank you.
<FromGitter>
<r00ster91> the compiler wants you to deal with `Nil` and handle it in order to avoid bugs
<FromGitter>
<bigeasy> Is there anyway to tell the compiler to chill out a bit?
<FromGitter>
<tenebrousedge> can you post a code sample in the playground?
<FromGitter>
<r00ster91> you can use `not_nil!` but you should try to avoid that
<z64>
generally, you make the type non-nilable by providing some static guarentee it won't ever be nil; either by restructuring your types, or accessing the data with an assertion like `@m.not_nil!.foo` as mentioned
<FromGitter>
<bigeasy> A linked list is going to have `@next : Node(T)`. I've tried `next = self` to satisfy the compiler, but it says using self before initializing `@next` (I agree) and so `@next` must be `@next | Node(T)?`.
<FromGitter>
<bigeasy> Thank Mr. Robot!
<FromGitter>
<bigeasy> Thank you Mr. Robot!
<z64>
lol
<z64>
yeah `@next : Node(T)?` would be correct for a LL
<FromGitter>
<tenebrousedge> perhaps using a lazy `getter` with a block would help
<FromGitter>
<bigeasy> Oh, you're person. Not a robot. Thank you @z64.
<z64>
the lazy getter macros are good for potentially expensive computations that you want to cache. for just traversing a LL or other data structure, it's not apropriate here
<z64>
np lol
<FromGitter>
<bigeasy> I know in my bones `@next` will not be `nil`. It is a circular list and I can see with my own two eyes where I initialize the head at construction. The `nil` checks to all the pointer surgery are really ugly and would introduce bugs anyway. If `node.try &.next = @head.try &.next` would just swallow an error which is just as bad.
<z64>
yeah. then probably `@next.not_nil!` is fine here
<FromGitter>
<r00ster91> maybe add a comment explaining why you are 100% sure that @next will never be nil
<z64>
if the LL structure is composed at runtime, then yeah - you have to make an assertion so that an apropriate error would be raised on an unsound/impossible condition
<jeremycw>
How do I know which order macros will be evaluated in?
<FromGitter>
<asterite> @watzon I used to work at Manas but not anymore. From the core team, just bcardiff and waj are in Manas
<FromGitter>
<shreeve> @asterite - Have you guys joined another company or created a new one to support Crystal?
<jeremycw>
I have a top level macro that reopens some classes and adds methods to them. Another macro in a class generates code which uses those methods.
<jeremycw>
But I often get undefined method errors during compilation and have found it difficult to order the macros in such a way that the methods are added to the classes before a method is generated that invokes those methods.
<FromGitter>
<asterite> @shreeve I just moved to another company (just to try something different). I do Crystal on my free time
<FromGitter>
<asterite> (tl;dr: Checking nil on instance var doesn't restrict the type because it could be mutated in a different thread. You must first assign the instance var to a local variable first and work with that)
<FromGitter>
<r00ster91> I find it strange that you don't get paid to work full-time on Crystal
<FromGitter>
<bigeasy> @asterite I figured that one out.
<FromGitter>
<bigeasy> At this point I've created `Null(T)` which has a `next` and `next=` and use that in `initialize` then I set it with a `Node(T)` immediately after.
laaron has quit [Client Quit]
<FromGitter>
<bigeasy> The compiler is quieting down.
<FromGitter>
<bigeasy> So, `next : Node(T) | Null(T)`.
<FromGitter>
<bigeasy> All this `nil` checking might be too much for me, though.
<FromGitter>
<Blacksmoke16> have less nilable types, problem solved :p
<FromGitter>
<Blacksmoke16> or move nil handling higher up or something
laaron has joined #crystal-lang
<FromGitter>
<bigeasy> @Blacksmoke16 You're not following.
<FromGitter>
<Blacksmoke16> prob, kinda late to the convo
<FromGitter>
<Blacksmoke16> but i mean if you know things wont be nil, dont make them nilable
<FromGitter>
<bigeasy> It's in the scrollback if you're interested.
<FromGitter>
<Blacksmoke16> `@m : T?` why not just make that `@m : T`?
<FromGitter>
<Blacksmoke16> then `Node(Int32)` would not be nilable and thus avoid the nil compile errors
<FromGitter>
<bigeasy> > A linked list is going to have `@next : Node(T)`. I've tried `next = self` to satisfy the compiler, but it says using self before initializing `@next` (I agree) and so `@next` must be `@next | Node(T)?`.
<FromGitter>
<bigeasy> @z64 Defined the getter that asserts `not_nil!` and not it all looks pretty reasonable to me.
<FromGitter>
<bigeasy> Smoothing things over with an explicit accessor seems reasonable and fits with my expectations set by what little Ruby I know. Defining a `Null(T)` made the language feel broken.
<FromGitter>
<bigeasy> Indents: 2 spaces or 4?
<FromGitter>
<Blacksmoke16> 2
<FromGitter>
<bigeasy> Unrelated: Indents: 2 spaces or 4?
sz0 has quit [Quit: Connection closed for inactivity]
hightower2 has quit [Ping timeout: 245 seconds]
<FromGitter>
<wontruefree> shards has been taking a really long time to resolve the git dependencies. I have been timing cloning and I cannot figure out why it is taking so long
<FromGitter>
<wontruefree> it is taking maybe 15 minutes sometimes to resolve 7 dependencies
<FromGitter>
<Blacksmoke16> :thinking:
<FromGitter>
<watzon> Internet connection speed? And what shards are you installing?