<asterite>
It’s mostly used in low-level code to define a static array without initializing it (for performance reasons): buffer :: UInt32[1024]
<zamith>
I interested in particular in this line from the getter macro: {% name = name.var if name.is_a?(DeclareVar) %}
<asterite>
But in a class or struct you can use it to force an instance variable to be of that type
<asterite>
Oh, you can do: getter foo :: Int32
<zamith>
oh ok
<zamith>
got it
<zamith>
thanks
<zamith>
about what I've asked earlier, care to explain how the IO object works?
<zamith>
is it like a buffer, that gets flushed on print, for instance
<zamith>
?
<asterite>
Oh, I didn’t see it earlier, sorry
<asterite>
In Crystal IO is a module that just provides convenience methods for reading and writing somewhere
<zamith>
In particular, why does the to_s method have to receive an io?
<asterite>
an object include IO must implement write(slice, count) and read(slice, count)
<asterite>
We chose to do it in a different way than Ruby for efficiency
<asterite>
for example, if you do `puts [1, 2, 3]`
<asterite>
if puts just calls to_s on the argument, a String must be created from the Array
<asterite>
then that string is printed, and it’s not used anymore
<asterite>
Instead, if it’s to_s(io), the Array implementation writes “[“ to the give IO, then writes each of the values separated by a comma, then the ending “]”
<asterite>
there’s no need to create intermediary strings
<asterite>
And this is just for an Array. Imagine a big object containing other sub-objects, lots of strings would have to be created
<zamith>
I understand
<asterite>
We also use this in json generation, it’s to_json(io)
<asterite>
In Ruby/Rails it’s worse because you first create a big hash/array and then convert that to a String, and then send it to the browser
<asterite>
It’s very, very slow
<zamith>
actually, I got into a funny behavior when I was implementing the inspect method for some objects which were in an array, and then leveraging the fact that the p method calls inspect, and in ruby it just printed what I've defined
<zamith>
in crystal it added the [ and ], and the commas in between
<zamith>
I found it was because of how to_s (which then inspect calls) is implemented in Array
<asterite>
Oh, I think that’s because `puts array` in Ruby prints the element one by one separated by a newline, but I’m not sure I like that
<zamith>
yeah
<zamith>
I just wasn't expecting it
<asterite>
For me it’s unexpected too :)
<zamith>
thanks so much for the feedback
<asterite>
:)
<zamith>
asterite: How does lib find which C library we want to bind to?
<zamith>
asterite: still regarding the IO object, when you say that it writes each of the values, you mean it writes them to bytes directly, without creating a string?
<asterite>
Well, it writes the bytes to an intermediary buffer (allocated on the stack) and then writes that buffer to the given IO
<zamith>
sure
<asterite>
(because if you write it directly you will get the number reversed)
<zamith>
but that's the optimization you were talking about, right?
<zamith>
or are there more benefits than those?
<asterite>
No, it’s just that it’s more efficient
<asterite>
I mean, the optimization is in every to_s(io) implementation, which doesn’t need to create an intermediary string
<zamith>
asterite: Why do you use a Generic to implement expectation, such as class EqualExpectation(T)?
<zamith>
also, sorry for being so annoying :p
<asterite>
You are not annoying :)
<asterite>
We use a generic because otherwise EqualException’s @value’s type would be a huge union of all the possible types you instantiate it with, and that would cause a huge dispatch to be made on every “==“ call
<asterite>
but if it’s generic then @value’s type would be T (but there would be many EqualExceptation(T) types, but that doesn’t affect performance)
<asterite>
But mostly, in the early days that didn’t compile, it crashed the compiler due to some bugs. Maybe now it works if it’s not generic and maybe it’s still efficient, but I don’t know
<zamith>
ok, but the only instantiation of it I see is Spec::EqualExpectation.new value
<zamith>
does it figure out T from value?
<asterite>
Yes
<zamith>
oh, cool
<asterite>
In that same way you can do: Array.new(4, false)
<zamith>
Array is a generic
<asterite>
and that will create an Array(Bool) of length 4 because it figures it out from “false"
<zamith>
?
<asterite>
Yes
<zamith>
got it
<zamith>
nice
<zamith>
so, the main (only?) goal of generics is to get a type when they are instantiated, for performance (safety?) reasons?
<asterite>
Oh, it’s not documented :(
<asterite>
It’s because a class’s instance variable accumulates all the types you assign to it
<asterite>
so if array weren’t generic, if you do this: `[1]; [“hello”][0] #=> Int32 | String`
<asterite>
all arrays would have their types mixed
<asterite>
I’m sure I wrote something about this somewhere, but I can’t find it