ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.31.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
<FromGitter> <Blacksmoke16> Nice one
<hightower2> The last issue I'm on is that I do have MyEvent, and its object with packed args. Now I need to extract those args to pass them onto MyEvent::Element
<FromGitter> <Blacksmoke16> Not sure I follow
<hightower2> MyEvent is emitted. Then if there are no listeners, the code wants to emit MyEvent::Element. But, the original arguments it was called with are in MyEvent object, not in MyEvent::Element which is just being created.
<hightower2> So I need to figure a way to copy them over, before emitting MyEvent::Element
<FromGitter> <Blacksmoke16> Can't just pass the obj
<hightower2> thought I could but gives some error. Let me stare at it some more
<FromGitter> <Blacksmoke16> Like change element to accept a single argument of e.id
<hightower2> yes that initializer is already there, but it doesn't get chosen, the other one which accepts *args gets chosen, and then complains
<hightower2> I think it's not choosing the right one due to it being defined as obj : {{e.id}} , and e.id doesn't match between MyEvent and MyEvent::Element
<hightower2> if I change {{e.id}} to Event, then it gets further but then fails later down the line again due to the same mismatch where we've made it accept {{e.id}}. Will try replacing again with basic Event, although not sure what this will lead to.
absolutejam2 has quit [Ping timeout: 250 seconds]
absolutejam2 has joined #crystal-lang
<FromGitter> <Blacksmoke16> ok
<hightower2> actually it's clear what it leads to ... since handlers are procs, and procs can't be called with Type+ as we discussed with asterite, it's a no go
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]
<hightower2> Tried with casting, like _emit(My::Element, obj.as({{e.id}}::Element), but got error: can't cast My to My::Element
<FromGitter> <Blacksmoke16> and why doesnt `_emit(My::Element, obj)` work?
<FromGitter> <Blacksmoke16> where `record My::Element < Event, event_obj : My`?
<hightower2> mmm,, ah yeah since the element ones are special cases this would work
<hightower2> I also got it to work just now by using unsafe_as
<FromGitter> <Blacksmoke16> ok
<hightower2> your solution is cleaner, let me try if it works
absolutejam2 has quit [Ping timeout: 268 seconds]
<hightower2> fabulous, got it working
<FromGitter> <Blacksmoke16> 👍
<hightower2> many thanks for the discussion, very informative/educational/appreciated
<FromGitter> <Blacksmoke16> np
_whitelogger has joined #crystal-lang
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7wz2 am i missing something?
<FromGitter> <Blacksmoke16> looks like you just cant access it in a macro
<FromGitter> <lbarasti> About Enumerable mixin, the following raises an exception related to the implementation of `Enumerable#map` ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ https://play.crystal-lang.org/#/r/7wzh [https://gitter.im/crystal-lang/crystal?at=5db8e960e886fb5aa21cb5f3]
<FromGitter> <lbarasti> shall I implement `A#each` differently to work around the issue, or shall we have `Enumerable#map` not call `yield`?
<FromGitter> <Blacksmoke16> i dont that mixin works like that
<FromGitter> <lbarasti> that's what I'd do in Ruby, as far as I can remember
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7wzq
<FromGitter> <Blacksmoke16> not sure thats the best way to go about that tho
<FromGitter> <Blacksmoke16> could just forward the methods to `@ar`
<FromGitter> <tenebrousedge> ^
<FromGitter> <lbarasti> @Blacksmoke16 why is `a.map{|v| pp "hello" }` not printing anything - line 13 in your example https://play.crystal-lang.org/#/r/7wzq
<FromGitter> <Blacksmoke16> because the array is empty so it never yields
<FromGitter> <lbarasti> right, sorry, just noticed
<FromGitter> <lbarasti> workaround it is, then!
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7wzw would be the better way
<FromGitter> <Blacksmoke16> or use `delegate` if you only want to allow a select few methods to be usable on `ar`
<FromGitter> <tenebrousedge> I like `forward_missing_to`
<FromGitter> <lbarasti> oh well, that looks quite the nuclear option to me...
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db8eba710bd4128a1862167]
<FromGitter> <Blacksmoke16> rip
<FromGitter> <lbarasti> let me read about `delegate`, I'm keen on keeping the API of the class including `Enumerable` as small as it can be
<FromGitter> <Blacksmoke16> `delegate :map, to: @ar`
<FromGitter> <lbarasti> `delegate` looks neat!
<FromGitter> <lbarasti> cheers @Blacksmoke16
<FromGitter> <Blacksmoke16> basically just does like ⏎ ⏎ ```def map(*args, **named_args)``` [https://gitter.im/crystal-lang/crystal?at=5db8ebe3fb4dab784a2c9ca5]
<FromGitter> <Blacksmoke16> basically just does like ⏎ ⏎ ```def map(*args, **named_args) ⏎ @ar.map(*args, *named_args) ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5db8ebf1f26ea4729d1d410c]
<FromGitter> <Blacksmoke16> something like that, prob a bit diff since it uses a block
<FromGitter> <watzon> Ok I've been facing an issue which is illustrated in this example https://carc.in/#/r/7x05 ⏎ What I really want is for the `on` method to know that the value passed into the `&block` is always going to be the same type as `klass`, because otherwise every time you call `on` you have to use a guard statement to check the type. Any ideas? The real code is massive and includes a good 770+ different potential
<FromGitter> ... types. I had thought about using a macro to make a union of all of those types instead of using `Types::Base`, but I couldn't get it to work.
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7vta what about something like that approach
<FromGitter> <Blacksmoke16> iterate over children making overloads for each specific type
<FromGitter> <watzon> Ooooh that's an idea
<FromGitter> <watzon> With 770+ classes that's going to be a lot of overloads, but that could work
<FromGitter> <asterite> I provided a simpler solution where you add a proc wrapper
<FromGitter> <asterite> no macros involved
<FromGitter> <Blacksmoke16> oh yea, thats an option too, make things a bit simpler
<FromGitter> <Blacksmoke16> @asterite anything come to mind for https://play.crystal-lang.org/#/r/7wz2?
<FromGitter> <watzon> So basically using a class to wrap the proc? Kind of like the `event` class in @Blacksmoke16's example?
<FromGitter> <asterite> let me try to code it
<FromGitter> <watzon> Very interested in seeing what you come up with. I've been scratching my brain with this one. It's so simple to do in Ruby for obvious reasons.
<FromGitter> <Blacksmoke16> was something liek
<FromGitter> <Blacksmoke16> ```@handler = ->(ev : Event) do ⏎ handler.call(ev.as(T)) ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5db8f3627477946badf41b42]
<FromGitter> <asterite> https://carc.in/#/r/7x07
<FromGitter> <asterite> Right
<FromGitter> <asterite> differences from the original code are in lines 25~27
<FromGitter> <watzon> Yeah I see, very nice. That's pretty simple.
<FromGitter> <watzon> Well that works, thanks @asterite and @Blacksmoke16 :)
<FromGitter> <Blacksmoke16> np
HumanG33k has joined #crystal-lang
HumanG33k has quit [Ping timeout: 240 seconds]
<FromGitter> <watzon> @Blacksmoke16 how would you deal with deserializing data like this: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db8fc439825bd6bacf1bc56]
<FromGitter> <watzon> Where each `@type` matches a class in a lookup table
<FromGitter> <watzon> It's that same hash with 770+ classes
f1refly has quit [Ping timeout: 276 seconds]
f1refly has joined #crystal-lang
<FromGitter> <christopherzimmerman> Finally made some progress on n-dimensional arrays. Feels like I'm using python again :D ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db9053cf26ea4729d1df24d]
<FromGitter> <christopherzimmerman> Porting over the 2D BLAS work won't be hard, but broadcasting is going to be a nightmare
<FromGitter> <watzon> Yeah matrices and ndarrays in Crystal are a nightmare to figure out at first
<FromGitter> <christopherzimmerman> The hardest thing I've run into is writing a generic indexer, right now, you have to specify trailing empty dimensions: ⏎ ⏎ ```a = NDTensor.sequence([3, 3, 2, 1]) ⏎ ⏎ a[[1, 2, ..., ...]] ⏎ # [[ 10.0] ⏎ # [ 11.0]]``` ⏎ ⏎ If you don't add the slices it treats it as a single element lookup instead of a view. [https://gitter.im/crystal-lang/crystal?at=5db906ddfb4dab784a2d49eb]
<FromGitter> <christopherzimmerman> But still, the hardest thing by far, was writing the method to print the array neatly lol.
absolutejam2 has joined #crystal-lang
absolutejam2 has quit [Ping timeout: 268 seconds]
sagax has quit [Ping timeout: 252 seconds]
hemite has joined #crystal-lang
ht_ has joined #crystal-lang
ht_ has quit [Quit: ht_]
absolutejam2 has joined #crystal-lang
DTZUZO has quit [Ping timeout: 264 seconds]
absolutejam2 has quit [Ping timeout: 268 seconds]
<FromGitter> <ImAHopelessDev_gitlab> Notepad has been good to me. however, it's time to move on
<FromGitter> <ImAHopelessDev_gitlab> 100+ comments, wow
<FromGitter> <naqvis> @ImAHopelessDev_gitlab so what's your next choice? notepad++ 😆 or sublime?
<FromGitter> <ImAHopelessDev_gitlab> haha not sure. i haven't used notepad++ is so long... it will be very nostalgic
<FromGitter> <naqvis> 😆
<FromGitter> <ImAHopelessDev_gitlab> what editor you using?
<FromGitter> <naqvis> VS code most of the time and remaining time on vim
<FromGitter> <ImAHopelessDev_gitlab> noice
<FromGitter> <naqvis> VS code is good for polyglot programmers, as for some languages , extensions are too good to give you feel of full-fledged IDE
<FromGitter> <naqvis> would suggest you to give VS code a try
<FromGitter> <ImAHopelessDev_gitlab> i ran into format on save issues on a new windows installation. so i rage quit, then just said f*** everything, went started to code directly in notepad. thus, i created that notepad topic on the forum
<FromGitter> <ImAHopelessDev_gitlab> only downside of notepad for me so far.. is sometimes i'll have a "floating file" open (more than 1), and edit that one instead.. LOL. need to be careful. other than that, i really enjoy it for some odd reason
absolutejam2 has joined #crystal-lang
absolutejam2 has quit [Ping timeout: 265 seconds]
<FromGitter> <yxhuvud> I sometimes end up with 20 emacs windows floating around :P
<FromGitter> <yxhuvud> or frames, using emacs terminology.
return0e has quit [Ping timeout: 240 seconds]
return0e has joined #crystal-lang
alexherbo2 has joined #crystal-lang
beepdog has quit [Remote host closed the connection]
ternarysolo has quit [Read error: Connection reset by peer]
erdnaxeli has quit [Remote host closed the connection]
olbat[m] has quit [Remote host closed the connection]
vegai has quit [Remote host closed the connection]
baweaver has quit [Ping timeout: 240 seconds]
<FromGitter> <j8r> How to use `non_blocking_select`?
<FromGitter> <j8r> When compiling `Crystal 0.32.0-dev` from master, I can't get it working the same as `select`
<FromGitter> <j8r> The purpose is to remove the deprecation warnings in the compiler CI
erdnaxeli has joined #crystal-lang
ternarysolo has joined #crystal-lang
olbat[m] has joined #crystal-lang
vegai has joined #crystal-lang
beepdog has joined #crystal-lang
duane has quit [Ping timeout: 265 seconds]
duane has joined #crystal-lang
mhi^ has left #crystal-lang [#crystal-lang]
teardown has quit [Ping timeout: 240 seconds]
teardown has joined #crystal-lang
lvmbdv has quit [Ping timeout: 240 seconds]
lvmbdv has joined #crystal-lang
DTZUZO has joined #crystal-lang
<FromGitter> <Blacksmoke16> @watzon good luck
<FromGitter> <Blacksmoke16> you'd prob have to do some gross custom overloads
<FromGitter> <Blacksmoke16> there isn't really a good way to do it afaik
absolutejam2 has joined #crystal-lang
<FromGitter> <kinxer> @watzon Is the structure always ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ ? [https://gitter.im/crystal-lang/crystal?at=5db9a378e1c5e915080077cf]
<FromGitter> <ImAHopelessDev_gitlab> Good morning
<FromGitter> <ImAHopelessDev_gitlab> @tenebrousedge and @kinxer thanks for the help last night! `base` value has helped me tremendously with math and dealing with increase/decrease of percentages!!
<FromGitter> <tenebrousedge> 👍
DTZUZO has quit [Ping timeout: 276 seconds]
absolutejam2 has quit [Ping timeout: 268 seconds]
ma_ has joined #crystal-lang
DTZUZO has joined #crystal-lang
<FromGitter> <kinxer> 👍
Yxhuvud has quit [Quit: http://quassel-irc.org - Chat comfortably. Anywhere.]
Yxhuvud has joined #crystal-lang
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]
DTZUZU has quit [Quit: WeeChat 2.2]
absolutejam2 has joined #crystal-lang
<FromGitter> <watzon> @kinxer kind of. Basically if the value is a hash, then it will have a `@type` in it, otherwise the value will be one of the standard JSON types (String, Int32, Float64, Bool)
ht__ has joined #crystal-lang
<FromGitter> <kinxer> How varied and complex are the `<some data>` portions?
DTZUZU has joined #crystal-lang
DTZUZU has quit [Quit: WeeChat 2.2]
<FromGitter> <watzon> Well they all match the same pattern. Basically every key, that has a hash as a value will match a defined class somewhere, where the `@type` key in the hash will match up with a key in a lookup table that says what class it should be deserialized as. So you could potentially have a JSON payload that looks like this: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ That's probably a more perfect representation of
<FromGitter> ... what data could look like [https://gitter.im/crystal-lang/crystal?at=5db9bd3810bd4128a18c1c46]
DTZUZU has joined #crystal-lang
<FromGitter> <kinxer> Yeah, that looks like it would be pretty hairy to deal with. I do not envy you your 770+ classes... I was hoping that there would be some way to load data into an intermediary data structure that could handle any of your options and then use `"@type"` to choose between classes to instantiate from that data structure, but that looks too varied for an approach like that.
<FromGitter> <kinxer> I don't suppose your JSON format has a JSON schema?
duane has quit [Ping timeout: 265 seconds]
<FromGitter> <watzon> Actually it looks like it does https://core.telegram.org/schema/json
<FromGitter> <kinxer> Could https://app.quicktype.io/#l=schema be useful to you (for auto-generating Crystal code from a JSON schema)?
<FromGitter> <kinxer> It looks pretty out of its depth with that much text, actually...
<FromGitter> <kinxer> Oh, there's a CLI option (https://github.com/quicktype/quicktype#generating-code-from-json-schema).
<FromGitter> <asterite> we need to improve JSON deserialization by allowing you to inspect key-values before determining how to deserialize stuff. The current approach is nice for streaming JSON in, but it's a bit bad to dynamically deserialize some things
<FromGitter> <Blacksmoke16> its a feature im planning on adding to my shard, would be similar to https://jmsyst.com/libs/serializer/master/reference/annotations#discriminator
absolutejam2 has quit [Ping timeout: 240 seconds]
<FromGitter> <watzon> @asterite agreed. In normal situations it's pretty good, but for this it's kind of a nightmare
<FromGitter> <Blacksmoke16> it uses `JSON::Any` so would be pretty easy to do
<FromGitter> <kinxer> The `JSON::PullParser` doesn't currently create any intermediate representation (e.g. `JSON::Any`), right? Given that JSON is (by spec) unordered, how do you deserialize based on contents without knowing when the key will occur?
<FromGitter> <kinxer> Backtracking only when you have a key you're looking for?
<FromGitter> <Blacksmoke16> you cant atm, thats the problem
<FromGitter> <kinxer> No, I mean if/when that feature is implemented.
<FromGitter> <Blacksmoke16> cant rewind it nor can look ahead without moving the parser forward
<FromGitter> <kinxer> I'm asking how it would be implemented *in* the JSON parser (presumably `PullParser`)
<FromGitter> <Blacksmoke16> no idea :p
<FromGitter> <Blacksmoke16> my approach was to separate the parsing of the JSON from how to deserialize it
<FromGitter> <Blacksmoke16> i.e. parse as `JSON::Any` then you can deserialize your types from that, which allows you to read the data before consuming it and such
<FromGitter> <kinxer> That slows down parsing, though, and takes more memory.
<FromGitter> <Blacksmoke16> not really
<FromGitter> <Blacksmoke16> the JSON has to be parsed anyway, might be a bit extra overhead for its not going to be anything insane
<FromGitter> <Blacksmoke16> let me make a benchmark
<FromGitter> <watzon> @kinxer idk how quicktype is supposed to help me with Crystal though since it's not a supported language
<FromGitter> <watzon> The ruby output is very unhelpful
<FromGitter> <kinxer> Yeah, I'm interested. I'm going off of intuition and my understanding of why we use `JSON::Serializable`, so I may be far off target.
<FromGitter> <kinxer> @watzon Crystal is one of the supported languages on the website (drop-down on the right).
<FromGitter> <watzon> Ahh I see
<FromGitter> <kinxer> I'm about to try it using the CLI.
<FromGitter> <watzon> Unfortunately doesn't seem super helpful. It just deserializes things normally into a Constructor or a Param
<FromGitter> <watzon> It didn't actually generate code for everything
<FromGitter> <Blacksmoke16> i did find a bug with my thing and nested types tho, i'll fix that tonight :p
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db9c6b8ef84ab3786c64c32]
<FromGitter> <Blacksmoke16> slower yes, but 300ns slower so nbd :shrug:
<FromGitter> <kinxer> @watzon I'm not sure that the "JSON Schema" that Telegram gives is a JSON Schema (https://json-schema.org/).
<FromGitter> <watzon> Doesn't look like it actually
<FromGitter> <watzon> It looks like they prefer this format for code generation
<FromGitter> <kinxer> Which is why QuickType doens't work...
<FromGitter> <watzon> Looks like I'll have to write a code generator myself. Luckily there's a ruby example (https://github.com/southbridgeio/tdlib-ruby/blob/master/bin/parser)
<FromGitter> <asterite> One way I can think of is to use `JSON::Parser#read_raw` to read a JSON::Any. Then you can do some logic on top of that, and when you are done you can deserialize from `any.to_json`. It's a bit bad that you need to convert it to JSON again, maybe there's a simpler way. Another possibility would be to be able to create a `JSON::PullParser` from `JSON::Any` somehow...
<FromGitter> <kinxer> Is it fair to assume that the type to deserialize to will always be on the "top level" of the JSON object?
<FromGitter> <kinxer> That is, not in a nested object.
<FromGitter> <asterite> Probably yes. But if you can get a JSON::Any for the thing you want to deserialize you can dig as deep as you want
<FromGitter> <watzon> Yes, the top level will always have a `@type`
<FromGitter> <asterite> I might try to think of something...
<FromGitter> <watzon> If you can I'd appreciate it. This has been a nightmare
duane has joined #crystal-lang
<FromGitter> <asterite> Yeah, it's asked all the time and we have some workarounds, but it would be nice to have a simple way to handle that
<FromGitter> <confact> @vladfaust I have created an issue on your stripe library as I am working on adding more classes and API calls to it on my repo. Would love to get your help.
dwdv_ has joined #crystal-lang
<FromGitter> <kinxer> @asterite How would someone indicate the mapping of `"@type"` values to classes?
<FromGitter> <kinxer> If we have the JSON string `[{"type": "point", "x": 1, "y": 2}, {"type", "circle", "center": {"type": "point", "x": 5, "y": 0}, "radius": "7"}]`, how do we indicate in our Crystal code how these objects map to our classes?
ma_ has quit [Read error: Connection reset by peer]
<hightower2> Any recommendations how to enable mouse in a crystal cli-based app? Is there even anything that gives hope for running on both unix and win?
<FromGitter> <tenebrousedge> Lasciate ogne speranza, voi ch'intrate
<hightower2> Lo sapevo!
<FromGitter> <tenebrousedge> I actually have no idea about whether it's possible, it just sounds like a path to madness
<hightower2> I'm confident I could get it working on unix, but the other half... I don't wanna know unless there is a ready-made library available :)
<FromGitter> <tenebrousedge> thus far, Crystal and Windows are not friends
dannyAAM has quit [Quit: znc.saru.moe : ZNC 1.6.2 - http://znc.in]
dannyAAM has joined #crystal-lang
<FromGitter> <asterite> @kinxer hehe, cool, in my code I also used point and circle. Amazing!
<FromGitter> <asterite> I was thinking something like this
<FromGitter> <asterite> ``` property type : String```
<FromGitter> <asterite> if you have 770+ classes you'll have to list them... though I wonder what API in the world would have 770+ classes, it seems barely manageable
<FromGitter> <Blacksmoke16> wouldnt it make more sense as a class annotation?
<FromGitter> <Blacksmoke16> with a `key: "type"` field
baweaver has joined #crystal-lang
<FromGitter> <asterite> Maybe, yes. In the small PoC I did I error if there are multiple discriminators. But yes, it could be done like that.
<FromGitter> <Blacksmoke16> mm, multiple discriminators
<FromGitter> <Blacksmoke16> good point
<FromGitter> <asterite> something like `@[JSON::Discriminator(key: "type", mapping: {point: Point, circle: Circle})]`
<hightower2> If I have a starting directory, and need to find a filename that may be in it there (including in subdirs), is there anything ready-made that I can use?
<FromGitter> <Blacksmoke16> yea exactly
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/0.31.1/Dir.html#glob(patterns:Enumerable(String),match_hidden=false,&block:String-%3EUNDERSCORE)-class-method
<FromGitter> <asterite> I mean, having it on top of the class might be better because there's no way to specify multiple discriminators that way. On the other hand having it near the instance variable is less typing, since you'll want to have that vairable for serialization (when you generate the JSON)
<FromGitter> <Blacksmoke16> im assuming this is for determining what type to from_json given the key
<FromGitter> <asterite> Right
<FromGitter> <Blacksmoke16> and the annotation would be added in the parent abstract class? basically like https://jmsyst.com/libs/serializer/master/reference/annotations#discriminator ?
<FromGitter> <asterite> Maybe there are more complex scenarios... but I think the case of "I have a field that says how to deserialize something" is suuuuper common to merit including it in the default serialization logic
<FromGitter> <asterite> Cool, yeah, like that!
<FromGitter> <Blacksmoke16> wouldn't serialization just work if `JSON::Serializable` is included?
<FromGitter> <asterite> But I think I still prefer it to include the annotation right next to the instance variable
<FromGitter> <asterite> What do you mean it would just work?
<FromGitter> <asterite> it currently doesn't
<FromGitter> <Blacksmoke16> i mean once you have your deserialized obj, as long as it includes `JSON::Serializable` (and its children) should just be able to call `.to_json` on it
<FromGitter> <Blacksmoke16> there isn't anything needed from the discriminator to tell it how to serialize
<FromGitter> <asterite> I mean, if you have `@[JSON::Discriminator(key: "type", ...)] abstract class Shape`
<FromGitter> <asterite> but you don't specify `property type : String`
<FromGitter> <asterite> then when calling `to_json` the type won't be there
<FromGitter> <asterite> What I mean is, if we allow `Discriminator` to be at the top of the class, you can forget to define the instance variable that is the actual discriminator, and when serializing back you won't have that field anymore
<FromGitter> <asterite> forcing `Discriminator` to be on the instance variable will guarantee it's in the output too
<FromGitter> <Blacksmoke16> i would expect it to not compile if you give it a key that doesnt exist
<FromGitter> <Blacksmoke16> like `{% raise "Discriminator key is not defined" unless @type.instance_vars.map(&.name.stringify).includes? disc[:key] %}
<FromGitter> <asterite> Good idea
<FromGitter> <Blacksmoke16> same idea if its blank
<FromGitter> <asterite> but I still I still prefer the discriminator to be on top of the instance var
<FromGitter> <asterite> but it can be discussed once I send a PR (I'll do it for JSON and YAML, probably making the "deserialize abstract type by checking all its children" invalid because it's better to provide a concrete logic rather than trying to blindly deserialize all types)
<FromGitter> <kinxer> Annotation question: ⏎ ⏎ ```@[Something(contents: "a")] ⏎ @[Something(value: "b")] ⏎ class A ⏎ end``` ⏎ ⏎ Would the second annotation override the first? [https://gitter.im/crystal-lang/crystal?at=5db9d9b1f26ea4729d244766]
<FromGitter> <Blacksmoke16> no
<FromGitter> <Blacksmoke16> if you do `@type.annotation(Something)` you would get the last, while `@type.annotations(Something)` would get an array of both
<FromGitter> <kinxer> So you could use multiple class-level annotations of the same kind to define the type-class relationships for (de)serialization?
<FromGitter> <Blacksmoke16> got an example?
<FromGitter> <kinxer> Ah, I didn't see above that you can use a named tuple as the contents of an annotation. That makes more sense.
<FromGitter> <kinxer> However, maybe like ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ ? [https://gitter.im/crystal-lang/crystal?at=5db9dbfd2a6494729c6a0d7f]
<FromGitter> <kinxer> I guess you could probably just do that in one annotation, though.
<FromGitter> <Blacksmoke16> pretty much
<FromGitter> <Blacksmoke16> if you go that route i would expect it to be more like
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db9dc939825bd6bacf8170a]
<FromGitter> <kinxer> At that point, I'd probably want another namespace (e.g. `@[JSON::Discriminator::Key("type")]`).
<FromGitter> <Blacksmoke16> prob
<FromGitter> <kinxer> I'm also a bit leery of annotations that rely on other annotations existing, though.
<FromGitter> <kinxer> What was your reasoning for having the annotation on the class rather than the instance variable?
<FromGitter> <Blacksmoke16> because its for determining what child class should be used
<FromGitter> <Blacksmoke16> having it on the ivar would make me think its going to set the ivar to one of those classes based on the value
<FromGitter> <asterite> The nice thing about having it on top of the ivar is that you don't need to come up with names other than `Discriminator`. On top of the class it has to be `Discriminator(key: "type", mapping: {...})`, but on top of the ivar it can just be `Discriminator(...)`
<FromGitter> <asterite> but do we use `key`, or `field` or `property`? (that discussion came up already regarding `JSON::Field`? Is `mapping` okay? etc.
<FromGitter> <asterite> less leeway for bikeshedding :-)
<FromGitter> <Blacksmoke16> ehh still rather have it on the class, another reason is that JMS lib supports exclusion policies using groups, so would allow only trying to deserialize that field if we're in that group
<FromGitter> <kinxer> Another idea (which would be of even more use to @watzon): if the type field is always going to be the same, is there a way that we could have the annotation just define a name and then require that each subclass have a constant String with that name so that we can define the name-class mapping at compile-time?
<FromGitter> <Blacksmoke16> you can just get it from the annotation tho?
<FromGitter> <kinxer> That seems less cumbersome in the superclass than, e.g., creating an annotation with 770+ key-value pairings.
<FromGitter> <kinxer> I'm suggesting that the superclass wouldn't define a mapping.
<FromGitter> <Blacksmoke16> :thinking:
<FromGitter> <kinxer> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db9e042f26ea4729d2481ca]
<FromGitter> <kinxer> Well, the whole "constant in caps" thing kinda shuts down my idea, huh?
<FromGitter> <kinxer> Are you just saying that it wouldn't currently work with generic types?
<FromGitter> <Blacksmoke16> yea, if the classes have generics it wouldnt compile
absolutejam2 has joined #crystal-lang
<FromGitter> <kinxer> I've never actually tried using `JSON::Serializable` with generic types. Does that work right now?
<FromGitter> <Blacksmoke16> probably
<FromGitter> <asterite> > JMS lib supports exclusion policies using groups ⏎ What does that mean?
<FromGitter> <Blacksmoke16> something like that
<FromGitter> <asterite> Nice!
<FromGitter> <Blacksmoke16> yea, they also allow custom ones to be defined, we use some at work like `@[IgnoreOnUpdate]`
<FromGitter> <Blacksmoke16> so those fields are only set on POST and cant be changed via PUT
<FromGitter> <kinxer> Side note: I think that `example.to_json(CrSerializer::SerializationContext.new.groups = ["list"])`is pretty cumbersome (and it's strange that `SerializationContext#groups=`would return a `SerializationContext`, which I don't think it actually does). Maybe a `Context.with_groups(Array(String))` constructor?
<FromGitter> <Blacksmoke16> tbh the library would ideally be implemented within some other framework
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5db9e2eee886fb5aa22426ab]
<FromGitter> <kinxer> It seems like I'm in the minority among the Crystal community, but I personally don't work on web stuff, so if I were to use `CrSerializer` (which I would), I'd be using its API directly. I'll certainly grant you that the `Athena` API is really slick, though.
<FromGitter> <Blacksmoke16> i would also expect the users to implement it within their app, without an example to go off of i dunno how to explain it, but there are ways
<FromGitter> <Blacksmoke16> i guess an example would be like some context factory specific to your application, or override the `serialize` method to implement logic common to all your objects etc
<FromGitter> <Blacksmoke16> but yea i see your point
<FromGitter> <Blacksmoke16> are some other pretty slick stuff under the `Annotations` namespace as well ^
<FromGitter> <Blacksmoke16> expose/exclude/virtual property etc
<FromGitter> <kinxer> Unrelated: is this difference from definition ordering intentional: https://play.crystal-lang.org/#/r/7x31 vs. https://play.crystal-lang.org/#/r/7x32 ?
<FromGitter> <Blacksmoke16> its prob always hitting the first constructor in the first example
<FromGitter> <kinxer> But shouldn't method calls always match the most specific definition?
<FromGitter> <Blacksmoke16> im not sure
alexherbo2 has joined #crystal-lang
<FromGitter> <kinxer> Per the docs: "However, the compiler cannot always figure out the order because there isn't always a total ordering, so it's always better to put less restrictive methods at the end." ⏎ However, that doesn't help this case at all: https://play.crystal-lang.org/#/r/7x3f
<FromGitter> <Blacksmoke16> in this case arent A and B the same thing
<FromGitter> <kinxer> Same outcome if they aren't.
<FromGitter> <Blacksmoke16> `The compiler will always do this for classes and structs under the same hierarchy: it will find the first superclass from which all types inherit from`
<FromGitter> <kinxer> I don't think that's relevant here.
<FromGitter> <Blacksmoke16> no?
<FromGitter> <kinxer> I don't think so because they're two different methods.
<FromGitter> <kinxer> It's not a single scope (method, if-else block, etc.) that could return different types.
<FromGitter> <Blacksmoke16> they resolve to the same type tho?
<FromGitter> <Blacksmoke16> thats my guess at least
<FromGitter> <kinxer> I'm not following your logic here. Could you explain more what you mean?
<FromGitter> <Blacksmoke16> `The real reason the compiler does this is to be able to compile programs faster by not creating all kinds of different similar unions`
<FromGitter> <Blacksmoke16> since B inherits from A that makes B the same type as A
<FromGitter> <Blacksmoke16> and due to that virtual type stuff, it makes the type of B, A
<FromGitter> <Blacksmoke16> i bet if you introduce an abstract parent class to this it would work
<FromGitter> <kinxer> That's not how I read that doc page at all, but, assuming you're right, why would re-opening the class work, then? https://play.crystal-lang.org/#/r/7x3i
<FromGitter> <kinxer> (To clarify, I read that doc page as referring specifically to type resolution for non-specified return types.)
<FromGitter> <Blacksmoke16> :shrug: idk enough about the compiler to say
<FromGitter> <ImAHopelessDev_gitlab> hi
<FromGitter> <kinxer> Hey, @ImAHopelessDev_gitlab.
<hightower2> Hey how do I write regex /\u0020/ in form that crsytal/pcre accept?
<FromGitter> <kinxer> @Blacksmoke16 That's fair. I just find it perplexing (in a bad way) that code with re-opening would function differently than the same code in a single class definition. I was hoping @asterite might still be around to weigh in (and I know that you're more well-versed in Crystal internals than most).
<FromGitter> <kinxer> @hightower2 From here (https://www.regular-expressions.info/unicode.html), "Perl, PCRE, Boost, and std::regex do not support the \uFFFF syntax. They use \x{FFFF} instead."
<FromGitter> <kinxer> @hightower2 https://play.crystal-lang.org/#/r/7x3x
<hightower2> wonderful, thanks
<FromGitter> <kinxer> Np.
<FromGitter> <asterite> @kinxer looks like a bug to me
<FromGitter> <kinxer> Should there be an issue for it?
<FromGitter> <asterite> Please! I think what might be happening is that `A` is found and so it put before `B`, which is unknown. But that's not correct
Nekka has quit [Read error: Connection reset by peer]
Nekka has joined #crystal-lang
duane has quit [Ping timeout: 265 seconds]
hemite has quit [Quit: hemite]
<hightower2> Hey, in "x = y == z || a", is this parsed as (y==z)||, or as y==(z||a) ?
<FromGitter> <tenebrousedge> the second one
hemite has joined #crystal-lang
<FromGitter> <tenebrousedge> I think
<FromGitter> <tenebrousedge> do you use `icr` ?
<hightower2> ok, placed parentheses so don't have to think twice, thanks
<hightower2> I used to, in fact I used/contributed to cry (similar to icr, maybe has some more options unless icr progressed from last time I checked)
<FromGitter> <tenebrousedge> `x = 5 == false || true` returns `true`
<FromGitter> <straight-shoota> I've just overhauled the chapter about operators in the language reference, including a list of operator precedence
<FromGitter> <straight-shoota> crystal-lang/crystal-book#370
<FromGitter> <straight-shoota> So yes, equality binds stronger than logical OR
<hightower2> ah ok so || is what or is in ruby
<hightower2> (priority-wise)
<FromGitter> <ilanpillemer> what method do you add to a class so that if you use puts it uses that method?
<FromGitter> <tenebrousedge> `to_s` ?
<FromGitter> <tenebrousedge> `inspect` is slightly different
<hightower2> ilanpillemer you can also use "p" which calls #inspect on your class
<hightower2> or instance rather
<FromGitter> <ilanpillemer> ``` ⏎ 27 | println m ⏎ ^------ ⏎ Error: undefined method 'println' for top-level ⏎ % ``` [https://gitter.im/crystal-lang/crystal?at=5dba075014d55a3785a5ca4e]
<FromGitter> <ilanpillemer> why not if print works?
<FromGitter> <tenebrousedge> hmm, it doesn't call `to_s`, interesting
<FromGitter> <ilanpillemer> yeah
<FromGitter> <ilanpillemer> I just tried
<FromGitter> <ilanpillemer> I think you have override a specific version of to_s
ht__ has quit [Quit: ht__]
<FromGitter> <ilanpillemer> ``` def to_s(io) ⏎ 1.upto(10) do |i| ⏎ puts i ⏎ end ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5dba07faef84ab3786c8626e]
<FromGitter> <ilanpillemer> this worked.. dont know why
<FromGitter> <tenebrousedge> ahhhh, yes that makes sense
<FromGitter> <ilanpillemer> Why?
<FromGitter> <tenebrousedge> see the link I posted
<FromGitter> <tenebrousedge> `puts` calls `self << obj`, and `<<` passes `self` to `to_s`
<FromGitter> <ilanpillemer> I dont like the lack of symmetry with puts and print
<FromGitter> <ilanpillemer> print should have a println and puts a put
<FromGitter> <ImAHopelessDev_gitlab> I LOVE BASE numbers
<FromGitter> <kinxer> @straight-shoota The operator docs rework is really nice. Thanks for doing that.
<FromGitter> <kinxer> @ImAHopelessDev_gitlab Making things a lot easier?
<FromGitter> <ImAHopelessDev_gitlab> @kinxer yes! :D
<FromGitter> <kinxer> That's good to hear. :)
<FromGitter> <straight-shoota> @ilanpillemer When defining a string representation, you usually implement`to_s(io : IO)`. But it needs to s to append the content to `io`, not print directly to STDOUT.
<FromGitter> <straight-shoota> Thanks @kinxer
<FromGitter> <tenebrousedge> ahhh
<FromGitter> <tenebrousedge> that's a thing
<hightower2> How come that File::Info doesn't have #socket?
absolutejam2 has quit [Ping timeout: 240 seconds]