<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> 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>
<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> 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> 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> 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
<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>
<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> 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]