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: No route to host]
deavmi has joined #crystal-lang
DTZUZU has quit [Read error: Connection reset by peer]
DTZUZU2 has joined #crystal-lang
rocx has quit [Quit: 👏 developers 👏 developers 👏 developers 👏 developers 👏 developers]
rocx has joined #crystal-lang
<FromGitter> <sam0x17> I'm trying to write a macro where one of the parameters is a type i.e. `String` and use some of the typenode operators to see if `type >= SomeType`, but I get Error: undefined macro method 'Path#>='
rocx has quit [Ping timeout: 260 seconds]
renich has quit [Quit: renich]
<FromGitter> <watzon> @sam0x17 got example code?
DTZUZU2 has quit [Quit: WeeChat 2.8]
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 260 seconds]
_ht has joined #crystal-lang
Nekka has quit [Ping timeout: 258 seconds]
_ht has quit [Remote host closed the connection]
_ht has joined #crystal-lang
Nekka has joined #crystal-lang
<oprypin> sam0x17, maybe u just need `type.resolve`
Nekka has quit [Ping timeout: 272 seconds]
Nekka has joined #crystal-lang
<FromGitter> <Uzay-G> Could someone help me with some JSON problems?
<FromGitter> <Uzay-G> I have an endpoint like this:
<FromGitter> <Uzay-G> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebb9ed18c044c1914999552]
<FromGitter> <Uzay-G> And when I send the JSON object, I get the following error:
<FromGitter> <Uzay-G> `Expected Hash for #[](key : String), not String`
<FromGitter> <Uzay-G> Here is an example of the JSON that was received: ```json
<FromGitter> <Uzay-G> ```{"type":0,"content":"~pin","id":"709887503166865409"}```
<FromGitter> <Uzay-G> Am I making a mistake with the parsing?
<FromGitter> <naqvis> JSON.parse you needn't to invoke `to_json`
<FromGitter> <naqvis> parse requires String
<oprypin> @Uzay-G minimized your example. it's nice to do that https://carc.in/#/r/9270
<oprypin> and indeed it works https://carc.in/#/r/9272
<FromGitter> <Uzay-G> Oh thanks
<oprypin> yeah to_json considers it a string and turns to json `"foo".to_json == "\"foo\""`
<oprypin> probably shouldn't do that to something thats already json
<FromGitter> <Uzay-G> Hmm, when I try with that the parsing doesnt work correctly
<FromGitter> <Uzay-G> i get an error
<FromGitter> <Uzay-G> Maybe I need to format it like you did, with the `%(`?
<oprypin> no that's a way to write a string literal
<oprypin> `%(foo) == "foo"`, nothing special
<FromGitter> <Uzay-G> hmm, when i hardcode it it works
<oprypin> ok show us more
<FromGitter> <naqvis> also `%(` is convenient when your string contains quotes
<FromGitter> <naqvis> or else you would have to individually escapes those quotes
<FromGitter> <Uzay-G> yeah problem is it's an api endpoint
<FromGitter> <Uzay-G> so I can't like hardcode it
<oprypin> cool cool. so why dont you show us the error and the code
<FromGitter> <naqvis> ^
<FromGitter> <Uzay-G> that's the main part of the code
<FromGitter> <Uzay-G> but i am getting this:
<FromGitter> <Uzay-G> `Unexpected char 'y' at 1:`
<FromGitter> <Uzay-G> because the first parameter is named `type` so I guess it's misinterpreting that
<FromGitter> <Uzay-G> in the json
<FromGitter> <Uzay-G> This is when I do this: `discord_data = JSON.parse(params[:data].not_nil!)`
<oprypin> show code between receiving the html reply and this
<oprypin> http*
<FromGitter> <Uzay-G> you mean exactly what I am sending?
<FromGitter> <Uzay-G> or do you mean the endpoint
<oprypin> code that populates params[:data]
<oprypin> or just everything
<FromGitter> <Uzay-G> this is how I am sending: `curl --data "data={"type":0,"content":"~pin","id":"709887503166865409"}" -H "origin: *" http://localhost:3000/send_data`
<FromGitter> <Uzay-G> Amber handles the `params` part
<FromGitter> <Uzay-G> I'll send the controller
<oprypin> Uzay-G, ok well the curl command line is totally wrong
<FromGitter> <Uzay-G> why?
<oprypin> run this command and see for yourself: `echo curl --data "data={"type":0,"content":"~pin","id":"709887503166865409"}" -H "origin: *" http://localhost:3000/send_data`
<oprypin> (just added echo)
<FromGitter> <Uzay-G> oh yeah that must be it
<FromGitter> <Uzay-G> thanks 😅
<oprypin> also zsh syntax highlighting can help :p https://i.imgur.com/iJSoWgr.png
<oprypin> well not so much
<oprypin> anyhow use single quotes `--data 'data={"`
<FromGitter> <Uzay-G> yeah thanks a bunch!
zorp has joined #crystal-lang
Xeago has quit [Read error: Connection reset by peer]
Xeago_ has joined #crystal-lang
Xeago_ is now known as Xeago
hightower4 has joined #crystal-lang
Xeago_ has joined #crystal-lang
Xeago has quit [Ping timeout: 264 seconds]
Xeago_ is now known as Xeago
<raz> hm. it's a little depressing that `bundle` runs faster than `shards`. :p
<jhass> well git clone is comparably slow to wget + tar
<FromGitter> <llathasa-veleth> i am experimenting with my lang's syntax
<FromGitter> <llathasa-veleth> i want me some interpreter
<raz> jhass: i think it's more because it serializes the clones ;)
<jhass> it doesn't help, sure
<jhass> but even then
<raz> no biggie. just in the process of upgrading an app to rails 5 (ugh) and, well, everything is broken. but gotta say... bundler is surprisingly fast lol
<jhass> they spent a shitload of effort on performance optimizations a couple of years ago
<raz> yup yup, that's still ahead of us
<jhass> basically they calculate the dependency tree on the server and cache whole subtrees and shit
<jhass> for something like this language speed makes no real difference
<raz> yeh i dunno, i think doing the git clones in parallel would already give a huge boost. but guess that will need some changes to the dep resolution.
<jhass> it's algorithmic complexity (just take a look at how slow the SAT solver was) and IO bottlenecks (network, disk)
<jhass> you can be naive with that too, if you just spawn as many clones as possible concurrently they will compete with each other on network and disk IO
<jhass> which easily is making the total slower because the CPU and kernel have to context switch so much and you'll get higher lock contention and what not
<raz> or you could set a wise default and let the user override it. my gbit/s line and macbook won't mind doing 10+ clones in parallel
<jhass> I doubt Github will allocate you a gbit of their uplink
<jhass> so you could go as far as have a two layered worker pool, one total limit of workers and one per source
rocx has joined #crystal-lang
<raz> well, here's a little experiment. copy/paste those "Fetching https://github.com/..."; lines to a file called "/tmp/wee". then run: `cd /tmp && echo wait >>wee && chmod 700 wee && sed -i -e 's/Fetching/git clone/;s/$/ \&/' wee`
<raz> then compare `time ./wee` to `shards`
<raz> for me the diff is 3s vs 30s. :)
<FromGitter> <Uzay-G> for JSON::Any types, is there something like `as_u64`?
<FromGitter> <Uzay-G> I could only find `as_i64`
<FromGitter> <Uzay-G> is there a way to do that?
<FromGitter> <Blacksmoke16> `.as_i64.to_u64`
<FromGitter> <Blacksmoke16> nvm, seems you figured that out already
<FromGitter> <xmonader> is there an option to change the router in kemal to use something else other than radix tree?
<FromGitter> <Blacksmoke16> prob not easily
<FromGitter> <xmonader> well, i just spent a couple hours and the problem was in that router https://github.com/threebotserver/publishingtools/issues/93
<FromGitter> <Blacksmoke16> pretty sure thats just a limitation with the tree
<FromGitter> <xmonader> yes indeed, but as a user of framework I shouldn't debug your dependencies for sure
<FromGitter> <Blacksmoke16> i mean its a *limitation* not a bug
<FromGitter> <xmonader> yes, limitation in radixtree, but a bug in kemal :)
<FromGitter> <Blacksmoke16> not really, how would you fix it?
<FromGitter> <Blacksmoke16> be easier to just add some static parent key like in the example
deavmi has quit [Ping timeout: 246 seconds]
<FromGitter> <xmonader> if possible in kemal sure, well I don't have that same problems in other frameworks,even a dumb router like the one i created in a weekend would be just okay https://xmonader.github.io/nim-servy/
deavmi has joined #crystal-lang
<FromGitter> <Blacksmoke16> not really a fair comparison because if it doesnt use a radix tree it wouldnt have this issue
<FromGitter> <Blacksmoke16> is one of the cons of using a radix tree as the router
<FromGitter> <Blacksmoke16> im sure it would be doable to switch out the router for something else, but might not be a trivial endeavor, nor worth the effort given there are easy workarounds to the problem.
<FromGitter> <Blacksmoke16> plus might lose some performance, which is a key selling point of kemal
<FromGitter> <xmonader> what frustrated me is i didn't see any note about that in kemal docs and drove me crazy :(
<FromGitter> <Blacksmoke16> if anything could be a doc improvement somewhere
<travis-ci> crystal-lang/crystal#0f3f29c (master - Refactor Log::Formatter (#9211)): The build passed. https://travis-ci.org/crystal-lang/crystal/builds/686550180
travis-ci has joined #crystal-lang
travis-ci has left #crystal-lang [#crystal-lang]
<DeBot> https://github.com/crystal-lang/crystal/pull/9211 (Refactor Log::Formatter)
<travis-ci> crystal-lang/crystal#433ca8e (master - Refactor spec hooks (#9090)): The build passed. https://travis-ci.org/crystal-lang/crystal/builds/686550585
travis-ci has joined #crystal-lang
travis-ci has left #crystal-lang [#crystal-lang]
<raz> Blacksmoke16: athena needs a better readme. with examples.
<FromGitter> <Blacksmoke16> i agree
<raz> i'm looking into candidates for a little api backend
<raz> kemal being the obv baseline. but a little sugar on top wouldn't hurt. ideally automatic swagger/openapi docs etc. (but that's wishful thinking atm)
<FromGitter> <Blacksmoke16> prob wouldnt be a bad idea to add a section to the readme describing architecture/getting started example, then link out to related API docs
<raz> yup. for me athena is out simply cause it doesn't tell me what a non-trivial (or even a trivial) example would look like ¯\_()_/¯
<raz> ohhh there
<raz> that's quite hidden lol
<FromGitter> <Blacksmoke16> yea..docs are all written for their respective types/methods, but needs something to tie it all together
<raz> ohhh that looks quite cool actually
<FromGitter> <Blacksmoke16> thanks :)
deavmi has quit [Quit: Eish! Load shedding.]
<raz> let's say i have this demo and want to wrap basic auth around only two of the endpoints. is there an @[ART::Auth] or such, or an easy way to build one?
<raz> i really like the param converter / validation thing
<FromGitter> <Blacksmoke16> nothing directly build in for auth yet, but it would essentially be something like https://github.com/Blacksmoke16/athena-blog-tutorial/blob/master/src/listeners/security_listener.cr
deavmi has joined #crystal-lang
<FromGitter> <Blacksmoke16> so like, if endpoint is public, skip, otherwise run some logic to auth the given request
<raz> hm hm. that looks kinda promising. and can i then also access data from this auth-validation-thinger in the request handler?
<raz> like, when i want to know what user is authed
<raz> (or write that to the request context or such)
<FromGitter> <Blacksmoke16> > access data from this auth-validation-thinger ⏎ ⏎ hm?
<raz> ah. hmmm. && {"/user", "/login"}
<FromGitter> <Blacksmoke16> ah, yea. the concept here is that the last line in the listener sets the user within the `UserStore`
<raz> looks like that's more like a middleware
<FromGitter> <Blacksmoke16> that skips the login/register endpoints
<FromGitter> <Blacksmoke16> since they're public
<raz> hmm yea, i think what i'd essentially want to write is: @[ART::NeedsAuth]; def some_endpoint; puts request.user; end
<FromGitter> <Blacksmoke16> idea being you would have this run early in the request lifecycle, then in other places you can inject that user store to get access to the current user, like https://github.com/Blacksmoke16/athena-blog-tutorial/blob/master/src/controllers/article_controller.cr#L14
<raz> where `request.user` was injected by the auth annotation
<raz> hm ok, user_storage would also work i guess, tho i can't wrap my head around that rn :D
<FromGitter> <Blacksmoke16> > *<raz>* hmm yea, i think what i'd essentially want to write is: @[ART::NeedsAuth] ⏎ ⏎ something along these lines to handle auth is on my list, just lower on the priority
<raz> if you do it first it might align the stars in a better direction for other things, too :p
<FromGitter> <Blacksmoke16> wanted to get the serialization/validation side of things working first. plus need to do some thinking on how it should all work in the end
<raz> not just for auth, but the general pattern is useful for a million things (annotate endpoints with extra context/bits of logic they should have, basically do_before/do_after annotations)
<FromGitter> <Blacksmoke16> some of that is a bit hard since you cant read annotations at runtime
<raz> yap yap, take your time. i'll refrain from nagging you again till after dinner. :p
<FromGitter> <Blacksmoke16> so logic on what to do with/how to handle those annotations needs to be defined at compile time
<FromGitter> <Blacksmoke16> i mean i imagine you could define some annotation, and add that macro to the request listener? :shrug:
<raz> oh right. yea, i think i've been in similar spots in the past. one thing you can do (not sure if applicable) is, you can essentially "transplant" procs with a macro. i.e. if a macro takes a block and you insert it elsewhere, it runs in that elsewhere-context.
<FromGitter> <Blacksmoke16> > *<raz>* hm ok, user_storage would also work i guess, tho i can't wrap my head around that rn :⁠D ⏎ ⏎ its a feature related to the DI stuff. the container injects the same instance of the store into various types. So that after the auth request listener runs, the other objects injected elsewhere get a reference to that character
<raz> yep, i think i understand what it does (and it looks good to me!). just not sure _how_ it does it, but i don't really care anyway as long as it works :D
<FromGitter> <Blacksmoke16> `0.35.0` needs to come out already. then i could release new DI shard version, and a new athena version
<raz> that sample code looks really close to how i want to write an api server
<raz> esp. the param validation/conversion stuff
<FromGitter> <Blacksmoke16> yup, dont need boilerplate to resolve IDs to objects
<raz> takes so much boilerplate out of the endpoint code
<raz> yap
<FromGitter> <Blacksmoke16> reusable, can be documented, and tested
<raz> can even document itself (swagger/openapi generator)!
<raz> that's huge
<raz> everybody hates writing those swagger annotations manually, and they always go out of sync with the actual endpoint, etc.
<FromGitter> <Blacksmoke16> i have an open issue about it. it would be possible as a fair bit of data can be deduced from the method sig
<FromGitter> <Blacksmoke16> but some things would require either user intervention, or another annotation. like for the descriptions of stuff etc
<raz> yep, the meth sig should get you 95% there. and then the developer only has to fill in a few remaining blanks
<raz> yup, descriptions/labels and return values basically. those can not be easily inferred i guess.
<raz> but those are minor. the main headache always is to translate the basic params, data-types, validations to the god awful swagger synax
<FromGitter> <Blacksmoke16> i would know the return type, which gets you most of the way. assuming you use an object and dont just type everything as strings
<FromGitter> <Blacksmoke16> esp if you use an enum or something
<raz> well, fill in those blanks (auto-docs, proper auth story) and you're #1 api framework on crystal instantly. unless another already does that, but i haven't seen it yet :)
<FromGitter> <Blacksmoke16> think the one @j8r made does that?
<raz> ohhh which one is it?
<FromGitter> <Blacksmoke16> oh it 404s now, have to ask him
<FromGitter> <Blacksmoke16> current focus is the serialization shard, then once next crystal version releases, can do next di/athena release
<FromGitter> <xmonader> do u guys see anything wrong here? ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ because i get `can't infer the type of class variable '@@GROUPS' of TFWeb::ACLGroup` [https://gitter.im/crystal-lang/crystal?at=5ebbfdb22baa191854683cc0]
<FromGitter> <Blacksmoke16> `@@GROUPS` is prob a class var in a module, not the class
<FromGitter> <Blacksmoke16> so `@@GROUPS` in `ACLGroup` is a different one
<FromGitter> <xmonader> but how can i reference the one in the module?
<FromGitter> <Blacksmoke16> does it need to be a class var versus a const?
<FromGitter> <xmonader> don't think so ^_^
<FromGitter> <Blacksmoke16> id use a const then
<FromGitter> <Blacksmoke16> or define a getter for the class var
<FromGitter> <Blacksmoke16> or define the class var within the class
<FromGitter> <xmonader> thank you ^_^
Human_G33k has joined #crystal-lang
HumanGeek has quit [Ping timeout: 246 seconds]
<FromGitter> <j8r> @Blacksmoke16 raz the framework was moved to https://github.com/grip-framework/gripen
<FromGitter> <Blacksmoke16> ah, that would do it
<FromGitter> <j8r> I didn't communicate on it, sorry
<FromGitter> <Blacksmoke16> might want to update your forum post
<FromGitter> <j8r> Yep
<FromGitter> <Blacksmoke16> if you havent
<FromGitter> <j8r> I was waiting to finalize grip migration, but things has taken time
<FromGitter> <j8r> Will do, thanks
<FromGitter> <Blacksmoke16> np
olbat has joined #crystal-lang
olbat has quit [Max SendQ exceeded]
olbat has joined #crystal-lang
<raz> j8r: hmm, looks like params are not typed and prob not validated either tho?
<raz> or actually. the bullets say they are. hmm. the sample code confuses me
<raz> it seems to declare a required param called "optional" (?!?), but doesn't mention a type
<raz> ohhh
* raz found EXAMPLES.MD
hightower4 has quit [Read error: Connection reset by peer]
<raz> hmm, so this is gonna become the new router for grip?
* raz feels like he's looking at two awesome pieces that are not connected yet
<FromGitter> <j8r> raz you're right
<FromGitter> <j8r> We would like to make it the "grip v2" with @grkek
<raz> ohsom
<raz> finish it! </mortal-kombat-voice>
<FromGitter> <j8r> the type is mainly to add documentation. I tried to make it more type safe, but we can do `params[WhatEverOptionalQueryType]`
<FromGitter> <j8r> and also for custom casting
<FromGitter> <j8r> instead of dealing with strings
<raz> yea it looks pretty perfect from what i can gather from the docs. not even an annotation, just a simple method def that creates endpoint, validation and docs (and then perhaps annotations/DSL to refine it)
<raz> that's how i want to write apis. 3 endpoints = 3 lines. plus the method bodies of course and a minimum of glue. but none of the boilerplate that is always the main time sink.
<FromGitter> <Blacksmoke16> :0 do i have some competition now? :p
<raz> Blacksmoke16: you can still be #2 api framework :P
<FromGitter> <Blacksmoke16> xD
<raz> j/k ;)
<raz> some will surely prefer yours. for me, gripen is more crystalline tho. yours is more java'esque (but still tolerable from what i've seen).
<FromGitter> <Blacksmoke16> you can also do like ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebc2376f25ee4780694dd1d]
<FromGitter> <Blacksmoke16> versus def + ann
<raz> Blacksmoke16: see, that's why you need a proper README. how is anyone supposed to discover that :D
<FromGitter> <watzon> Docasaurus is waiting
<FromGitter> <Blacksmoke16> it was in the controller docs! :P
<FromGitter> <watzon> I really wish you could do something like this without including the module in each class
<FromGitter> <watzon> https://carc.in/#/r/92cz
<FromGitter> <watzon> Interfaces would be a wonderful thing
<raz> Blacksmoke16: possibly. but when ppl search for an api thing and glance over the github pages of gripen and athena, guess which one they're gonna give the first shot
<raz> competition is steep :D
<raz> those github stars ain't come free
* raz snaps the OSS whip on the volunteers
<FromGitter> <Blacksmoke16> i guess so :p
<FromGitter> <Blacksmoke16> the module meaning `JSON::Serializable`?
<FromGitter> <j8r> raz yeah, need to generate gh-pages - it was done before
<raz> j8r: you can have github serve up /docs automatically, then you won't need to think about it anymore (mostly, you still have to generate and commit them of course ;))
<FromGitter> <Blacksmoke16> GH action to make it deploy them on push to master
<raz> hmm yea, i always serve mine directly from master
<FromGitter> <Blacksmoke16> mhm
<raz> that extra branch only confuses me most of the time
<raz> but tastes differ :)
<FromGitter> <Blacksmoke16> can just ignore it really, its essentially just holds master docs, w/o needing to commit your `./docs` dir
<raz> true
<FromGitter> <Blacksmoke16> prob will need to revisit it now that you will be able to have docs for diff versions
<FromGitter> <Blacksmoke16> versus it always being master
<raz> oh great, so that google can always send me to the wrong version like it does for crystal :p
<raz> actually, that's a tidbit you both could consider for your api-frameworks (as the last thing perhaps): endpoint versioning
<raz> everyone forgets to think about that. having it in the framework could be a nice touch (although not a hugely important one imho)
<raz> basically just a "v" param on each endpoint that appends `.v3` to the path
<raz> or maybe sth fancier, it's a beautiful bikeshed (that's why i'd suggest to think about it last, when everything else is done :P)
<FromGitter> <j8r> @Blacksmoke16 I'll copy your GH worflow, maybe
<FromGitter> <Blacksmoke16> would you expect the param to be provided as an argument to the action, or just used for routing?
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <j8r> Just not a fan to give a token to third party repo
<FromGitter> <Blacksmoke16> theres a bug with actions, otherwise you could use the built in actions token
<FromGitter> <Blacksmoke16> versus needing to create one
<raz> Blacksmoke16: good point. actually i was thinking wrong. i guess better might be along the lines of `@[ART::Get("/foo/:id", v: 3)]` which translates to `/foo.v3/:id`
<FromGitter> <Blacksmoke16> id think `/v3/foo/:id` would be better no?
<raz> no, that's a mistake (and a widely popular one)
<raz> you almost always want per-endpoint versioning, unless you can really do consistent full api updates
<FromGitter> <Blacksmoke16> thats what that is tho? you could still have like `/v1/bar/`
<raz> yes, but `/v3` implies that all endpoints exist under that prefix. (i.e. that all endpoints have a /v1, /v2 an /v3). suffixing makes it clearer that the version belongs to the endpoint (and is not a folder hat contains many endpoints).
<raz> it's a subtle difference but bleeds into many areas, like the sorting in swagger etc. if you prefix the version you get a wild mix. whereas if you suffix, you get all versions of a given endpoint grouped together.
<FromGitter> <Blacksmoke16> i dunno, normally an API has a defined set of endpoints
<FromGitter> <j8r> IMO this things should be up to the user
<raz> well, as always, it depends. ;) but in practice i found suffixing much more useful in most cases. yes, ideally it would be configurable.
<FromGitter> <Blacksmoke16> endpoint is `/character/{character_id}/`, but then is a version for each, so its `BASE + version + path`
<raz> in fact _ideally_ you'd probably want suffix versions by default. and then be able to release groups of endpoints under a prefix version. (that's where the bikeshed starts turning into a palace with a segway parking lot)
<raz> Blacksmoke16: well the main issue i'm getting at is, imagine you're looking at the swagger docs for an api with 100 endpoints. all of them only have a v1, only one also has a v2. with prefix-versioning that v2 endpoint will be sorted to the very end. it basically presents itself like there are two "api versions", whereas the 2nd one only has 1 endpoint. ;)
<raz> so in reality what you'd want for a public api in that model, would be to serve a copy of all v1 endpoints that are missing in v2 also under v2. for consistency.
<raz> so users can choose "an api version" and use all endpoints in it. this model is good for public apis.
<raz> however for internal SOA apis that are in constant flux, the per-endpoint suffix versioning is usually preferable.
<FromGitter> <Blacksmoke16> i think github uses `Accept` header for versioning as well
<FromGitter> <Blacksmoke16> versus the paht
<raz> ideally both should ofc be supported. i was just suggesting the suffix-one first cause... it's all a huge bikeshed and takes ages to describe alone ;)
<raz> yep, _response_ versioning, accept & co then also become interesting
<FromGitter> <Blacksmoke16> serializer i been working on has support for that aspect
* raz regrets opening that can of worms now
<raz> that was only meant as a "btw" thing :D
<FromGitter> <Blacksmoke16> https://blacksmoke16.github.io/CrSerializer/CrSerializer/ExclusionStrategies/Version.html (dont have docs on new stuff yet as its WIP, but concept is the same)
<raz> ohhh, yes, that looks interesting
<FromGitter> <Blacksmoke16> xD
<raz> that's the thing they really screwed up with protobuf
<raz> but it's also super hard to figure out a one-size-fits-alls
<FromGitter> <Blacksmoke16> for sure
<raz> what we do in pbuf is the same as with the api versions. we just have FooReqV1 an FooReplyV1 (e.g. always a pair of messages, always versioned)
<raz> works fine overall, but still leaves a bunch to be desired
<raz> e.g. in a queue system, during deploys, older consumers may see FooReplyV2's without knowing them yet - and can only bounce them until an updated consumer takes them
<raz> anyway, that bikeshed is an airport now. i'll go have my dinner :D
<FromGitter> <Blacksmoke16> haha, enjoy
rocx has quit [Ping timeout: 260 seconds]
rocx has joined #crystal-lang
<FromGitter> <sam0x17> @straight-shoota could you give me some quick info on how the `include_path` option works in your `sass.cr` shard? Is this like a directory, a glob, or what?
<straight-shoota> > Colon-separated list of paths where @import directive looks for include files (semicolon-separated on Windows).
<FromGitter> <sam0x17> @straight-shoota so if I just want scss files to be able to arbitrairly import any path within my `public` directory (where all scss files live in arbitrary subdirectories), do I just need to add `public` or do I need to add every possible directory within `public`
<straight-shoota> I'm not entirely sure how it works, the option is just passed forward to libsass. But AFAIK if you set libraries_path="./public" you can import ./public/foo/bar as `import "foo/bar"`
<straight-shoota> if you want to import it as `import "bar"` you need to add ./public/foo to include_path
<FromGitter> <sam0x17> ok perfect that's what I need thx so much
<straight-shoota> the libsass documentation isn't super extensive unfortunately
<FromGitter> <sam0x17> that `libraries_path` thing is that same as `include_path`?
<FromGitter> <sam0x17> or did you mean `include_path`?
<straight-shoota> yeah, I meant include_path
<FromGitter> <sam0x17> kk
<travis-ci> crystal-lang/crystal#32a6282 (master - Followup of #9134. Missing swap of arguments (#9289)): The build passed. https://travis-ci.org/crystal-lang/crystal/builds/686675128
travis-ci has joined #crystal-lang
travis-ci has left #crystal-lang [#crystal-lang]
<DeBot> https://github.com/crystal-lang/crystal/pull/9134 (Refactor to standardize on first argument for methods receiving `IO`) | https://github.com/crystal-lang/crystal/pull/9289 (Followup of #9134. Missing swap of arguments)
DTZUZU has joined #crystal-lang
<FromGitter> <watzon> Here's my interface proposal if anyone wants to take a gander https://forum.crystal-lang.org/t/proposal-interfaces-for-more-generic-code/2103
<FromGitter> <Blacksmoke16> 😮
<FromGitter> <watzon> I'm not use to writing proposals, but this is something I've felt Crystal has needed for years
<FromGitter> <Blacksmoke16> idt id go with `interface` as the keyword tho
<FromGitter> <Blacksmoke16> but i get the idea
<FromGitter> <watzon> I mainly went with `interface` just because it's well known from the Java/C#/Typescript worlds. Something more appropriate for Crystal would be welcome.
<FromGitter> <Blacksmoke16> yea mainly since its not really an interface
<FromGitter> <Blacksmoke16> normally an interface implies you would do like
<FromGitter> <Blacksmoke16> ```class Foo implements MyInterface ⏎ ``` [https://gitter.im/crystal-lang/crystal?at=5ebc39253c51a11913f9e671]
<FromGitter> <watzon> Yeah that's true
<FromGitter> <watzon> Which is more or less what modules are
<FromGitter> <watzon> I can see where your previous confusion came in
<FromGitter> <Blacksmoke16> right, i have thought about something like
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebc3950faa128031ccd12c2]
<FromGitter> <Blacksmoke16> or even `module Foo`
<FromGitter> <watzon> I just don't know what a more appropriate word would be, but I guess that's something that can be hashed out in the comments
<FromGitter> <Blacksmoke16> for sure
<FromGitter> <watzon> As long as we have something like this, idgaf what it's called 😄
<FromGitter> <Blacksmoke16> ^ that wouldnt be that bad, same idea as a module but maybe could make the method `abstract` behind the scenes, and disallow defining actual methods in it
<FromGitter> <Blacksmoke16> methods/other types
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebc39c9f8ac217807456b62]
<FromGitter> <watzon> The only problem is you still have to monkeypatch every type you want it to apply to
<jhass> isn't it a trait?
<FromGitter> <watzon> Trait and interface have basically the same connotation
<FromGitter> <watzon> In that they have to be explicitly implemented
<FromGitter> <Blacksmoke16> i think you could do something fancy here, moment
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/92ea
<FromGitter> <Blacksmoke16> meh, kinda
<FromGitter> <watzon> It's the right idea haha
<FromGitter> <Blacksmoke16> heh, allow `alias` to take a block
<FromGitter> <Blacksmoke16> that filters `Object.all_subclasses` via macro method logic
<jhass> btw big unions are slow (compile and runtime wise)
<jhass> I think that's my biggest problem with the idea
<FromGitter> <Blacksmoke16> esp if you do something common like `to_s`
<FromGitter> <watzon> The thing is, crystal already kind of has support for this kind of thing built in. When you don't explicitly provide a type for an argument the compiler is able to determine automagically what they type could possibly be based on the methods you call on it.
<FromGitter> <watzon> The problem is that it can only go so far
<jhass> yeah
<FromGitter> <watzon> And is terrible for documentation
<jhass> so embrace that
<jhass> show duck typing some love
<FromGitter> <watzon> Duck typing can *duck* itself haha
<jhass> I actually despise the current trend in the community to so strictly type everything
<FromGitter> <Blacksmoke16> :0
<FromGitter> <watzon> That's the thing, I love explicitly declaring types. But I'm also big on documentation.
<jhass> Crystal's initial attraction and traction came from exactly not requiring this
<jhass> it's a little big like giving up its spirit and it makes me a little sad
<jhass> *little bit
<FromGitter> <watzon> It still wouldn't require it, but it does make things a lot easier in many cases
<FromGitter> <Blacksmoke16> granted when i use type restrictions i mean like `value : Number`
<FromGitter> <Blacksmoke16> or `str : String`
<FromGitter> <watzon> When you explicitly type an argument you get an error right away if something you're passing in to that argument isn't the right type
<FromGitter> <Blacksmoke16> wouldnt really get any benefit *not* including those?
<jhass> duck typing is to do #to_s in the method body instead
<jhass> and suddenly I can pass HTMLSafeString AND use composition over inheritance
<FromGitter> <Blacksmoke16> depends on the context, are deff times when you just want a string version of an obj, dont need a restriction there
<FromGitter> <watzon> For sure
<FromGitter> <Blacksmoke16> if anything type it as `value : _`
<jhass> that's just value, why the noise
<FromGitter> <Blacksmoke16> imo it makes it clear that it should accept anything, versus just not having a restriction
<FromGitter> <Blacksmoke16> but someone *could* come along, and add `: String` and now you're duck typing is broken
<jhass> not having the restriction is saying I accept anything (that reasonably quacks like anything that makes contextually sense, not passing any object)
<FromGitter> <Blacksmoke16> right, and `: _` just makes that intent more clear
<jhass> Ruby and Python built entire gigantic ecosystems on this principle, Crystal added compile time validation to it and that made it awesome
<FromGitter> <watzon> While you *can* avoid the restriction in many cases, it's much less explicit. And sometimes explicit is what you want. Especially when it comes to generating documentation.
<jhass> this is exactly what I'm talking about, if I want to declare my intent over and over again I write Java
<jhass> Crystal is becoming a bit to java with all these proposals
<jhass> I mean I never got the need for abstract types really...
<FromGitter> <watzon> I don't think so. It's not like they're required.
<jhass> let alone abstract defs
<FromGitter> <Blacksmoke16> mainly for documentation
<jhass> it's not about what the compiler forces me to do, I'm talking about community spirit
<FromGitter> <watzon> Abstracts help for documentation and they help the compiler know that a specific type is never going to be instantiated.
<jhass> I never missed any of this in Ruby (documentation)
<FromGitter> <Blacksmoke16> cant miss what you never had 😉 /s
<jhass> my day job currently is Java
<rocx> lucky...
<FromGitter> <watzon> Ruby has better documentation generation. If you want to make sure people know what type a property is supposed to be you still have to specify it explicitly.
<FromGitter> <watzon> ```@param contents [String, #read] the contents to reverse```
<jhass> https://api.rubyonrails.org/ give me any parameter docs here that specify the type, then tell me the time it took you to find
<FromGitter> <watzon> Rails API docs are terrible
<jhass> yet good enough for billions of LOC written in rails
<jhass> and I actually don't agree. They just don't attempt to be the guides.
<FromGitter> <watzon> https://api.rubyonrails.org/
<FromGitter> <watzon> Ahh damn it
<FromGitter> <watzon> Tell me, what is value and what are the possible `options`?
<jhass> the one possible option is class:
<FromGitter> <watzon> `:class` is listed as an option, but that had to be provided explicitly
<jhass> name and value are obviously string ducks in this case
<FromGitter> <watzon> Often time options get missed
<jhass> for value I don't even need to care, it'll do the right thing in 98%
deavmi has quit [Quit: Eish! Load shedding.]
<jhass> "it's good for documentation" is the "everything should be an interface" Java mantra all over again
<jhass> rocx: even luckier: Android. Best case is that I'm the sole dev on the codebase for now, so I don't have to fight with anybody over any design principles or whatever
deavmi has joined #crystal-lang
<jhass> but yeah, if you guys know something cool in Berlin, I'm open to change
<FromGitter> <Blacksmoke16> ayy berlin, nice city
<FromGitter> <Blacksmoke16> having docs be tied to type restrictions is nice, its deff possible to be *too* strict tho
<FromGitter> <Blacksmoke16> in those restrictions
<FromGitter> <kinxer> @watzon I'm confused about how you're emphasizing explicitness while creating an "interface" proposal that is more or less completely implicit, replicating the compiler's existing ability to check if a class would have the method that's being called. What is gained, anyway? Better error messages? ⏎ ⏎ Okay, I see what you mean about documentation. I think maybe a better way than introducing something like an
<FromGitter> ... interface (though I agree that that word is not accurate for this proposal) would be some way of specifying a type implementing a particular method signature. That starts to skew more toward Rust or C++ syntax, though, rather than Java (which isn't really desirable either).
<FromGitter> <watzon> No one said that everything should be an interface, but there are times when having an interface makes things much easier. For example: ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebc40cf3f5b010319480839]
<FromGitter> <watzon> Crap not done, just a sec
<FromGitter> <Blacksmoke16> fwiw you can do `Number::Primitive`
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/master/Number/Primitive.html gets you most of that
<FromGitter> <watzon> Hmm actually didn't know that existed
<FromGitter> <watzon> Still illustrating a point here. Sec.
<FromGitter> <Blacksmoke16> same thing for `Int` and `FLoat`
<FromGitter> <Blacksmoke16> :p
<FromGitter> <kinxer> Also, I agree with @jhass that allowing duck typing is a necessary part of Crystal and something that allows it to be so versatile. That said, I'd say that explicitness is pretty useful when you're defining a library API. I've gone back to Python libraries in the past couple years (after not using it regularly for a couple years but remembering it fondly), and it's very difficult to tell what things *are*.
DTZUZU has quit [Ping timeout: 256 seconds]
<jhass> we're discussing every sharp corner in the current type system with feature additions, or I'd call it bloat, to it. Rather than refining the existing semantics and fixing the real implementation bugs we argue to make it more complex, making it seemingly impossible to ever catch up on the former. I think we should talk more about cultural solutions, patterns and idioms, than technical ones.
<jhass> Show some faith. The recent io argument is a good example. It spawned a possible technical improvment to string interpolation by a purely cutlural policy change
DTZUZU has joined #crystal-lang
<FromGitter> <watzon> Yes there are ways around it, but not pretty ones
<jhass> you cannot optimize for every possible usecase and we should stop trying.
<FromGitter> <watzon> The point is that you can make situations like this much easier by leveraging functionality that's already built into the compiler, but not available to us as something that can be used explicitly. All you'd really need are 2 interfaces in the above example. One that defines `#to_io` for the numbers, and one that defines `#to_slice` for `String`, `Slice`, and `IO::Memory`. Then you handle the `BigInt` explicitly
<FromGitter> ... and you're good. Makes for much more readable code, avoids a massive alias, and allows for better documentation.
<jhass> https://p.jhass.eu/7y.cr caller passes me something that doesn't confirm to the interface? their problem
<jhass> and Crystal will tell them at compile time! awesome!
<jhass> they make up a type I could never imagine that confirms to the interface? It just works
<jhass> just define the right methods, it'll work
<FromGitter> <watzon> Generics are error prone. Try creating an ivar with `Foo` as the type. Doesn't work unless you explicitly define `T`
<yxhuvud> It is not possible to define to_io for numbers. It needs to know byte order etc. Same is true for anything that is to be consumed by anything else.
<raz> watzon, i think jhass has the better argument there. feature bloat is a slippery slope. it'd be nice to see some real world use-case to back your side. (not snippets specifically crafted to create a problem)
<raz> ruby is having that bloat problem atm. they add all kinds of crap that nobody needs or asked for, and people like DHH rage-quit over it
<raz> cause even people who don't use a given feature will still be exposed to it in libraries, their tools (editor, linters etc.) need to keep up, and so on
<FromGitter> <watzon> yxhuvud not correct. `#to_io` is exactly what `IO::#write_bytes` uses to convert a number to a slice and push it into the IO. It's defined as `Int#to_io(io : IO, format : IO::ByteFormat)`
<FromGitter> <watzon> So it does exist already
<raz> oh, there seems to be a bug actually
<raz> this shouldn't exist i think?
<FromGitter> <watzon> raz: I guess I just don't really believe in language bloat to a certain degree. If a feature could be helpful and is not something you could implement yourself in code (i.e. it requires a change to the compiler) I see no reason not to add it. Specifically when the compiler already has most of the functionality it would need to make that thing work. I understand feeling like it's "just one more thing to learn",
<FromGitter> ... but I don't see that as a reason to just push away new ideas.
<FromGitter> <watzon> I didn't realize `SystemEndian` was an alias. According to the Crystal philosophy of not aliasing things unless absolutely necessary I don't see why it exists.
<FromGitter> <kinxer> I believe `SystemEndian` is meant to contrast with https://crystal-lang.org/api/0.34.0/IO/ByteFormat/NetworkEndian.html.
<raz> watzon: no i mean, crystal should not expose the SystemEndian. afaik go-lang doesn't because it is just a bug waiting to happen (i.e. you never want to use SystemEndian for anything)
<raz> h
travis-ci has left #crystal-lang [#crystal-lang]
travis-ci has joined #crystal-lang
<travis-ci> crystal-lang/crystal#2898564 (master - Refactor Docs::Generator source link generation (#9119)): The build passed. https://travis-ci.org/crystal-lang/crystal/builds/686726571
<DeBot> https://github.com/crystal-lang/crystal/pull/9119 (Refactor Docs::Generator source link generation)
<raz> oh!
<FromGitter> <watzon> Idk why it would be a bug waiting to happen when it's just an alias
<raz> systemendian is just an alias for little
<FromGitter> <watzon> So it NetworkEndian
<raz> :confusedparrot:
<FromGitter> <watzon> Yeah
<raz> n/m, then my vocabulary might just be incomplete. i thought system = the local cpu's endian
<oprypin> raz, no yeah it is
<raz> re: no reason not to add it. i think you have that backwards. features need to justify their existence (and it has to be a good justification). there is a maintenance cost to every feature.
<oprypin> watzon, the point is, on some other system it would alias to bigendian
<raz> oprypin: ha, then i'm right!
* raz victory dance
<FromGitter> <watzon> I would've thought, but in the code there's no macro wrapping it. It's just a straight alias.
<FromGitter> <watzon> Is it just for future proofing?
<oprypin> watzon, yea
<oprypin> one could add a macro {% if false %} lol
<FromGitter> <watzon> Ahh ok. I figured that might be it. You just don't see a lot of future proofing.
<FromGitter> <watzon> On what type of system would `SystemEndian` be `BigEndian`?
<raz> Solely big-endian architectures include the IBM z/Architecture, Freescale ColdFire (which is Motorola 68000 series-based), Atmel AVR32, and OpenRISC. The IBM AIX and Oracle Solaris operating systems on bi-endian Power ISA and SPARC run in big-endian mode; some distributions of Linux on Power have moved to little-endian mode.
<raz> ^ wikipedia
<raz> i don't think you see that in the wild much anymore
<FromGitter> <watzon> Hmm interesting. Explains why the macro hasn't been added.
<raz> watzon: btw, one example for how problematic feature bloat can be: symbols. it was just a tiny mistake very early on, but will continue to give everyone headache till the end of :time.
<FromGitter> <watzon> I don't think symbols are that big of a deal really. They do serve a purpose. More so in Ruby than in Crystal, but a purpose nonetheless.
<raz> no.
<raz> or what would that purpose be?
<FromGitter> <watzon> In Ruby the purpose is to avoid unnecessary string allocations because Symbols always point to the same location in memory. I think it's the same thing in Crystal, but in Ruby unnecessary allocations take a much heavier toll.
hightower4 has joined #crystal-lang
<FromGitter> <watzon> Looks like it's not the same case in Crystal, which is a missed opportunity imo
<FromGitter> <watzon> https://carc.in/#/r/92fz
_ht has quit [Remote host closed the connection]
<raz> yes, i tried to stitch together their history and it looks like ruby just made a design mistake by not making them string-equivalent. there was a discussion to remove them or fix that in 1.9 https://bugs.ruby-lang.org/issues/5964 - but that was ofc far too late, a million gems would break.
<raz> afaik they originally come from smalltalk, and there they inherit from string
<raz> (not 100% sure if that is accurate tho, i haven't found many good sources on their lineage)
<FromGitter> <watzon> I can see why they would come from smalltalk. Lisp languages love that syntax.
<raz> yea, i just don't see what purpose they serve in crystal.
<raz> other than giving me headache every more often than i like :p
<FromGitter> <watzon> I use to have a book on the Ruby compiler and how various things are implemented in C and just remember that identical symbols share the same memory, while strings don't.
<raz> yup, but i _think_ that shouldn't prevent them from being treated as regular strings everywhere
<raz> :foo == "foo"
<FromGitter> <watzon> If Crystal is going to keep them I think they should do the same thing ruby does. In assembly they should all just be global pointers to the same small chunk of memory.
<FromGitter> <kinxer> I've seen them used more often in places where I'd expect an enum, in which case the solution is simple (use an enum).
<FromGitter> <watzon> And it would be nice if they could be used as strings too
<FromGitter> <watzon> Yeah Symbols can be auto cast to enums too, which is nice
<FromGitter> <watzon> Doesn't always work as one might expect, but that just needs to be fixed in the compiler
<raz> yup. i can't think of a single case where the distinction had ever been useful to me. it only ever causes problems ("does this thing use strings or symbols for its hash keys", "ah ok, and this other thing does it the other way round" "great now i have to `to_s` in exactly the right places")
<raz> i may be missing an important reason why it has to be that way. but until someone explains it to me i'll continue to hate on them :P
<FromGitter> <Blacksmoke16> im in favor of removing symbols as actual things, but keep it specific for enum casting
<FromGitter> <watzon> Same
<raz> if they actually get removed i'll buy the dev who does it a bottle of champaigne
<FromGitter> <Blacksmoke16> doing it before `1.0.0` would be best case...
<raz> this one, to be precise
<FromGitter> <watzon> Lmao sounds nice
<raz> yup, i think crystal is still small enough to allow for such a change (and i imagine if we continue to allow :foo to be used interchangably with "foo" then it might not even break much)
<FromGitter> <sam0x17> what is the type of `String.class`?
<FromGitter> <sam0x17> actually let me rephrase -- I need to have an `Array(Class)` but that can't be used generically
<FromGitter> <sam0x17> workarounds?
<FromGitter> <Blacksmoke16> array of what class?
<FromGitter> <Blacksmoke16> try `Array(Class.class)`? or
<FromGitter> <watzon> Can you do that? I don't think you can.
<FromGitter> <watzon> Class can't be used as a type, and I don't think `Class.class` can either.
<FromGitter> <sam0x17> `[Int32, String]` is an `Array(Int32.class | String.class)` FYI
<FromGitter> <aleandros> Hi! I’m new to Crystal but I had a lot of fun creating this personal project (a CLI tool for comparing JSON/YAML files) https://github.com/aleandros/tdiff . It’s still super early in the development phase but if any of you have time to make recommendations regarding code style, crystal idioms, etc. I would really really appreciate it. Thanks!
<FromGitter> <sam0x17> @watzon I've tried a number of times to hack my way into accessing the symbol table to make `"asdf".to_sym` work in the cases where `asdf` is a valid symbol from compile time
<FromGitter> <watzon> No it's fine haha. Taking a look now.
<FromGitter> <sam0x17> but I'm not knowledgeable enough about the compiler to do it lol
<FromGitter> <watzon> @sam0x17 interesting
<FromGitter> <sam0x17> like even if it just throws a runtime error if it isn't in the symbol table, that would be great for me
<FromGitter> <sam0x17> but then there's this question of "what to do if it isn't in the symbol table" which leads to my suggestions I posted in my reply
<FromGitter> <sam0x17> in general, it's either "throw a runtime error", "add to the symbol table at runtime by having it live on the heap or having an auxillary symbol table on the heap" or "do some kind of weird hybrid storage union where it's either a symbol id or a String depending on presence in the compile-time symbol table"
<FromGitter> <watzon> Personally this is one of those cases where I'm onboard with just removing the type entirely. It would require some changes to code, but nothing overly drastic.
<FromGitter> <sam0x17> I think 2 is the cleanest and would make people's general usage of this very efficient
<FromGitter> <watzon> The second option is the cleanest for existing code, but would be very messy compiler side
<FromGitter> <sam0x17> symbols are sort of inherently part of the fabric of a lot of APIs in terms of a nice clean token thingy
<FromGitter> <sam0x17> well I'm not sure how things are organized, but might it be possible to simply modify whatever method that looks up a symbol ID to also check in an auxillary heap-allocated table?
<FromGitter> <watzon> Right, but there's no reason they couldn't be replaced with Strings. I do like the symbol syntax for keys over using a String, and if it was easier to do option 2 compiler side I'd be all for doing that. But I would rather have a slightly less pretty syntax than make the compiler harder to maintain.
<FromGitter> <watzon> If they can figure out how to do option 2 and not make it messy in the compiler that would be awesome
<FromGitter> <sam0x17> ultimately I'd also upvote `:token` is shorthand for `"token"` and change Symbol to be an alias for String
<FromGitter> <sam0x17> but I like the idea of these things being given globally unique ids and being represented in a compact way
<FromGitter> <watzon> In Ruby I believe Symbol actually inherits from String
<FromGitter> <sam0x17> yeah they are literally strings
<FromGitter> <watzon> So if they could manage to do that it could fix issues
<FromGitter> <sam0x17> as of some version a few years ago
<FromGitter> <watzon> They're strings with a different memory layout
<hightower4> Hey quick question re. llvm and clang++... is there a way to discover if I need -fPIC as argument during compilation? I am looking into all the output from clang/llvm-config commands which give insight into flags (like --cxxflags, --ldflags etc.) and nowhere do I see -fPIC. So what other trick can I use to detect the need for it?
<FromGitter> <watzon> If they do keep them, and make them inherit from String, it would be nice if they could also share the same memory like they do in Ruby
<FromGitter> <watzon> I feel like @oprypin would be the one to ask hightower4
<FromGitter> <sam0x17> yeah, I forget how Ruby did it but I wouldn't be surprised if it's basically a big heap allocated hash table of all the symbol names
<FromGitter> <watzon> He strikes me as someone that knows clang
<hightower4> great, thanks for @-ing him
<FromGitter> <watzon> @sam0x17 I'm pretty sure it is
<FromGitter> <watzon> And that does provide a benefit over using standard strings
<FromGitter> <sam0x17> totally -- I vote that! lol
<FromGitter> <watzon> One way or another, it needs to be done before v1.0
<FromGitter> <watzon> Otherwise it's going to be waiting for 2.0
<FromGitter> <sam0x17> but yeah, on a general level, Symbols have stuck around because they look nice in code so they get used in tons of APIs
<FromGitter> <watzon> Yeah that's the main reason they're nice
<FromGitter> <sam0x17> and I'd have like a party if "something".to_sym suddenly worked lol
<hightower4> #to_sym would be nice... basically the opposite of that idea to do away with symbols in crystal :)
<FromGitter> <watzon> If the memory layout was handled in the same way as with Ruby it could work. If handled in the more efficient way, where at compile time the symbols become global variables pointing to a small memory stack, it would only work if the string you're using `to_sym` on is compile time known.
<FromGitter> <sam0x17> which I'd also be OK with
<FromGitter> <sam0x17> nothing existing would break from something like that
<FromGitter> <watzon> True, and they'd give a pretty nice performance boost
<FromGitter> <sam0x17> right
<FromGitter> <watzon> Right now you won't see a huge increase over using a String
<straight-shoota> sorry guys, but something as substantial like symbols is not going to change before 1.0
<FromGitter> <watzon> Gues it would have to wait for 2.0 then
<straight-shoota> Yeah. If at all.
<straight-shoota> I'd very much prefer to remove them as a data type to make more use of symbol literals for enums :-)
<straight-shoota> But some people really like symbols as ad-hoc singletons. That includes core developers. So it's going to need a lot of convincing
<FromGitter> <watzon> Same tbh, just because it would lessen confusion and simplify the compiler
<FromGitter> <watzon> I do like the syntax though, so I'm torn
<FromGitter> <sam0x17> there is probably some version of this that makes people who like the syntax happy but also has some sort of auto-equivalence with enums --- btw enums would be less painful if you didn't have to qualify them, like if the compile-time type of a LHS is a particular enum, I should be able to write `Bar` rather than `Foo::Bar` (or is that already a thing?)
<FromGitter> <sam0x17> *RHS
<FromGitter> <sam0x17> .
<FromGitter> <sam0x17> I'm picturing like `v : Foo = Bar` where `Foo` is an enum with `Bar` as a choice
<FromGitter> <watzon> I wouldn't be opposed to that. They could conflict with constants, in which case a constant should always take precedence
<FromGitter> <watzon> Or if they conflict it should just refuse to compile and require a fully qualified name
<FromGitter> <sam0x17> yeah I'd be fine with the compiler error
<FromGitter> <sam0x17> if that shorthand was working I'd actually use enums
<FromGitter> <sam0x17> I know it's a thing in other languages but I forget which
<FromGitter> <sam0x17> as long as the compiler error is like `Bar is ambiguous as it could refer to the enum value Foo::Biz::Bar or the constant Foo::Bar` but still allows `Foo::Biz::Bar` and `Foo::Bar` to co-exist without errors otherwise
<FromGitter> <watzon> Yeah that would be nice
<FromGitter> <watzon> @jwaldrip had an idea for crystalshards. Being able to sort search results would be nice sometimes. Like sorting by latest updated.
<FromGitter> <sam0x17> reminds me of some rust errors that are pretty informative
<FromGitter> <watzon> Yeah the rust compiler still has some of the best errors
<FromGitter> <Blacksmoke16> Isn't that the point of autocasting symbols to enums
<FromGitter> <Blacksmoke16> Can use the symbol versus full name of the enum
<FromGitter> <sam0x17> I think? I'd still like to see what that would look like
<FromGitter> <sam0x17> related: https://github.com/rust-lang/rust/pull/70645
<FromGitter> <Blacksmoke16> `@ var : Foo = :bar`
<FromGitter> <sam0x17> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebc7155f8ac21780745febb]
<FromGitter> <Blacksmoke16> all of the above?
<FromGitter> <sam0x17> that would be nice with a little automatic downcase thrown in
<FromGitter> <Blacksmoke16> i mean its already a thing
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/92gd
<FromGitter> <Blacksmoke16> that was my point
<FromGitter> <sam0x17> ohh
<FromGitter> <sam0x17> I didnt realize that was already in
<FromGitter> <watzon> Wait it is?
<FromGitter> <Blacksmoke16> mhm
<FromGitter> <sam0x17> woahhh
<FromGitter> <watzon> I didn't know that either
<FromGitter> <Blacksmoke16> i mean yea?
<FromGitter> <sam0x17> yeah it's all talk until I see it in a library
<FromGitter> <sam0x17> lol
<FromGitter> <watzon> Oh wait nvm
<FromGitter> <watzon> I see the type has been added
zorp has quit [Ping timeout: 264 seconds]
<FromGitter> <sam0x17> oh just noticed `[]=` isnt defined for `JSON::Any` -- is there no way to modify a `JSON::Any` once it's been created?
<FromGitter> <Blacksmoke16> Create another probably
<FromGitter> <sam0x17> /cry
<FromGitter> <sam0x17> :P https://play.crystal-lang.org/#/r/92gp
<FromGitter> <Blacksmoke16> Oh boy
<FromGitter> <sam0x17> lol
zorp has joined #crystal-lang
<straight-shoota> @sam0x17 what's wrong with `json.as_h["prop"] = JSON::Any.new(30)`. If you want multiple assigns, to_h is only needed once.
early has quit [Quit: Leaving]
<FromGitter> <Blacksmoke16> oh its beautiful
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebc87a9852efc0adad85225]
<FromGitter> <Blacksmoke16> allow doing a `PUT` request like:
<FromGitter> <Blacksmoke16> ```{ ⏎ "id": 1, ⏎ "title": "New Title", ⏎ "body": "New Body" ⏎ }``` [https://gitter.im/crystal-lang/crystal?at=5ebc880a40e3122a881818f5]
<FromGitter> <Blacksmoke16> fetches the related model from the DB, applies the deserialized data from the `PUT` request to it, then returns the obj
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5ebc88807312422a87e38d6f]
<FromGitter> <Blacksmoke16> i.e. retains other columns, like FKs or timestamps