ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.30.1 | Fund Crystal's development: http://is.gd/X7PRtI | GH: https://github.com/crystal-lang/crystal | Docs: http://crystal-lang.org/docs/ | API: http://crystal-lang.org/api/ | Gitter: https://gitter.im/crystal-lang/crystal
<hypercore> is crystal/amber/lucky efficient with hardware?
<hypercore> could i run several apps on a single vps?
<FromGitter> <watzon> It's Crystal
<FromGitter> <watzon> The answer is pretty much yes
<FromGitter> <watzon> Obviously the heavier the app the more resources it's going to use, but even with all of it's features Lucky is still tons faster than Rails
<FromGitter> <watzon> And I could potentially run multiple Rails apps on a single VPS
<FromGitter> <DanilaFe> what's the convention for re-using code between constructors of a class?
<FromGitter> <DanilaFe> defining an extra method seems hacky
<FromGitter> <watzon> @DanilaFe example?
<FromGitter> <Blacksmoke16> Another method that would call the other constructor
<FromGitter> <DanilaFe> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7d8421c82c2e0d7ed79cf5]
<hypercore> thanks
<FromGitter> <watzon> I've done it a couple times where I have a private initializer that has the common stuff, and then have multiple `.new` methods
<FromGitter> <watzon> Something like this? ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7d84c5d5c523462f83c652]
<FromGitter> <DanilaFe> ah, that will work. thanks!
<FromGitter> <watzon> `self.new` can be pretty handy
<FromGitter> <DanilaFe> how does Crystal's serializer handle Unions?
<FromGitter> <asterite> tries one by one, returns the first one that succeeds (in some order)
<FromGitter> <DanilaFe> that's strange. In that case, does Union(Child1, Child2) become Parent, where Child1 and Child2 are sublcasses of Parent?
<FromGitter> <DanilaFe> I have the following: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ I just get "just an event?" multiple times. [https://gitter.im/crystal-lang/crystal?at=5d7d8e7aa6f489644907f711]
<FromGitter> <DanilaFe> I specifically want to try one decoder, then another. Should I user JSON::Field to override this behavior?
<FromGitter> <asterite> Union(Child1, Child2) become Parent -> yes. And serialization doesn't work in that case
<FromGitter> <asterite> I mean, you can't read `Parent` from JSON or YAML
<FromGitter> <DanilaFe> so should I then just define my own converter?
<FromGitter> <asterite> I think so
<FromGitter> <DanilaFe> since I know specifically that I want to try the from_json of StateEvent,then from_json of RoomEvent
<FromGitter> <DanilaFe> alright, one more question: can I define a converter for an array, given a converter for its elements?
<FromGitter> <stronny> can you show an example of the json?
<FromGitter> <DanilaFe> that's problematic, since raw JSON is very long. I can try cook up a reduced example.
<FromGitter> <stronny> yes, the relevant part
<FromGitter> <DanilaFe> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7d91f1d5c523462f840e2b]
<FromGitter> <DanilaFe> StateEvent has both fields a and b, RoomEvent has only field a
<FromGitter> <stronny> do you control the generation code?
<FromGitter> <DanilaFe> for the JSON? no
<FromGitter> <DanilaFe> it's a response from an API
<FromGitter> <stronny> I see
<FromGitter> <stronny> maybe just declare b optional?
<FromGitter> <DanilaFe> that doesn't feel right, since I'd be duplicating fields and properties. I think I'll just write a converter for an array of events, and specify that.
<FromGitter> <stronny> sure, do what works best for you
<FromGitter> <stronny> but my first appreach would be to pull the json into simpler types, then maybe construct more complex structure
<FromGitter> <DanilaFe> PullParser doesn't keep the original JSON objects, and so I can't cast and retrieve more fields later
<FromGitter> <stronny> ```if b_present? ⏎ Type1.new @a, @b ⏎ else ⏎ Type2.new @a ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5d7d93b5d5c523462f841afd]
<FromGitter> <stronny> is what I meant
<FromGitter> <DanilaFe> this involves overriding `from_json`, no?
<FromGitter> <stronny> no
<FromGitter> <DanilaFe> then how will `b_present?` be set?
<FromGitter> <stronny> > presence: if true, a {{key}}_present? method will be generated when the key was present (even if it has a null value), false by default
<FromGitter> <DanilaFe> oh, I see
<FromGitter> <stronny> built-in JSON.mapping
<FromGitter> <DanilaFe> alright, my next question: `Type1` and `Type2` must be returned from somewhere... and this is nested in a JSON structure, so this *would* have to be in from_json?
<FromGitter> <stronny> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7d9608b84cb24c7ece6d0c]
<FromGitter> <stronny> and call it explicitely
<FromGitter> <stronny> you may also consider making RoomEvent and StateEvent independent classes not sharing a common ancestor
<FromGitter> <stronny> precisely so that Crystal will not glue them together into Parent+
<FromGitter> <stronny> if there is a common code there, you can always include a common module
<FromGitter> <DanilaFe> yeah, I considered that, too
<FromGitter> <Blacksmoke16> you could do the serialization approach i thought of
<FromGitter> <Blacksmoke16> deserialize using `JSON.parse` then from there pass that initializers that accept `JSON::Any` to new up an obj from the `JSON::Any`
<FromGitter> <Blacksmoke16> then you have access to the JSON data in order to see what keys it has
<FromGitter> <Blacksmoke16> pass that to*
<FromGitter> <DanilaFe> that's possible. I tried basically hardcoding `Union`'s behavior, to satisfactory results: ⏎ ⏎ `````` [https://gitter.im/crystal-lang/crystal?at=5d7d9a0e5d40aa0d7d3a4cd5]
<FromGitter> <Blacksmoke16> sec let me find my proof of concept
<FromGitter> <DanilaFe> I think did: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7d9a3d2e8fd94630d3e69c]
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7j9d
<FromGitter> <Blacksmoke16> thats using discriminator keys, but shows what i meant
<FromGitter> <DanilaFe> yes, I remember this
<FromGitter> <Blacksmoke16> oh right that was you :p
<FromGitter> <Blacksmoke16> this API you're working with is pretty shit tbh ha
<FromGitter> <DanilaFe> It seems, however, that this approach would be something to be implemented by a shard author (you :) ), as it appears generic enough.
<FromGitter> <Blacksmoke16> thats the plan 😉
<FromGitter> <Blacksmoke16> need to finish the serialization stuff first
<FromGitter> <DanilaFe> Oh, I'm not rushing you :) Just saying that this is why I haven't done what you have said.
<FromGitter> <Blacksmoke16> whats the api you're working with?
<FromGitter> <Blacksmoke16> something public or?
<FromGitter> <DanilaFe> matrix.org
<FromGitter> <DanilaFe> public enough since you can host your own server, but otherwise, no easy way to test
<FromGitter> <DanilaFe> I'm also spoiled. I come from using Elm and JSON decoders, and parser combinator-based decodingapproaches are very elegant
<FromGitter> <Blacksmoke16> what endpoint is it?
<FromGitter> <DanilaFe> well, I'm testing on a locally hosted server (That needs an Authorization HTTP header), so I'm not sure if it'll be useful to you
<FromGitter> <DanilaFe> the events / state are technically "private data"
<FromGitter> <DanilaFe> brb, I'm going for dinner
<FromGitter> <Blacksmoke16> ah so wouldnt be in https://matrix.org/docs/api/client-server/ ?
<FromGitter> <DanilaFe> That's the spec
<FromGitter> <DanilaFe> Now that I think about it, there was an API playground. That's probably what you found
<FromGitter> <DanilaFe> Apologies, I forgot about that
<FromGitter> <DanilaFe> /shrug I've just been reading the spec the entire time
<FromGitter> <Blacksmoke16> Yea was looking at the swagger docs
chachasmooth has quit [Ping timeout: 276 seconds]
chachasmooth has joined #crystal-lang
chemist69 has quit [Ping timeout: 245 seconds]
chemist69 has joined #crystal-lang
olbat[m] has quit [*.net *.split]
OvermindDL1 has quit [*.net *.split]
Seich has quit [*.net *.split]
Seich has joined #crystal-lang
olbat[m] has joined #crystal-lang
_whitelogger has joined #crystal-lang
<FromGitter> <DanilaFe> why is HTTP complaining here: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7dd320c82c2e0d7ed98ea2]
<FromGitter> <watzon> @DanilaFe what's the code for that call?
<FromGitter> <DanilaFe> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7dd42762bfc95112ef1b03]
<FromGitter> <DanilaFe> a similar issue occurs when I pass in a `String` to a method that takes `HTTP::BodyType`...
<FromGitter> <DanilaFe> interesting. Removing the type restriction on `body` fixes this.
<FromGitter> <watzon> I was wondering if that would be it
<FromGitter> <watzon> Is kinda weird though
<FromGitter> <DanilaFe> yeah, it's seemingly a problem of `HTTP::BodyType` vs `BodyType`
_whitelogger has joined #crystal-lang
absolutejam1 has joined #crystal-lang
DTZUZO has quit [Ping timeout: 245 seconds]
absolutejam1 has quit [Ping timeout: 276 seconds]
ht_ has joined #crystal-lang
alex``` has joined #crystal-lang
sorcus has joined #crystal-lang
devil_tux has joined #crystal-lang
alex`` has joined #crystal-lang
HumanGeek has quit [Remote host closed the connection]
HumanGeek has joined #crystal-lang
<FromGitter> <lagerfeuer> I have a question concerning Crystal's type system: I have an abstract class (like `Statement`), and a bunch of classes inheriting from it (e.g. `ReturnStatement`). I have an array, filled with different types of statements, but the array's type is `Statement`. How can I narrow down the type? I guess you call it "narrowing". ⏎ Like, I have a function `test_return_statement`, this function obviously only
<FromGitter> ... takes a `ReturnStatement` as argument, but Crystal complains that no overloads for the other types of statements are found. How can I tell the compiler to not worry about other types? A minimal example can be found here: https://play.crystal-lang.org/#/r/7kfr
<FromGitter> <stronny> But this is more of a hack than something useful imo, if you know that the first element is always C, maybe use a Tuple or a Record?
<FromGitter> <stronny> another approach is to only call a method if the type is correct like `print_C(arr[0]) if arr[0].is_a?(C)`
<FromGitter> <lagerfeuer> it's not that I always know which position is which type, it's that every type has a `handle_XXX_statement` or `test_XXX_statement` function, and I go through it in a loop and call the appropriate function. when I call `handle_return_statement` I *know* it's the correct type, but Crystal complains. so I guess the `as` hack works fine for me. unless there is something better to use.
<FromGitter> <lagerfeuer> I like the if version better, thank you :)
<FromGitter> <stronny> maybe instead of `def handle_XX_statement(s : Statement)` use `def handle_statement(s : Statement::XX)`? Overload for all children et voila
<FromGitter> <lagerfeuer> makes even more sense, and I like that even better. still exploring what Crystal can do. thank you very much :)
<FromGitter> <stronny> yes, for a language with what, 6 core devs it has surprising amount of features
alex``` has quit [Quit: The Lounge - https://thelounge.chat]
alex`` has quit [Quit: WeeChat 2.6]
alex`` has joined #crystal-lang
<Yxhuvud> lagerfeuer: if you are returning an array with positional elements of different types, then it is very likely you want to use a Tuple instead.
<Yxhuvud> Or even a specialized struct /class.
<FromGitter> <stronny> I have two related questions: ⏎ ⏎ 1) What if `"text"` string literal makes s StaticString(N)? ⏎ 2) Is it possible to find a middle ground between complete inferrance (`def a(a)`) and complete typing (`def a(a : Tuple(Int32))`)? I guess modules help here, so maybe StaticString of all sizes could include some new interface. [https://gitter.im/crystal-lang/crystal?at=5d7e251ba6f48964490be480]
<FromGitter> <lagerfeuer> @yxhuvud the thing is, I don't know which type is gonna be at which position beforehand. it's completely dynamic. To me (correct me if I'm wrong) it doesn't make much of a difference whether I use `Array(Statement)` or `Tuple(StatementA,StatementB,StatementC)`, where `StatementX` inherits from the abstract class `Statement`, but I think it's nicer to define it as `Array(Statement)`. Unless I misunderstood
<FromGitter> ... your answer.
<FromGitter> <stronny> it's just your first example with arr[0] leads to a certain direction =)
<FromGitter> <lagerfeuer> Yeah, it might have been a bad example, I just wanted to explain the issue in as little text as possible. The thing is, the array of different types might have 20 different types, that somewhere call a specfic method for the current type of `Statement`. Like I tried to explain with the `handle_XXX_statement` message. So I don't actually know which type is at `arr[0]`, it could be any subclass of `Statement`.
<FromGitter> ... I just need to tell Crystal that once I call `handle_return_statement` it can only be a `ReturnStatement` and not any other type of statement. ⏎ Think of an interpreter handling parsed statements. And the program is represented as an array of statements that get executed one by one. ⏎ Thus `handle_assign_statement`, `hand ... [https://gitter.im/crystal-lang/crystal?at=5d7e29dfd5c523462f87fb32]
<FromGitter> <lagerfeuer> I do appreciate all the answers though, guys!
<FromGitter> <lagerfeuer> Thanks for that
<FromGitter> <lagerfeuer> or maybe it's an issue with my program flow and if I fix that Crystal is smart enough to realize that there is no way this can be anything but that specific type of `Statement`
<FromGitter> <stronny> yes, it is smart enough
<FromGitter> <stronny> here, two different approaches https://play.crystal-lang.org/#/r/7kg1
return0e_ has joined #crystal-lang
return0e has quit [Ping timeout: 245 seconds]
DTZUZO has joined #crystal-lang
<FromGitter> <asterite> @DanilaFe I just sent a PR to be able to deserialize abstract base types. Might be useful for your case: https://github.com/crystal-lang/crystal/pull/8185 (though it always considers all child types, not just a subset like what you had, but I think it's still useful)
<FromGitter> <asterite> @lagerfeuer I'm pretty sure your problem can be solved by using overloads with type restrictions, like stronny showed. This is used all over the place in the compiler's source code
<FromGitter> <stronny> any thought on a StaticString?
<FromGitter> <asterite> I, didn't know that was a proposal for the language
<FromGitter> <asterite> it means we'll have StaticString(1), StaticString(2), then the union of that, then I don't know how would the type of string concatenation be computed
<FromGitter> <asterite> I don't think it's something practical
<FromGitter> <asterite> > it possible to find a middle ground between complete inferrance (def a(a)) and complete typing (def a(a : Tuple(Int32)))? . I don't quite understand the question
<FromGitter> <stronny> I mean the tuples work the same?
<FromGitter> <asterite> you mean, passing a tuple of one element?
<FromGitter> <stronny> I mean I don't restrict types to Tuples, instead I use interfaces that reflect what I do with the tuples. Probably Enumerable or Indexable and I don't even care what's the type there
<FromGitter> <stronny> In the same sense if I need a string to somehow parse it, all I care about is eg `#split` or `#each_char` or smth, I don't really care whether it lives on stack or heap
<FromGitter> <asterite> so you mean having interfaces or c++ concepts?
<FromGitter> <stronny> we already have them with modules
<FromGitter> <stronny> maybe in the future we can start using them more, like Deque(N) could become a module
<FromGitter> <stronny> and then like a RingBuffer(T, N) could include Deque(N)
<FromGitter> <stronny> and a method than needs to pop a value could accept any deque of T
<FromGitter> <stronny> even a straight array
<FromGitter> <asterite> Ah, I see. Multiple implementations of Deque(T)
<FromGitter> <asterite> Yeah... I guess I like Go's interfaces that are automatically implemented. Or even something like concepts could work. But it's really hard to fit that into a language where types in methods are optional.
<FromGitter> <stronny> I don't even mean automatic iface deduction, there is no problem to include a module explicitely
return0e_ has quit [Read error: Connection reset by peer]
<FromGitter> <stronny> and then if String becomes a module, all the StaticString(N) and the HeapString could just include it and presto
return0e has joined #crystal-lang
<FromGitter> <asterite> What's the problem with the current string?
<FromGitter> <stronny> heap allocation
<FromGitter> <stronny> ☝️ September 13, 2019 9:13 PM (https://gitter.im/crystal-lang/crystal?at=5d7bea683cc2b87edff9f809)
<FromGitter> <stronny> even if I stop caring about RSS, there are places where malloc is not a good idea, first thing that comes to mind is finalize()
<FromGitter> <stronny> yes, sometimes I can make a string in advance, but even then it feels like jumping through hoops instead of doing something useful
<FromGitter> <stronny> if we have the stack, why not use it?
Yxhuvud has quit [Read error: Connection reset by peer]
Yxhuvud has joined #crystal-lang
<FromGitter> <nsuchy> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7e623705fd3716952d9e03]
<FromGitter> <nsuchy> I'm getting the following error if the connection to proxmox fails
<FromGitter> <nsuchy> the library returns nil instead of # (key : String)
<FromGitter> <nsuchy> Reset VM works like: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7e626bd5c523462f898a9f]
<FromGitter> <nsuchy> If the connection fails, it shouldn't attempt to go further right?
<FromGitter> <nsuchy> Proxmox connect works like: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7e62a236461106bb225d8e]
<FromGitter> <stronny> what are those two? ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7e6391d5c523462f899274]
<FromGitter> <nsuchy> those are a library I wrote
<FromGitter> <nsuchy> one moment will post link
<FromGitter> <nsuchy> it's free for eeryone
<FromGitter> <nsuchy> also
<FromGitter> <nsuchy> plz don't laugh at me
<FromGitter> <nsuchy> I converted a ruby lib to crystal
<FromGitter> <stronny> hey, we are not here to judge
<FromGitter> <nsuchy> It was badly converted
<FromGitter> <nsuchy> I didn't know crystal at the time
<FromGitter> <nsuchy> so the library errors out I guess
<FromGitter> <nsuchy> but my app should just handle the exception so it doesn't matter right?
<FromGitter> <stronny> so, exception is thrown before `HTTP::Client.new`
<FromGitter> <stronny> look at the stack trace
<FromGitter> <nsuchy> okay so I can rescue the exception: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d7e64e5577fc14c7fccee46]
<FromGitter> <nsuchy> which works
<FromGitter> <stronny> `proxmox_connect` calls `CrystalProxmox.new` calls `CrystalProxmox.initialize` calls `CrystalProxmox.create_ticket` calls `CrystalProxmox.extract_ticket` which fails
<FromGitter> <nsuchy> the app still reports the VM rebooted
<FromGitter> <nsuchy> lol
<FromGitter> <nsuchy> (that's buggy logic on my part
<FromGitter> <nsuchy> I need to repair extract_Ticket
<FromGitter> <nsuchy> but then return what?
<FromGitter> <stronny> I don't understand the question. Return what you the caller expects?
<FromGitter> <nsuchy> they expect a ticket
<FromGitter> <nsuchy> if no ticket ticket exists
<FromGitter> <nsuchy> nothing else can proceed
<FromGitter> <Blacksmoke16> then throw an exception if one could not be created?
<FromGitter> <stronny> then an exception is a valid behaviour
<FromGitter> <nsuchy> yeah
<FromGitter> <stronny> just maybe not a JSON exception, but some custom NoTicketError
<FromGitter> <nsuchy> it's an unhelpful error message
<FromGitter> <nsuchy> but some special excpetion is the alternative
<FromGitter> <nsuchy> okay coolio I can handle the exception now
<FromGitter> <Blacksmoke16> after doing the post, make sure the response was successful before trying to extract the ticket
<FromGitter> <Blacksmoke16> `raise SomeEx.new "auth request failed" unless response.success?`
<FromGitter> <stronny> also instead of digging though a free-form hash you could instead create classes with JSON.mapping
<FromGitter> <nsuchy> i need to pull source to my dev machine
<FromGitter> <nsuchy> and work on it
<FromGitter> <nsuchy> with better exceptions
<FromGitter> <nsuchy> this was a buggy ruby lib
<FromGitter> <nsuchy> half finished
<FromGitter> <nsuchy> ported to crystal
<FromGitter> <nsuchy> (I didn't write the ruby lib)
<FromGitter> <nsuchy> I made a crystal lib and cookies it's logic basically
absolutejam1 has joined #crystal-lang
absolutejam1 has quit [Ping timeout: 265 seconds]
Human_G33k has joined #crystal-lang
HumanGeek has quit [Ping timeout: 268 seconds]
hightower2 has joined #crystal-lang
return0e_ has joined #crystal-lang
return0e has quit [Ping timeout: 268 seconds]
dannyAAM has quit [Quit: znc.saru.moe : ZNC 1.6.2 - http://znc.in]
dannyAAM has joined #crystal-lang
hypercore has quit [Ping timeout: 260 seconds]
hypercore has joined #crystal-lang
hypercore has quit [Ping timeout: 260 seconds]
alex`` has quit [Quit: WeeChat 2.6]
alex`` has joined #crystal-lang
_whitelogger has joined #crystal-lang
HumanGeek has joined #crystal-lang
Human_G33k has quit [Ping timeout: 240 seconds]
<FromGitter> <tenebrousedge> huh. TIL that Ruby has a (deprecated) flip-flop operator (https://blog.newrelic.com/engineering/weird-ruby-part-3-fun-flip-flop-phenom/)
hypercore has joined #crystal-lang
f1refly has joined #crystal-lang
ht_ has quit [Quit: ht_]
alex`` has quit [Quit: WeeChat 2.6]
absolutejam1 has joined #crystal-lang
alex`` has joined #crystal-lang
f1refly has quit [Quit: bye fags]
rohitpaulk has joined #crystal-lang
f1refly has joined #crystal-lang
rohitpaulk has quit [Ping timeout: 240 seconds]
gangstacat has quit [Ping timeout: 246 seconds]
gangstacat has joined #crystal-lang
alex`` has quit [Quit: WeeChat 2.6]
hypercore has quit [Ping timeout: 260 seconds]
alex`` has joined #crystal-lang
DeBot has quit [Quit: Crystal IRC]
asterite has quit [Quit: Bye]
jhass has quit [Quit: Bye]
DeBot has joined #crystal-lang
asterite has joined #crystal-lang
absolutejam1 has quit [Ping timeout: 276 seconds]
jhass has joined #crystal-lang
alex`` has quit [Quit: WeeChat 2.6]
sagax has quit [Read error: Connection reset by peer]
sagax has joined #crystal-lang
<FromGitter> <stronny> for me the hardest to wrap the head around are continuations https://max.computer/blog/delimited-continuations-in-ruby-part-1/
<FromGitter> <stronny> also refinements, oh my god