jhass changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Crystal 0.35.1 | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
<FromGitter> <jrei:matrix.org> @Blacksmoke16: ⏎ ⏎ ```a = 0 ⏎ b = 1 ⏎ a -=- b``` [https://gitter.im/crystal-lang/crystal?at=600a1620410c22144014db6e]
<FromGitter> <Blacksmoke16> lol what? i imagine its like `a -= (-b)`?
<FromGitter> <jrei:matrix.org> some works in Crystal too 😇
<FromGitter> <jrei:matrix.org> yes it is, it adds b
<FromGitter> <jrei:matrix.org> like said in your article
<straight-shoota> oprypin, any idea what causes shards CI to break on windows?
<oprypin> straight-shoota: well i commented that it's https://github.com/crystal-lang/shards/pull/444 so something about File.touch, right?
<oprypin> i don't know what exactly is happening there, is it a touch of a directory or symlink or something
<oprypin> or is touch just broken?
<FromGitter> <Sija> `File#touch` seems to work fine in other (win32) specs
<straight-shoota> what confuses me is the error output
<straight-shoota> it says "command failed: shards install" + normal output
<straight-shoota> and that's a FailedCommand, so the exit code must be != 0
<straight-shoota> but nothing written to stdout
<straight-shoota> *no error
<oprypin> straight-shoota: ah that's probably just because writing stderr is broken 😂
<straight-shoota> ah
<straight-shoota> that explains
<oprypin> not stderr per se, it's just disabled because 2 streams at once is a deadlock
<oprypin> it would seem very likely that touching a directory isn't a thing on Windows. but not sure if that's what's happening, and not even sure that we *are* dealing with a directory here
<FromGitter> <Sija> oprypin: seems like it: `File.touch(Shards.install_path)`
<oprypin> straight-shoota: anyway in the next 20hrs i don't plan to look into this one. if you do, first of course I'd suggest to try in CI if dropping just the part that touches the directory helps
<straight-shoota> first thing is getting error output
<FromGitter> <Sija> there r no specs for touching directory either
<FromGitter> <Sija> in crystal I mean
<straight-shoota> succeeds
<straight-shoota> I just changed that non-rescued errors are printed to STDOUT instead of STDERR
hightower2 has quit [Ping timeout: 264 seconds]
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/aacc lol what?
<Andriamanitra> what would you expect?
<FromGitter> <Blacksmoke16> either a compiler error that i cant conditionally define an ivar, or the ivar not to be defined, or the ivar's value to be 123 like it should
<Andriamanitra> yeah i guess a compiler error could make sense
<FromGitter> <wyhaines> If anyone is interested, I am going to be noodling around with some Crystal code on Twitch tonight: https://twitch.tv/wyhaines
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 260 seconds]
avane has quit [Quit: ZNC - https://znc.in]
avane has joined #crystal-lang
chachasmooth has quit [Ping timeout: 240 seconds]
chachasmooth has joined #crystal-lang
<FromGitter> <watzon> @jrei:matrix.org I'm trying out Crystalizer. Does it not work for nested objects right now?
<FromGitter> <watzon> Tried this simple example: ⏎ ⏎ ```{ ⏎ "foo": "foo", ⏎ "bar": {} ⏎ }``` [https://gitter.im/crystal-lang/crystal?at=600a5dd2410c22144015807e]
<FromGitter> <watzon> I think I figured out part of the problem. You put a `{% print O %}` below this line (https://github.com/j8r/crystalizer/blob/master/src/crystalizer.cr#L8) you'll see that the type of `O` ends up being `(Bar | String)`, and since that union doesn't have any instance variables it doesn't return any.
<FromGitter> <watzon> An easy fix is to monkey patch `Object` with the `each_ivar` method instead like this: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ and then in the serializer just call `each_ivar` directly on the object being passed in [https://gitter.im/crystal-lang/crystal?at=600a652097132e2480f77556]
<FromGitter> <watzon> Made a PR https://github.com/j8r/crystalizer/pull/3
<FromGitter> <watzon> Now it's time for bed
_ht has joined #crystal-lang
f1reflyylmao is now known as f1refly
fifr[m] has quit [Ping timeout: 268 seconds]
hightower2 has joined #crystal-lang
<hightower2> Hey do I see it right there's currently no OpenID Connect client lib for Crystal? Search for openid or oidc shards turns up nothing
<repo> looks like it
fifr[m] has joined #crystal-lang
<frojnd> Hi there.
<frojnd> Can't find soluton how to make JSON::Any object an Array(String)
<frojnd> Output of `JSON::Any` object is `["foo", "bar"]`
<FromGitter> <Daniel-Worrall> `.as_a`
<FromGitter> <Daniel-Worrall> will get you Array(JSON::Any)
<FromGitter> <Daniel-Worrall> `.as_a.map(&.as_s)`
<FromGitter> <Daniel-Worrall> Unless these are user provided JSON objects, you'll probably want to use deserialisation with a struct using JSON::Serializable
<frojnd> Hm what Am I missing @Daniel-WOrrall https://carc.in/#/r/aaf2
<FromGitter> <Daniel-Worrall> You're trying to put an Array(String) inside an Array(String)
<FromGitter> <Daniel-Worrall> You probably want an Array(Array(String)) there
<frojnd> I'm blind
<frojnd> No: arr_item.each {|o| arr << o}
<frojnd> Thank you!
<FromGitter> <Daniel-Worrall> ahh :)
<FromGitter> <Daniel-Worrall> frojnd, https://carc.in/#/r/aaff here's how that'd be with serializable
<frojnd> Hm nice
<FromGitter> <Daniel-Worrall> If you know the format ahead of time, it saves you from a headache of `.as_`
<frojnd> And if you don't know you must us `.as_`
<FromGitter> <Daniel-Worrall> Yeah, `.as_` is runtime type checking, while defining the class/struct is compile time type checking
<frojnd> Thank you for explanation
<frojnd> I found a bug
<frojnd> ...in my code
<frojnd> Unhandled exception: cast from String to Array(T) failed, at /u
<hightower2> always good :)
<frojnd> :D
<frojnd> So if obj is a String I have a problem
hightower2 has quit [Quit: Leaving]
<frojnd> If item is of type `JSON::Any` and holds a vuel of `"string"` then `arr_item = item.as_a.map(&.as_s)` fails
<frojnd> And I don't now if it's String or Array
<frojnd> Jejks
<frojnd> Or array of strings
<FromGitter> <Daniel-Worrall> I think there's an `as_a?`
<FromGitter> <Daniel-Worrall> so you could do `if arr = obj.as_a?`
<FromGitter> <Daniel-Worrall> `else obj.as_s` etc
<FromGitter> <Daniel-Worrall> but this can be solved with serialisable ;)
<frojnd> I gotta clean my code
<frojnd> It looks totaly messy
<repo> Blacksmoke16: uhhh, wth is happening? xD https://p.jokke.space/m-UnvPs/
<FromGitter> <Blacksmoke16> Possibly related to you doing`@database = ""`
<FromGitter> <Daniel-Worrall> ayy, hitting enter too soon
<FromGitter> <Blacksmoke16> repo might also be worth clearing cache
snapcase has quit [Quit: leaving]
snapcase has joined #crystal-lang
<FromGitter> <jrei:matrix.org> @watzon: Yes, it should support nested types. Thanks for the PR!
<FromGitter> <watzon> You're quite welcome! Tried to make sure that specs are passing, but locally I was getting errors on the YAML Nil spec.
<FromGitter> <watzon> No clue why
<FromGitter> <jrei:matrix.org> oops the CI does not run for PRs
<FromGitter> <watzon> Nope haha
<FromGitter> <jrei:matrix.org> can you rebase please? fixed
<FromGitter> <jrei:matrix.org> I don't really want to monkey-patch Object :/
<FromGitter> <jrei:matrix.org> that's one of the biggest point of this library: avoid having all this added methods (from_json, to_json, etc)
HumanG33k has quit [Quit: Leaving]
<FromGitter> <watzon> I don't know if there's really a way around it, but if you can figure something out I'd love to hear it
<FromGitter> <Blacksmoke16> make it so the obj doesnt serialize itself, problem solved
<FromGitter> <jrei:matrix.org> ...The tests are passing @watzon with the old behavior...
<FromGitter> <watzon> The old tests didn't account for nested objects though
<FromGitter> <watzon> The specs on my PR are passing, but if we can figure out how to not monkey patch Object I could update the PR
<FromGitter> <jrei:matrix.org> For me using `Crystalizer.each_ivar` works...
<FromGitter> <jrei:matrix.org> with your tests
<FromGitter> <watzon> Really? It shouldn't. It wasn't for me.
<FromGitter> <watzon> Let me check again
<FromGitter> <watzon> Oh you know the problem, I need to update the specs to account for the actual issue I was having
<FromGitter> <watzon> Try running this code without my changes Made https://gitter.im/crystal-lang/crystal?at=600a5d96a2354e44ac9d5ef7
<FromGitter> <jrei:matrix.org> 👍️
<FromGitter> <jrei:matrix.org> Working on it, I'll certainly open another PR
ua has quit [Ping timeout: 260 seconds]
<FromGitter> <watzon> There we go. Updated with more relevant specs. Those definitely should not pass with the old code.
<FromGitter> <jrei:matrix.org> Thanks!
<FromGitter> <watzon> The issue is when you have a nested 2+ properties in a class where one of them is a nested type, and another is a primitive.
<FromGitter> <jrei:matrix.org> yeah. We need an other way than yield, which yield an union
<FromGitter> <jrei:matrix.org> it may be possible to use `.as`
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/master/Class.html#cast(other):self-instance-method
<FromGitter> <watzon> Ooh that could work
<FromGitter> <Blacksmoke16> similar to `.as` but can use local vars
<FromGitter> <jrei:matrix.org> that's the opposite of .as
<FromGitter> <Blacksmoke16> how you figure? the example is the same as `number.as(Int32)` which is essentially what the implementation is doing
ua has joined #crystal-lang
<FromGitter> <watzon> The problem is knowing the type to cast to. Since the type of `O` ends up being that union, we can't use it as a casting type.
<FromGitter> <Blacksmoke16> where does the union come from? I assume its not from like `some_var : Int32 | Bool`?
<FromGitter> <Blacksmoke16> `@some_var`*
<FromGitter> <jrei:matrix.org> the method yields each ivar value
<FromGitter> <jrei:matrix.org> It ends up being an union of all ivar types
<FromGitter> <Blacksmoke16> ah
<FromGitter> <Blacksmoke16> whats the reasoning for yielding them versus just macro for each ivar?
<FromGitter> <jrei:matrix.org> It was working, I thought. I try using a macro instead
<FromGitter> <jrei:matrix.org> this logic is shared in several places
<FromGitter> <Blacksmoke16> fun fact not many people may know is you can access ivars of a type outside of the type generically via generics
<FromGitter> <Blacksmoke16> may not know*
<FromGitter> <Blacksmoke16> idk if that helps in this context, but i found it to be good to know
<FromGitter> <jrei:matrix.org> I thought methods overload will dispatch to the correct method...
<FromGitter> <watzon> So I figured out something that works, and this can definitely be refactored into a macro that will work for all of the serializers, but it might be a pain
<FromGitter> <jrei:matrix.org> I mean, if a var has a type `Nested | String`, it will dispatch to either `serialize(v : String)` or `serialize(v : O) forall O`
<FromGitter> <Blacksmoke16> :shrug: order might have some impact here
<FromGitter> <Blacksmoke16> might get dispatched to the first one matching overload
<FromGitter> <jrei:matrix.org> @watzon: right. I try to transform it to a macro, but I can't get iterating over ivars
<FromGitter> <watzon> I think that unions like that will always get dispatched to to `serialize(v : O) forall O` because that's the closest matching overload.
<FromGitter> <watzon> But I could be wrong
<FromGitter> <watzon> This works, although I think more testing needs to be done to see how it will react with ivars that are union types ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=600b2ca73855dd07fd7065d4]
<FromGitter> <jrei:matrix.org> of course, I'm afraid this will cause lots of duplications :(
<FromGitter> <jrei:matrix.org> but if there is no choice...
<FromGitter> <watzon> It might be unavoidable. You could almost definitely refactor it into a macro, but the resulting macro might end up being more confusing in the end
<FromGitter> <watzon> The main problem is that the serialization is done differently in each of the serializers
<FromGitter> <jrei:matrix.org> right
<FromGitter> <watzon> And in some cases, like the ByteFormat serializer, you don't even need the key
<FromGitter> <watzon> It's just a weird case
<FromGitter> <watzon> Granted this can always be refactored later
<FromGitter> <Blacksmoke16> could try to implement the byte format as part of Athena Serializer. Would be pretty doable i think? Something like https://github.com/athena-framework/serializer/blob/master/src/visitors/json_serialization_visitor.cr
<FromGitter> <jrei:matrix.org> maybe, but what would be the point Blacksmoke16 (George Dietrich)?
<FromGitter> <jrei:matrix.org> My library is lower level than yours IMHO
<FromGitter> <jrei:matrix.org> so logically yours could be based on mine :D
<FromGitter> <jrei:matrix.org> @watzon I could just pass `ivar.annotation(::Crystalizer::Field)` somewhere and have a common logic there
<FromGitter> <jrei:matrix.org> ok then, doing as you said
<FromGitter> <Blacksmoke16> :shrug: just as something to do? :p
<FromGitter> <Blacksmoke16> as an experiement*
<FromGitter> <Blacksmoke16> experiment*
<FromGitter> <watzon> Damn
<FromGitter> <watzon> This still breaks things ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=600b2e5cdfdbc1437fa6fc5a]
<FromGitter> <watzon> ```{ ⏎ "ns": {} ⏎ }``` [https://gitter.im/crystal-lang/crystal?at=600b2e7d97132e2480f9921b]
<FromGitter> <jrei:matrix.org> the method dispatch didn't work really as I thought... :(
<FromGitter> <jrei:matrix.org> maybe we have to do it yourself with a generated case/when ?
<FromGitter> <Blacksmoke16> ```code paste, see link``` ⏎ ⏎ I tried it to fwiw [https://gitter.im/crystal-lang/crystal?at=600b2eda2cb18a437c3608fa]
<FromGitter> <Blacksmoke16> too*
<FromGitter> <Blacksmoke16> so its deff possible
<FromGitter> <Blacksmoke16> the hardest part about your implementation is you dont have any interfaces to go off of
<FromGitter> <Blacksmoke16> since its a "native" implementation
<FromGitter> <Blacksmoke16> could try adding a module and having an overload typed to that module?
<FromGitter> <jrei:matrix.org> the module will be included where?
<FromGitter> <Blacksmoke16> wait
<FromGitter> <Blacksmoke16> what if you just move https://github.com/watzon/crystalizer/blob/nested-types/src/json/serialize.cr#L14 to the bottom?
<FromGitter> <Blacksmoke16> @watzon ^
<FromGitter> <watzon> Breaks even worse
<FromGitter> <Blacksmoke16> oof, nvm then
<FromGitter> <Blacksmoke16> ah i missed teh string version of it works
<FromGitter> <Blacksmoke16> could do like `{{pp O}} to see what all is making it to it
<FromGitter> <Blacksmoke16> `{{pp O}}`
<FromGitter> <Blacksmoke16> i dont see why that wouldnt work given `obj.@ns` would be the obj which should create an overload for that type, which should get used 🤔
<FromGitter> <jrei:matrix.org> @Blacksmoke16 already tried to move it
<FromGitter> <jrei:matrix.org> it was my first guess
<FromGitter> <watzon> Fixed it, but we'll definitely need a macro for this
<FromGitter> <watzon> and to clean it up a bit
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=600b30c2ac653a0802d6a131]
<FromGitter> <jrei:matrix.org> got it
<FromGitter> <watzon> Basically checks if the type is a union type , and if so generates a case statement that iterates over the types, then uses `.cast` to cast the type
<FromGitter> <jrei:matrix.org> I have done a `de_unionize` method
<FromGitter> <jrei:matrix.org> which iterates over the union
<FromGitter> <watzon> Perfect
<FromGitter> <Blacksmoke16> nice one!
<FromGitter> <jrei:matrix.org> it is: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=600b321c2cb18a437c3611dc]
<FromGitter> <watzon> Won't the return type of that method still be a union?
<FromGitter> <jrei:matrix.org> not sure, no return types are set
<FromGitter> <jrei:matrix.org> at least tests pass
<FromGitter> <jrei:matrix.org> you may be right
<FromGitter> <watzon> But within the method it's returning on the basis of a case statement, so to the compiler it's still going to be a union coming out
<FromGitter> <watzon> Better to use a macro in cases like this
<FromGitter> <jrei:matrix.org> the return type does not matter here
<FromGitter> <jrei:matrix.org> because we are building to a String or IO
<FromGitter> <watzon> Actually you're correct haha. Missed that.
<FromGitter> <watzon> So this would have to be implemented per-serializer I guess
<FromGitter> <jrei:matrix.org> hopefully it doesn't seem to have issues with deserializing
<FromGitter> <Blacksmoke16> wonder if you could do something with `.class`
<FromGitter> <Blacksmoke16> that returns the actual class type of the value
<FromGitter> <jrei:matrix.org> I tried, didn't work :(
<FromGitter> <jrei:matrix.org> I double check
<FromGitter> <watzon> Using your de_unionize combined with Crystalizer.each_ivar seems to work
<FromGitter> <Blacksmoke16> :sad:
deavmi has quit [Ping timeout: 244 seconds]
<FromGitter> <jrei:matrix.org> 🎉 https://github.com/j8r/crystalizer/pull/4
<FromGitter> <watzon> Lmao
<FromGitter> <watzon> I pushed literal seconds before that
<FromGitter> <jrei:matrix.org> oh... I did kept your commit for specs
<FromGitter> <watzon> Glad we could figure it out though. Good team work all around.
<FromGitter> <jrei:matrix.org> yeah, thanks a lot :D
<FromGitter> <jrei:matrix.org> I admit I mainly use my library along with https://github.com/j8r/crystal-byte-protocol, which is a very special use case
<FromGitter> <watzon> I really like the idea of crystalizer, especially the ByteFormat part. I've been wanting a way to serialize Crystal objects to binary for a while.
<FromGitter> <jrei:matrix.org> thanks! I did want something as dumb as possible, just a sequence of objects represented by bytes
<FromGitter> <watzon> Seems to be exactly that. Basically just JSON or YAML without all the markup getting in the way.
<FromGitter> <jrei:matrix.org> Exactly, it is not needed to pass key names when we control both ends
<FromGitter> <Blacksmoke16> isnt that what like protobuf is?
<FromGitter> <watzon> Protobuf adds some extra metadata to the objects does it
deavmi has joined #crystal-lang
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <watzon> Generally with protocols like that they have a header in each packet that tells the receiver what kind of object to expect, it's length, etc.
<oprypin> watzon, no protobuf relies on schema being already known to the receiver
<FromGitter> <watzon> So it is just a raw byte representation of the object's properties?
<FromGitter> <watzon> I just had a thought though. @jrei:matrix.org, the ByteFormat mode is order dependent isn't it? So if I were to serialize an object and then move a variable below another one in the class would that break things?
<FromGitter> <watzon> I have no idea what order `TypeNode#instance_vars` returns variables actually
<FromGitter> <jrei:matrix.org> @watzon: that's right, it is order dependent
<FromGitter> <jrei:matrix.org> if you move the ivar, it will break. I planned to add annotations to explicitly define the order (but didn't yet)
<FromGitter> <jrei:matrix.org> For my projects, if I modify any message, I just regenerate the JS bindings, recompile and redeploy everything
<FromGitter> <jrei:matrix.org> @watzon I think you have confused with msgpack
<FromGitter> <watzon> Might make more sense just to have a little extra metadata that acts as a key. That way ivars could change position, and new ones could even be added as long as they're not required to be initialized.
<FromGitter> <watzon> That's possible
<FromGitter> <jrei:matrix.org> Yes. Lots of annotations are also missing
<FromGitter> <jrei:matrix.org> If you need those, I'll welcome any PR 😃
<FromGitter> <watzon> I just might do some playing around
<FromGitter> <jrei:matrix.org> I didn't feel the need because I use it for little projects, but I agree for large ones breaking the schema may be painful
<FromGitter> <jrei:matrix.org> I use 0 annotations whatsoever for serialization (for now)
<FromGitter> <jrei:matrix.org> (for our previous union issue)
<FromGitter> <watzon> Oh yeah, you may be right
<FromGitter> <jrei:matrix.org> no sure actually...
<FromGitter> <jrei:matrix.org> oprypin: being at Google, you're familiar with grpc/protobuf. What's your experience with it?
_ht has quit [Remote host closed the connection]
deavmi has quit [Ping timeout: 265 seconds]
<FromGitter> <oprypin:matrix.org> please no D:
<FromGitter> <oprypin:matrix.org> i mean i refrain from comment
<FromGitter> <watzon> Wait, @oprypin:matrix.org works at Google?
<FromGitter> <jrei:matrix.org> that's a public information: https://github.com/oprypin
<FromGitter> <watzon> Never checked haha
<FromGitter> <watzon> Fun
<FromGitter> <jrei:matrix.org> oprypin (https://matrix.to/#/@oprypin:matrix.org): haha, last day I've read https://news.ycombinator.com/item?id=25582962
<FromGitter> <jrei:matrix.org> Does Google use Crystal, at least :D?
<FromGitter> <watzon> Hahahaha
deavmi has joined #crystal-lang
<FromGitter> <watzon> Where does the default value for `#to_s` come from? I can't figure out how this `#<Foo:0x105d22e70>` is being generated.
<FromGitter> <Blacksmoke16> you want to overload `to_s(io : IO) : Nil`
<FromGitter> <Blacksmoke16> or `inspect(io : IO) : Nil`
<FromGitter> <watzon> Ahh wait, it's coming from `Reference`
<FromGitter> <watzon> I don't care about overloading, just trying to take a peek at how the method is getting the address
<FromGitter> <watzon> So It's `Reference#object_id.to_s(16)` that's giving that hex value. Cool.
<FromGitter> <Blacksmoke16> ah, 👍
<FromGitter> <watzon> On an unrelated note, I wish we could do something like this: ⏎ ⏎ ```class Foo(T extends Bar) ⏎ end``` ⏎ ⏎ so that the compiler knows that `T` has to be a type that extends `Bar` [https://gitter.im/crystal-lang/crystal?at=600b4d61d8bdab473952b92e]
<FromGitter> <Blacksmoke16> could prob use a macro for that check, ofc with not as clean syntax
<FromGitter> <watzon> Yeah that's the problem, it would have to be in the initialize method
<FromGitter> <watzon> I've done it, I just don't like it
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/aaiv
<FromGitter> <Blacksmoke16> ah, fair enough
<FromGitter> <watzon> Yeah exactly haha
<FromGitter> <watzon> I mean it's not the worst, but it also doesn't provide any metadata to the compiler for doc generation
<FromGitter> <watzon> Which I think would be the biggest benefit
<FromGitter> <Blacksmoke16> wonder if you could annotate something and do something with mkdocstrings and custom template
<FromGitter> <Blacksmoke16> sec i have an idea
<oprypin> Blacksmoke16, im scared
<FromGitter> <watzon> I'm more intrigued. He is somewhat of a macro wizard.
<FromGitter> <watzon> His powers do scare me sometimes though
<FromGitter> <Blacksmoke16> naw idk
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/aak5 was thinking you could do something like
<FromGitter> <Blacksmoke16> but :shrug:, i give up
<straight-shoota> nah, this needs compiler support
<straight-shoota> and at some point we'll get that, probably
<FromGitter> <watzon> @straight-shoota has adding conditions to generics been discussed?
<straight-shoota> #3803
<DeBot> https://github.com/crystal-lang/crystal/issues/3803 (Covariance and contravariance)
sz0 has joined #crystal-lang