ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.34.0 | 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
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
blueberrypie has left #crystal-lang ["leaving"]
<FromGitter> <Blacksmoke16> i could believe it
hightower3 has quit [Ping timeout: 246 seconds]
<companion_cube> mm probably false alarm
<FromGitter> <Blacksmoke16> πŸ‘
<FromGitter> <cfishbein> Hi all. Love the language! Question regarding `Socket::IPAddress`: it seems to require defining a port. This feels a bit wonky when dealing with IP Addresses that only meant to identify another user. I will typically just give a `0`. Is this intentional or there just isn't enough usage for this object without a defined port?
Nekka has quit [Ping timeout: 256 seconds]
<FromGitter> <Blacksmoke16> what are you using it for? https://crystal-lang.org/api/master/URI.html might also make sense
<FromGitter> <cfishbein> Just plain user identification. A list of IP addresses on my home network for example.
Nekka has joined #crystal-lang
<FromGitter> <Blacksmoke16> could just store them as strings then?
<FromGitter> <cfishbein> I could, but then I lose a lot of nice validation or address manipulation (to which I would just store them as UInt32's). Not a huge deal and I have plenty of ways to achieve what I need without. Just thought I'd point it out as an oddity since when I think IP Address, I don't typically think of a port being required.
<FromGitter> <Blacksmoke16> Could make an issue about it, I don't recall seeing anything about it
<FromGitter> <cfishbein> I'll mull it over. I'm still not sure if this is just preference or there is really any value in making this kind of change to the standard lib. Thanks for your input!
<FromGitter> <Blacksmoke16> Np, could start off with a forum post as well
<FromGitter> <sam0x17> I also have found it annoying that port is aggressively a part of the ip struct
_whitelogger has joined #crystal-lang
_whitelogger has joined #crystal-lang
rocx has quit [Ping timeout: 260 seconds]
lunarkitty has quit [Ping timeout: 260 seconds]
lunarkitty has joined #crystal-lang
zorp_ has quit [Ping timeout: 265 seconds]
_ht has joined #crystal-lang
_whitelogger has joined #crystal-lang
<raz> blacksmoke16: back! :)
<raz> cfishbein: agree, `Socket::IPAddress` seems to be a bit of a misnomer as it really identifies a socket (which needs ip + port). would suggest for crystal to rename it to `Socket::Address` and invent a new top-level `IPAddress`. these would then be equivalent to java's `InetSocketAddress` (ip+port) vs `InetAddress` (only ip).
tdc has joined #crystal-lang
_ht has quit [Remote host closed the connection]
hightower2 has joined #crystal-lang
<hightower2> Hey is there something like batch-loader for Crystal?
<jhass> what is batch-loader?
<jhass> haven't seen anything, but shouldn't be terribly hard to implement
<raz> yup, would def be interesting to see a shard for that in crystal
zorp_ has joined #crystal-lang
<oprypin> alright, what's going on here? is this a bug? how to work around? https://carc.in/#/r/94w2
<oprypin> surely not https://carc.in/#/r/94w5 as the workaround?
<raz> is "it" allowed inside a "def"?
<oprypin> yes
<raz> ok, then i don't know
<hightower2> isn't this the case similar to instance variables, where they can change between test and use, because external code can modify them
<hightower2> that's the case with the do() block, x is not local to that block, but is only in scope, right?
<hightower2> if you further simplify your "workaround": https://carc.in/#/r/94w9 , then it works
<oprypin> uhh i think it is that, yeah
<oprypin> the interesting thing is `typeof(x) == Nil`
<oprypin> so in reality that value cant change at all
<oprypin> but i think the same explanation still applies, i forgot about it
<oprypin> more clearly seen in https://carc.in/#/r/94wb - vs https://carc.in/#/r/94wd
<oprypin> dont know if it's worth any attention but `if x` should be allowed to be discarded even in this case if `x : Nil`
<raz> guys... what is up with the little spinny crystal thinger on the forum
<raz> that alignment triggers my OCD so bad
<hightower2> haha it's really bad :)
<oprypin> raz, lol for me it'
<oprypin> raz, lol for me it's not even there
<raz> oprypin: it's sneaky, only appears when you click on a thread
<oprypin> ah it shows misaligned like that briefly and then disappears
<oprypin> must be Discourse changed under our feet
<raz> well, probably not the highest priority thing. :p
<raz> it just hurts my teeth :E
hsh has quit [Quit: Connection closed for inactivity]
mntmn_ has joined #crystal-lang
<mntmn_> hi, we're making an aarch64 based laptop and i wanted to try crystal on it. where can i find an aarch64 binary? the build process already seems to require a crystal binary?
allisio has joined #crystal-lang
<allisio> Should this work? https://carc.in/#/r/94x9
<allisio> It seems like the exhaustiveness mechanism should be able to prove there won't be an issue, no?
<oprypin> allisio, what do u mean exhaustiveness... the Types enum has nothing to do with anything else in the code, and also happens to be redundant
<oprypin> workaround: https://carc.in/#/r/94xb
<oprypin> idiomatic: https://carc.in/#/r/94xg
<oprypin> idiomatic likely in a better direction: https://carc.in/#/r/94xi
<allisio> oprypin: Thanks! I think I'll do some research into how as() works.
<allisio> What causes the re-assignment approach to work?
rocx has joined #crystal-lang
OvermindDL1 has quit [Ping timeout: 260 seconds]
OvermindDL1 has joined #crystal-lang
<oprypin> oh wow. the compilation of this fails only on Windows. that's crazy
<oprypin> no i dont get it, what's up with this example
<oprypin> is `caller` an actual thing???
<oprypin> LOL this is the *output* of the example, not a runtime error
<FromGitter> <Blacksmoke16> o/ raz
<raz> \o
allisio has quit [Remote host closed the connection]
<FromGitter> <Blacksmoke16> so i wanted to get your opinion on something
<FromGitter> <Blacksmoke16> ```code paste, see link``` ⏎ ⏎ So currently parm converters accept the request, and return the converted value [https://gitter.im/crystal-lang/crystal?at=5eca7d99549761730b548c66]
<FromGitter> <Blacksmoke16> i think i want to decouple the class that resolves the arguments from knowing about converters
sz0 has joined #crystal-lang
<FromGitter> <Blacksmoke16> so wanted to get your thoughts on something like: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5eca7e5a4c9b0f060d1e58d5]
<FromGitter> <Blacksmoke16> where `configuration` would hold metadata associated with the converter, like name of the argument it applies to, and/or any user supplied stuff. `@[ART::ParamConverter("num", converter: MultiplyConverter, by: 3)]`
<FromGitter> <Blacksmoke16> i.e. `value * configuration.options[:by]`
<FromGitter> <Blacksmoke16> or something like that
<raz> hum. not sure i fully understand, but that annotations syntax looks very good to me.
<raz> as a framework-user that's exactly what i want to write.
<FromGitter> <Blacksmoke16> essentially `request.attributes` stores arbitrary data, like query/path params, plus whatever else the user stored in it. So param converters now would just be mutating those values in attributes
<raz> or more precisely, i want to write: @[ART::Param("num", parse_as: Integer, addl_options: "could go here")]`
<FromGitter> <Blacksmoke16> well assuming the route is like `/multiply/:num` that would already happen
<FromGitter> <Blacksmoke16> would be supplied as `Int32` or whatever Int restriction the argument has
<raz> ah yea sorry, that example was a bit bad
<raz> @[ART::Param("num", parse_as: IntegerParam, addl_options: "could go here")]
<FromGitter> <Blacksmoke16> just a diff syntax to `ParamConverter`?
<raz> i think that extra "Param" makes it clearer. i.e. give the converter class, and any optional arguments to it
<raz> yea, it's pretty much the same i think. just "ParamConverter" sounds weird to me. as a user i want to declare a "Param" there.
<raz> (minor difference, just what caught my eye)
<FromGitter> <Blacksmoke16> sorry to be more clear
<FromGitter> <Blacksmoke16> ```@[ART::Get("/multiply/:num")] ⏎ def multiply(num : Int64) : Int64 ⏎ num ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5eca80859da05a060a29f068]
<FromGitter> <Blacksmoke16> this already works w/o conversion
<raz> ahhh
<FromGitter> <Blacksmoke16> its a Param *Converter* because it takes the value, and mutates/changes what it is
<raz> yes, now it makes sense, i didn't realize the annotation is optional. yes that's perfect then!
<FromGitter> <Blacksmoke16> E.x. `/user/:id`, `id` => `User` obj
<FromGitter> <Blacksmoke16> πŸ‘ and you cool with that syntax, i.e. getting/setting value from attributes, versus just returning the value
<FromGitter> <Blacksmoke16> bit more verbose, but also a bit more flexible
<raz> hmm, what do you mean by returning the value?
<raz> ohhhhh
<raz> you mean *in* the converter class
<FromGitter> <Blacksmoke16> yea, currently the `#convert` method returns the converted value
<FromGitter> <Blacksmoke16> this would make it set it on the `request` object, and essentially return `nil`
<raz> yea that looks fine to me. these converters are prob not written/changed often anyway. (just write one for each type, then forget about them)
<raz> if plain out returning the value is also possible, that might feel more natural, but doesn't seem like a biggie to me
<raz> (more natural = one less thing that could go wrong, like forgetting the syntax or accidentally writing it to a wrong place or such)
<FromGitter> <Blacksmoke16> yea, ideally they would be semi generic, i.e. `@[ART::ParamConverter("user", converter: DBConverter, model: User)]`, then in code you could do like `configuration.options[:model].find id`
<raz> yup i'm not familiar enough with athena to know what that would take. if it's a major undertaking i'd say the current way is plenty fine, too
<FromGitter> <Blacksmoke16> mainly just separation of concerns
<raz> in 99% of cases i personally likely wouldn't even use a converter but just stick with the primitive types (integer, string) and do lookups etc. in the handler-body
<raz> cause otherwise i have to think about how to do error handling when the converter fails etc.
<FromGitter> <Blacksmoke16> would still need to do that in the handler tho no?
<FromGitter> <Blacksmoke16> converter is there to remove that boiler plate, of the query, what if its missing, etc
<FromGitter> <Blacksmoke16> granted if you only looking up one or two things, prob not worth it
<raz> yes, but there i know how to do it cause i do it all the time. converters i'd likely just use for very basic things like `String -> Time?`. not for sth like a user-lookup.
<FromGitter> <Blacksmoke16> fair enough
<raz> (but that's just a mindset thing. if error handling with converters is obvious enough, i might use them for more elaborate stuff too)
<FromGitter> <Blacksmoke16> error handling in athena are just exceptions, i.e. https://github.com/Blacksmoke16/athena-blog-tutorial/blob/master/src/converters/db_converter.cr (using old syntax but you get the idea)
<raz> Blacksmoke16: yep, but where do i get that exception? like if in my handler if want to display a different thing depending on whether user was found / not found / lookup error
<FromGitter> <Blacksmoke16> @neutrinog `#write` now returns the number of bytes written
<FromGitter> <Blacksmoke16> versus `nil`
<FromGitter> <neutrinog> @Blacksmoke16 but I'm not writing anything.
<FromGitter> <Blacksmoke16> can you share the code that reproduces?
<FromGitter> <Blacksmoke16> raz: i think i see what you mean. yea, if an error happens in a converter your handler wouldnt run
<FromGitter> <neutrinog> well, the codebase is quite large, and the error doesn't give me any hints. https://github.com/neutrinog/prism
<FromGitter> <neutrinog> It's just running `crystal spec` on the codebase.
<FromGitter> <Blacksmoke16> so you would want to cover your bases there
<jhass> mntmn_: you may need to bootstrap by cross compiling
<FromGitter> <Blacksmoke16> @neutrinog try running with `--error-trace`?
<raz> Blacksmoke16: yup. and i think that's fine. malformed URL = http 5xx. for more complicated stuff with more than 2 possible outcomes, well, why not do it in the method body :) (or some kind of before-handler like you need for auth anyway)
<raz> http 4xx actually
<FromGitter> <Blacksmoke16> mainly since im not a fan of duplicating essentially the same logic in every handler i need to go from and ID to a db obj
<raz> yep, hence "before-handler'. not sure how athena does these atm.
<FromGitter> <Blacksmoke16> when i can define the not found, invalid id, etc logic in a centralized place (that can be tested)
<raz> like if you want to wrap multiple endpoints with auth (but not all of them).
<FromGitter> <Blacksmoke16> but for what you want, would need another event that happens after arguments are resolved, but before handler is executed
<raz> hmmm.
<FromGitter> <Blacksmoke16> sadly i dont have anything specific to handling auth built in atm
<FromGitter> <Blacksmoke16> its on my list
<FromGitter> <neutrinog> @Blacksmoke16 I guessed it was from baked_file_system since that was the only lib I had that does IO. Adding the error trace confirmed that.
<FromGitter> <Blacksmoke16> πŸ‘
<raz> yea actually... in my mind it would be something like @[ART::Before(DoAuthStuff)]. where DoAuthStuff has full access to the request-context and can make variables available to it (such as a `user`)
<raz> kinda like your converters, except not bound to a specific param
<FromGitter> <Blacksmoke16> thats what listeners are no?
<raz> ah, good! - i haven't dabbled with athena so didn't know :)
<FromGitter> <Blacksmoke16> it wouldnt be as specific as annotating a method tho
<raz> well for auth it has to be
<FromGitter> <Blacksmoke16> would be global for all endpoints, and the listener would need to determine if it should act
<raz> some endpoints want auth, others don't
<raz> some want different auth from the rest
<FromGitter> <Blacksmoke16> https://github.com/crystal-lang/crystal/issues/9322 would be one option i think
<FromGitter> <Blacksmoke16> then the listener could check for a like `ART::Security` annotation, and noop if its not there
<FromGitter> <Blacksmoke16> but i havent thought too much about this side of things yet
<raz> yup, not sure how it can be implemented. that's just what i need it as a user. just like your ParamConverter is specific to a handler, things like auth also need to be
<raz> (bonus points for being able to wrap it around multiple handlers w/o having to repeat the annotation - but that's already in the luxury dept)
<FromGitter> <Blacksmoke16> id prob make it so you could add the annotation to the class to affect all handlers within it
<raz> yea, would worry about that last. per-endpoint is the important bit.
<FromGitter> <neutrinog> is there a nightly version of the api docs somewhere?
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/master/
<FromGitter> <neutrinog> or do I have to generate it manually?
zorp_ has quit [Ping timeout: 260 seconds]
<FromGitter> <neutrinog> πŸ‘
<FromGitter> <Blacksmoke16> raz: its on my list, deff quite a bit more thinking required in that area
<raz> yup yup
<FromGitter> <Blacksmoke16> other thing i wanted to show, https://github.com/athena-framework/athena/pull/60/files
<raz> as an impl idea, you could probably also do the per-endpoint constraint "in reverse". e.g. DoAuthStuff could be a Listener that runs for every request. but have a guard in it that looks up the id of the called endpoint whitelist. that whitelist could then be populated with annotations at compile time.
<FromGitter> <Blacksmoke16> need to add a section on error handling, but that should make for a bit better intro when navigating to the docs
<raz> in a whitelist*
<raz> yay, docs!
<FromGitter> <Blacksmoke16> maybe as a MVP, otherwise security is usually more in depth than white/blacklist
<FromGitter> <Blacksmoke16> like what we do at work `@Security("has_role('ROLE_ACTIVE_CUSTOMER') and has_role('ROLE_RECRUITING_USER') and has_role('ROLE_FEATURE_INTERVIEWS')")`
<raz> true, i didn't explain it well. there could still be multiple listeners of course. or one listener that behaves differently depending on which endpoint was called.
<FromGitter> <Blacksmoke16> ah true true
<raz> yea... you'll figure it out :)
<FromGitter> <Blacksmoke16> like a simple whitelist handler
<FromGitter> <Blacksmoke16> listener*
<raz> (whitelist was also misleading, i guess the annotation would write the params for the listener-call in there)
<FromGitter> <Blacksmoke16> most of the work would be behind the scenes. as i would now need built in ways to determine *how* to authenticate a given user
<FromGitter> <Blacksmoke16> or determine what roles/permissions they have
<FromGitter> <Blacksmoke16> and*
<raz> well, that's what the listener would do (to be implemented by the framework user)
<raz> it could check http auth headers, cookies, or whatever the dev desires
<FromGitter> <Blacksmoke16> i suppose i could start simpler
<FromGitter> <Blacksmoke16> lay the ground work and can always build upon it
<raz> yup yup. i think "per-endpoint listener" is the goal. since your listeners basically behave like middleware (run for all requests). so the annotation would only need to be able to provide the per-endpoint params it (and the information whether it should run for a given endpoint).
<raz> to it*
<FromGitter> <neutrinog> hey, it appears you have to manually count how many bytes you write to `IO`. Is that true or did I miss something?
<FromGitter> <Blacksmoke16> hm? also https://github.com/crystal-lang/crystal/pull/9233 is what i was talking about earlier
<FromGitter> <neutrinog> The problem I'm getting is related to a line like this `IO.copy file, encoder` where encoder is is a subclass of `IO` that implements a write method without returning the number of bytes.
<FromGitter> <Blacksmoke16> afaik just needs to add a `slice.size` at the bottom?
<raz> blacksmoke16: https://carc.in/#/r/94yj (just to clarify the idea in pseudo-code, i.e. how i think you could still keep your listeners global but constrain them to individual endpoints with annotations)
<FromGitter> <neutrinog> at first glance I thought as much, however I wasn't sure since it was writing some strings as well.
<FromGitter> <Blacksmoke16> raz: πŸ‘
<FromGitter> <neutrinog> @Blacksmoke16 for example this line adds an extra byte https://github.com/schovi/baked_file_system/blob/master/src/loader/string_encoder.cr#L25
<FromGitter> <Blacksmoke16> ah, yea im not super familiar with this :/
<FromGitter> <neutrinog> np. I was just wondering if IO could tell me how many bytes it received or if I had to do it manually. Which is better, etc.
alexherbo2 has joined #crystal-lang
<FromGitter> <neutrinog> I'm pretty certain the answer is no, it cannot, but thought I'd double check.
<FromGitter> <Blacksmoke16> i think you would know the size of the slice, but would just need to account for the extra stuff?
<FromGitter> <neutrinog> that's the way it looks.
<FromGitter> <neutrinog> on a different note is something like this `def hello(arg, *, another_arg)` simply making use of the splat to force the subsequent args to be named arguments?
<FromGitter> <neutrinog> because you can't actually use the `*` by itself right?
deavmi has quit [Quit: Eish! Load shedding.]
deavmi has joined #crystal-lang
<FromGitter> <Blacksmoke16> thats already a thing
<FromGitter> <Blacksmoke16> its not named so isnt a way to reference it
<FromGitter> <naqvis> When a splat method argument has no name, it means no more positional arguments can be passed, and next arguments must be passed as named arguments.
deavmi has quit [Quit: Eish! Load shedding.]
iwq has quit [Ping timeout: 246 seconds]
deavmi has joined #crystal-lang
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
deavmi has quit [Read error: Connection reset by peer]
deavmi_ has joined #crystal-lang
<oprypin> neutrinog, no it's not "making use of splat" seeing as splat args are not allowed then
<oprypin> it is a special syntax but in line with what's familiar
iwq has joined #crystal-lang
deavmi_ has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<oprypin> both `*` and `*args` signify that following args are keyword-only, but `*` is not the same as `*never_use_these`
hightower2 has quit [Remote host closed the connection]
alexherbo25 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 272 seconds]
alexherbo25 is now known as alexherbo2
HumanGeek has quit [Ping timeout: 256 seconds]
HumanG33k has joined #crystal-lang
<FromGitter> <neutrinog> thanks for the clarification @oprypin
alexherbo21 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 260 seconds]
alexherbo21 is now known as alexherbo2
gangstacat has quit [Quit: Ĝis!]
gangstacat has joined #crystal-lang
<FromGitter> <Blacksmoke16> Hm raz might to revisit somethings
deavmi has quit [Quit: Eish! Load shedding.]
<FromGitter> <Blacksmoke16> `missing key 'type' for named tuple NamedTuple(converter: DoubleConverter.class)`
<FromGitter> <Blacksmoke16> unions
deavmi has joined #crystal-lang
<FromGitter> <Blacksmoke16> is tricky, got this working
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ecab7a7a91f120a6cbd6b92]
<raz> welcome to my world
* raz evil laughter from tuple hell
<FromGitter> <Blacksmoke16> better solution would be to define specific metadata types for each converter
deavmi has quit [Read error: Connection reset by peer]
deavmi_ has joined #crystal-lang
<raz> yup, i think that's basically the "arbitrary mixed-type tuples" problem i cried about the other day
<FromGitter> <Blacksmoke16> pretty much
<FromGitter> <Blacksmoke16> ill have to think on it
<raz> yea, haven't found a great solution to it since then. it's either more verbosity (addtl struct / class) or rather hell'ish macros.
<raz> sometimes one can cheat by passing **kwargs around, but that's very case-dependentt
<FromGitter> <Blacksmoke16> prob end up going the additional struct route. problem then would be how to know which one to use
<raz> yup, that very much depends on the details. tends to be an arm-wrestle between macro & runtime context
<FromGitter> <Blacksmoke16> possibly something like `@[ART::ParamConverter("value", metadata: DoubleConverterMetadata)]`
<FromGitter> <Blacksmoke16> actual converter can be derived from the metadata, plus could contain things directly related to it
<FromGitter> <Blacksmoke16> i.e. back to `@[ART::ParamConverter("value", metadata: MultiplyConverterMetadata, by: 3)]`
<raz> yea, although, if you pass DoubleConverter *and* DoubleConverterMeta you could perhaps just ask the user to make a separate converter for each case himself
<raz> so he has to fiddle with only one (sub-)class instead of two
<raz> it's tricky tho in either case...
<FromGitter> <Blacksmoke16> well they are two different things
<FromGitter> <Blacksmoke16> metadata would contain like extra values supplied in the annotation that would determine how the actual converter obj functions
<FromGitter> <Blacksmoke16> sec, let me make an example
<raz> ah true, gotcha
<raz> well, perhaps, with some macro trickery, the *Metadata class could be autogenerated and hidden from the user, hmm.
<raz> (not sure if that's doable with annotations at play tho)
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ecabaf04412600ccd653e13]
<raz> phew. yea, i guess that could work. but tbh, would not be keen on having to write/remember such a thinig
<raz> (pure boilerplate)
<FromGitter> <Blacksmoke16> kinda sucks, because you need three types to handle this, the annotation, the metdata, and the actual converter. Would be nice if the annotation was the metadata
<raz> yep, +1 on the last bit
<raz> my belly feeling is a convoluted macro could get you there. but... don't ask for details plz :D
<raz> (cause it's really just a feeling, not sure how/where)
<FromGitter> <Blacksmoke16> what about `@[ART::ParamConverter("num", converter: MultiplyConverter, by: 3)]`, then just assuming the metadata is converter name + `Metadata`
<raz> yes, that's the direction i'm thinking. and ideally the +Metadata struct/class would be auto-generated so the user doesn't have to even know it exists
<FromGitter> <Blacksmoke16> auto-generated based on what?
<FromGitter> <Blacksmoke16> i couldnt possibly know
<raz> i guess more annotations in the MultiplyConverter class
<raz> it's the one that wants the "by"-parameter, right?
<raz> (well, annotations or setter-style macros... that's why my idea gets blurry)
<raz> why/where*
<FromGitter> <Blacksmoke16> could work for simple cases, but i could also see like optional, or defaulted values
<raz> ...very blurry
<FromGitter> <Blacksmoke16> which i wouldnt know about
<raz> yup yup
<FromGitter> <Blacksmoke16> granted as you said before, these wont be super common, so being a bit more verbose for some compile time safety/flexibility is prob alright
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ecabc9b9da05a060a2a8166]
<raz> yea, i think the extra verbosity of having to declare them wouldn't be a big deal
<raz> but the impl is likely gonna be a headache
<raz> ah yea, you mean not auto-generate
<FromGitter> <Blacksmoke16> then annotation would be `@[ART::ParamConverter("time", converter: TimeConverter)]`
<FromGitter> <Blacksmoke16> ooo
<FromGitter> <Blacksmoke16> i got it
<FromGitter> <Blacksmoke16> make `metadata` key optional, defaulting to `converter` + `Metadata`
<FromGitter> <Blacksmoke16> but would allow doing like `metadata: DBConverterMetadata(User)`, now could use generics if so desired
<raz> sounds promising
<FromGitter> <Blacksmoke16> ill try that approach out
<FromGitter> <Blacksmoke16> or even doing something like
<FromGitter> <Blacksmoke16> ```struct TimeConverter ⏎ METADATA = TimeConverterMetadata ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5ecabd6e225dc25f54a2262e]
<FromGitter> <Blacksmoke16> :shrug:
<raz> πŸ‘
deavmi_ has quit [Quit: Eish! Load shedding.]
deavmi has joined #crystal-lang
<FromGitter> <j8r> I don't understand why we this is allowed : https://play.crystal-lang.org/#/r/94zo
<FromGitter> <j8r> We can define ivars in standard methods? Sounds to be a bad practise
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/94zs its nil by default
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <j8r> yeah that's not good
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<FromGitter> <j8r> it annoys me quite a bit to have all this yaml/json methods everywhere one the API docs :(
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <j8r> `to_json`, `to_pretty_json` and `to_yaml` are defined in every objects
<FromGitter> <Blacksmoke16> makes sense?
<FromGitter> <j8r> And calling them won't always work - in this case, they are "dead" methods
<FromGitter> <j8r> It doesn't make sense
<FromGitter> <j8r> For example in IOs
<FromGitter> <Blacksmoke16> prob should just be defined if you `require "json"`
<FromGitter> <j8r> try STDOUT.to_json for instance
<FromGitter> <j8r> same for `from_json` and `from_yaml`
<FromGitter> <naqvis> just published Crystal Webview bindings (https://github.com/naqvis/webview) shard. Supports *two-way* bindings (Crystal <=> JS) ❀️
<FromGitter> <Blacksmoke16> that the thing you were talking about the other day? that was quick :p
<FromGitter> <naqvis> yeah, yesterday :)
<FromGitter> <naqvis> Library API is quite small
<FromGitter> <naqvis> but its really awsome and powerful library
<FromGitter> <naqvis> Have used this previously in other languages for desktop application development
deavmi has quit [Quit: Eish! Load shedding.]
<FromGitter> <naqvis> only thing which i'm not satisfied with this shard is that it requires user to do compilation of library
<FromGitter> <Blacksmoke16> could you make it a post install step?
<FromGitter> <naqvis> post install of shard?
<FromGitter> <Blacksmoke16> yea
<FromGitter> <naqvis> but does that get invoked before this shard is compiled?
<FromGitter> <naqvis> or post install mean, after download of shard source code?
<FromGitter> <naqvis> wow, thank you @Blacksmoke16
<FromGitter> <Blacksmoke16> also the libraries section might be helpful too?
<FromGitter> <naqvis> πŸ‘
<FromGitter> <naqvis> but thing is, those are OS dependent
<FromGitter> <naqvis> on OSX they are different than on *nix and similarly on Windows
<FromGitter> <naqvis> though Windows isn't in my radar atm lol
<FromGitter> <Blacksmoke16> cant determine what OS you're on and run the corresponding code? could use a bash script as well
<FromGitter> <naqvis> yeah true
<FromGitter> <naqvis> i was talking about those 'libraries` section of shard.yml
<FromGitter> <Blacksmoke16> ah gotcha
<FromGitter> <naqvis> isn't that static content?
<FromGitter> <Blacksmoke16> prob?
deavmi has joined #crystal-lang
<FromGitter> <naqvis> for this use-case, libraries are system dependent and they will be different on each OS
<FromGitter> <naqvis> so having listing all platforms libraries good?
<FromGitter> <Blacksmoke16> given its just informational, prob dont need to get too specific?
<FromGitter> <naqvis> e.g. on OSX it will require `Cocoa/WebKit` while on Linux it will be relying on `Gtk-webkit2` and on windows it will be `MSHTML or EdgeHTML`
<FromGitter> <naqvis> yeah
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
return0e has joined #crystal-lang
deavmi_ has joined #crystal-lang
deavmi has quit [Read error: Connection reset by peer]
return0e has quit [Remote host closed the connection]
<FromGitter> <Blacksmoke16> raz: i thought about it a bit more
<FromGitter> <Blacksmoke16> new plan :P
<FromGitter> <Blacksmoke16> have a default metadata object for the cases where the converter doesnt need extra data
<FromGitter> <Blacksmoke16> and add an optional constant to the converter to specify the metadata obj it should use (defaulting to the built in empty one if missing)
tdc has quit [Ping timeout: 258 seconds]
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ecae08e2c49c45f5a9ca976]
<FromGitter> <Blacksmoke16> not too bad
DTZUZU has joined #crystal-lang
alexherbo2 has quit [Quit: The Lounge - https://thelounge.chat]
alexherbo2 has joined #crystal-lang
<raz> yup, looks good to me. quite java'ish, but solid
<raz> and terse where it needs to be (in the actual method annotations)
<FromGitter> <Blacksmoke16> could make some macro to define the initializer that would hide the name/converter so user just have to define the new stuff but :shrug:
<raz> yup, if it was my thinger i would probably try to hide the above two behind a macro.
<FromGitter> <Blacksmoke16> hm
<FromGitter> <Blacksmoke16> ```metadata MultiplyConverterMetadata, by : Int32````
<oprypin> @naqvis: whaaa that's so weird, is the library really 3 separate things on separate platforms?
<oprypin> also edgehtml is discontinued 😬
<oprypin> naqvis, egh it needs some CI 😬
<raz> Blacksmoke16: ```create_converter(Multiply, by : Int32) { ...code that goes in the apply-method... }```
<raz> :)
<FromGitter> <Blacksmoke16> hmm
<FromGitter> <Blacksmoke16> could work assuming the converter itself doesnt have any dependencies
<FromGitter> <Blacksmoke16> or at least make those some named optional argument
<oprypin> naqvis, have u seen instructions how to compile webview for windows using cl.exe?
<raz> kinda like this. not sure if it's possible, nor if it fits the spirit of your framework, tho
<FromGitter> <Blacksmoke16> Deff a bit more convenient
<raz> yeh but also magical (less discoverable)
<oprypin> i'd guess `cl /c webview.cc -Ldll/x64 -lWebView2Loader -o windows/webview.obj` or something
<raz> if it's even possible syntax-wise, not sure about that. kinda just typed out what i think i would like to write as a framework-user. (which naturally is: as few keystrokes as possible ;))
<FromGitter> <Blacksmoke16> It is
<FromGitter> <Blacksmoke16> Essentially just a wrapper around the record macro
<raz> yup, well, it would also spare me from having to know what a ADI::Register is
<oprypin> naqvis, and as a suggestion, i just dont like this `darwin/` subdirectory stuff. i'd put it into one directory.
<FromGitter> <Blacksmoke16> That's where the real magic happens ha
<raz> i can imagine. thing is... unless i _have_ to know about it in common usage, i'd prefer not to ;)
<raz> like if i'm just typing out my API handlers and stuff, i like some cushion between me and the magic machinery
zorp_ has joined #crystal-lang
<FromGitter> <Blacksmoke16> I'm definitely going to keep this in mind, but focus on the structure/lower level side of things for now. Probably do another pass to add some abstractions
<raz> yup, sounds like a good plan
<FromGitter> <Blacksmoke16> Then can be assured all that is working well
<raz> yep, syntax sugar can also backfire when things are still in flux
<FromGitter> <Blacksmoke16> Indeed
<FromGitter> <Blacksmoke16> Especially since it's a bit more advanced feature and probably won't be too many of them
<FromGitter> <Blacksmoke16> Debating if I want to supply some built in ones
alexherbo2 has quit [Ping timeout: 272 seconds]
alexherbo2 has joined #crystal-lang
alexherbo2 has quit [Ping timeout: 240 seconds]
zorp_ has quit [Ping timeout: 258 seconds]
oprypin has quit [Remote host closed the connection]
oprypin has joined #crystal-lang
FromGitter has quit [Remote host closed the connection]
oprypin has quit [Client Quit]
rocx1 has joined #crystal-lang
rocx has quit [Ping timeout: 260 seconds]
rocx1 is now known as rocx
FromGitter has joined #crystal-lang
oprypin has joined #crystal-lang
zorp_ has joined #crystal-lang