<FromGitter>
<Blacksmoke16> also would be nice to have optional dependencies in shards
<FromGitter>
<Blacksmoke16> that are required for specific portions of code to work but otherwise not needed
<FromGitter>
<Blacksmoke16> which would tie into the `check if a shard is installed` macro, as if someone does `require "myApp/feature"` could throw compile error if that required shard is not installed
<FromGitter>
<Blacksmoke16> i guess it could be argued to just use separate shards but can be kinda overkill imo
<FromGitter>
<girng> i'
<FromGitter>
<girng> i'm getting `Unhandled exception in spawn: connect: Connection refused (Errno)` with `sock = UNIXSocket.new("pipe.sock")`
<FromGitter>
<girng> this is happening on native linux too, not just WSL. i don't have any sockets open except for the main socket server that is on port 9300 (master server)
fullforce has joined #crystal-lang
<fullforce>
asterite: got your message, power cut out
<FromGitter>
<Blacksmoke16> plan is to combine the required stuff for route definitions plus an optional annotation or something to build it out (for the most part) with minimal effort
fullforce has quit [Quit: leaving]
<FromGitter>
<Blacksmoke16> Peek*
<FromGitter>
<girng> O_O
early has quit [Quit: Leaving]
early has joined #crystal-lang
early has quit [Quit: Leaving]
early has joined #crystal-lang
<FromGitter>
<girng> WOW this is awesome. i just setup a *local* TCPServer on a diff port, and then utilize `shell_exec("bash -c 'echo ${user_id} >/dev/tcp/127.0.0.1/9305'");` in php to notify my crystal process
<FromGitter>
<j8r> You can't write in a file with PHP other than creating a bash subprocess?! I don't believe it
<FromGitter>
<sfcgeorge> Implementors may already be aware of this but when wanting to add a new Ruby feature to Crystal the code of this gem might help https://github.com/marcandre/backports As it implements new Ruby features for older Rubies in pure Ruby (not C) it should make porting to Crystal clearer.
<FromGitter>
<Blacksmoke16> could do something similar :/
<FromGitter>
<alex-lairan> This could work, but what if `Array(String) | String`, this will not work. ⏎ ⏎ I think the best I have to do is to forbid `Union` types. ⏎ ⏎ For my ORM I already provide two getter ... [https://gitter.im/crystal-lang/crystal?at=5c62c595dc3f0523cca15afd]
<FromGitter>
<Blacksmoke16> :shrug: or just handle the extra logic
<FromGitter>
<Blacksmoke16> on another topic, had a thought that i could prob generate athena controllers/actions from a swagger.yml/json files
<FromGitter>
<j8r> I can't do `myvar.as(Hash(Char, _))`
<FromGitter>
<bew> `.as(SomeType)` is not the same as using `SomeType` as a restriction
<FromGitter>
<bew> restrictions are much permissive
<FromGitter>
<bew> `.as` tries to 'set' the type of `myvar`, it must be a fully defined type
<FromGitter>
<Prutheus> I have something like this: `data["sellerInfo"][0]["bidCount"][0].as_s` but when the hash key `”sellerInfo”` is missing, how can I then stop this line and not raise an exception?
<FromGitter>
<Prutheus> Is it also possible to do that? `result.data.dig?("sellerInfo", 0, "sellerUserName", 0)?.try &.as_s` I get error : `unexpected token: .` at `?.try`
<FromGitter>
<Blacksmoke16> i dont think you need the `?` at the end of `dig?`
<FromGitter>
<j8r> You can also use JSON.mapping or JSON::Serializable, if it is JSON
<FromGitter>
<j8r> It'll simplify your life
jemc has joined #crystal-lang
<FromGitter>
<Sija> @Prutheus it is, but as @Blacksmoke16 mentioned, that's one `?` too much :)
<FromGitter>
<Sija> `?` here is part of the method name (`dig?`), not a language construct (like say in CoffeeScript)
<FromGitter>
<Prutheus> I have the problem that I want to use this: `result.data.dig?("sellerInfo", 0, "bidCount", 0).try &.as_s.empty? ? NO_DATA : result.data.dig("sellerInfo", 0, "bidCount", 0)` and NO_DATA should be reached when dig returns nil or the string is empty
<FromGitter>
<Prutheus> but how to do that, not with my method
<FromGitter>
<Blacksmoke16> could use the json serializable stuff and deserialize your json into structs or something
<FromGitter>
<Blacksmoke16> would depend on how the data is structured tho
<FromGitter>
<Blacksmoke16> otherwise prob would have to break that up a bit
<FromGitter>
<Blacksmoke16> got some example json or something?
<FromGitter>
<bararchy> BTW do we have a good way to JSON#as_xml ?
<FromGitter>
<Sija> @bararchy There's `XML::Builder` but nuffin' like `Object#to_xml`, nope
<FromGitter>
<Blacksmoke16> i was working on that
<FromGitter>
<Sija> well, you can't have it generalized since generating XML is bit moar complex than JSON or YAML
<FromGitter>
<Sija> say, how would you (de)serialize arrays or other compound types?
<FromGitter>
<Blacksmoke16> yea sadly, main challenge is array of objects vs array of scalar values like string
<FromGitter>
<Blacksmoke16> and from_xml would be a pita
<FromGitter>
<Sija> that's why Apple came up with their own PLIST format which standarizes that shit, while still using XML underneath
<FromGitter>
<Blacksmoke16> go does it by wrapping each array value in a tag thats has the name of the array property
<FromGitter>
<Sija> hmm, so how would `%w(foo bar)` be serialized in such case?
<FromGitter>
<Blacksmoke16> its not between json and xml
<FromGitter>
<Blacksmoke16> it would be similar to `to_json` or `to_yaml` to be obj => serialization format
<FromGitter>
<Blacksmoke16> looks like they just use type name as key
<FromGitter>
<Sija> yep, fair 'nuff. yet it's still a convention (albeit I'd agree pretty sensible one)
<FromGitter>
<Blacksmoke16> prob play with it more, prob would add it to my shard first
<FromGitter>
<Blacksmoke16> dont know if it would be wanted int stdlib if there is talk of moving that stuff out
<FromGitter>
<Blacksmoke16> to_xml would be far easier than from_xml imo
<FromGitter>
<Blacksmoke16> esp since i know like nothing about the XML::Reader or whatever
markoong has joined #crystal-lang
<FromGitter>
<Sija> IMHO `to/from_plist` would make more sense since it's some standard you can build on, whereas XML has none apart from some conventions used here and there...
rohitpaulk has joined #crystal-lang
<FromGitter>
<Blacksmoke16> possibly
rohitpaulk has quit [Ping timeout: 245 seconds]
Vexatoast has joined #crystal-lang
Vexatos has quit [Ping timeout: 246 seconds]
fullforce has joined #crystal-lang
<FromGitter>
<j8r> I was searching where is IntegerLiteral, but it's NumberLiteral
<FromGitter>
<j8r> How can I have an Array of MacroDef?
_whitelogger has quit [Remote host closed the connection]
_whitelogger has joined #crystal-lang
FromGitter has joined #crystal-lang
<mps>
after some contemplation about "Programming Crystal" I must write my apology to the authors and publisher. For not a much money I have guides which are dispersed over net in one place and organized from simple to more complex features of language, and with nice interviews with people who successfully deployed crystal in their applications
<FromGitter>
<dscottboggs_gitlab> and it's the `params do...` verification syntax you're asking about?
<FromGitter>
<dscottboggs_gitlab> or just the whole thing?
<FromGitter>
<mettuaditya> can anyone send me link on coverage tool
<FromGitter>
<dscottboggs_gitlab> There isn't a working one as of yet I don't believe. I found one one time but it wasn't up-to-date and didn't seem to work.
<FromGitter>
<vladfaust> It now works on top of Onyx and SQLite. On my machine atm, gonna publish in days
<FromGitter>
<vladfaust> Along with the detailed tutorial of how to recreate the Crystal World by yourself :)
<FromGitter>
<dscottboggs_gitlab> @vladfaust I like the way the code is organized, it's obvious at a glance that it's a middleware module which creates a comment. The `params do...` syntax is nice but seems a bit...long or verbose? Idk, I kinda like @Blacksmoke16's annotation based param validation better, but I also like the way that one is.
<FromGitter>
<dscottboggs_gitlab> If only annotations weren't so ugly.....
<FromGitter>
<vladfaust> The matter of preference, I guess. I love using annotations but I think they're ugly and I'm trying to hide them under macros DSL :)
<FromGitter>
<dscottboggs_gitlab> yes that is exactly the issue lol
<FromGitter>
<vladfaust> Their syntax may be scary for newcomers
<FromGitter>
<vladfaust> They'd prefer a beautiful DSL instead
<FromGitter>
<dscottboggs_gitlab> I stumbled on a great syntax idea yesterday... `:>`. I had been thinking of recommending `|>` for a while but I like `:>` even more.
<FromGitter>
<dscottboggs_gitlab> Yeah I really think it's just the wierd syntax -- lots of languages have annotations
<FromGitter>
<dscottboggs_gitlab> Although they usually work differently than in Crystal
<FromGitter>
<vladfaust> `:>` for what? `:>Annotation`?
<FromGitter>
<dscottboggs_gitlab> That's not much better but it fits with Crystal's operator-focused syntax
<FromGitter>
<dscottboggs_gitlab> Ugh, I guess nothing's good enough to be worth breaking everything at this point
<FromGitter>
<Blacksmoke16> unless the implementation i dont see how you could get much better than `@[JSON::Field(key: "key")]` i mean its not *that* bad imo
<FromGitter>
<Blacksmoke16> is what inspired my shard
<FromGitter>
<vladfaust> And how do you differ between "non-affecting" `@param` and "affecting" `@Type`
<FromGitter>
<dscottboggs_gitlab> See, on first glance I would think those were just weird doc-builder directives
<FromGitter>
<vladfaust> Casing?
<FromGitter>
<Blacksmoke16> just gotta know i guess? as with any lang
<FromGitter>
<vladfaust> Okay then, but I don't like it
<FromGitter>
<elorest> I think the syntax is fine, as long as we don’t use them everywhere. Are there like specific use cases where they make the most sense or is the current fad to just “Annotate all the things”?
<FromGitter>
<Blacksmoke16> afaik they are they preferred way to add compile time info to types, e.x. methods/properties/classes
<FromGitter>
<dscottboggs_gitlab> They tend to be more flexible and powerful than DSL's since you have to define all your types at compile time anyway
<FromGitter>
<Blacksmoke16> which i like that they are kinda "universal" in that its easy to tell what they are applied to, and if every serialization lib for example supported them changing which one you use would just be a matter of changing the annotation, and not have to worry about shard specific macros
<FromGitter>
<Blacksmoke16> so like everything kinda just "works"
<FromGitter>
<Blacksmoke16> vs i need this macro DSL for my ORM, this one for my REST API, this one for my validation/serialization
<FromGitter>
<Blacksmoke16> when they all pretty much are doing the same thing
<FromGitter>
<dscottboggs_gitlab> that's a really good point
<FromGitter>
<Blacksmoke16> would be more clear of what it is, but longer to type?
<FromGitter>
<dscottboggs_gitlab> and less ugly, which is my big gripe
<FromGitter>
<dscottboggs_gitlab> I'd say have both but Crystal is anti-alias
moei has quit [Quit: Leaving...]
<FromGitter>
<elorest> Hmmm. When I tried using annotations instead of macro’s a couple months back it really seemed like I was trying to pound a square peg into a round hole, plus it seemed to clutter up namespace with a bunch of single use module definitions. ⏎ ⏎ Faster is better though.
<FromGitter>
<dscottboggs_gitlab> it definitely depends on the use-case IMO, and annotation-based macros are definitely harder to write and require more knowledge about that area of Crystal than just a regular DSL
<FromGitter>
<dscottboggs_gitlab> yeah I always think I have these great idas and then I write it out and it's like "well that's not that much better"
<FromGitter>
<Blacksmoke16> it requires a diff way of thinking, plus annotations are not a replacement to macros
<FromGitter>
<Blacksmoke16> you need macros to get the annotations
<FromGitter>
<dscottboggs_gitlab> A really easy change that would make a big difference is not requiring the parentheses within the annotation
<FromGitter>
<Blacksmoke16> its just an alternative way to "storing" the data, vs having a macro DSL build out a method/property, just have the annotation on the method/property
<FromGitter>
<Blacksmoke16> is that a requirement atm?
<FromGitter>
<elorest> More knowledge is fine as long as it’s easy for the end user of libraries to use. My concern is that people come to crystal because it’s beautiful syntax plus speed. If the code all ends up looking like @Blacksmoke16 ’s ORM example above, then rust starts to look a lot more palatable.
<FromGitter>
<dscottboggs_gitlab> yes
<FromGitter>
<dscottboggs_gitlab> > If the code all ends up looking like @Blacksmoke16 ’s ORM example above, then rust starts to look a lot more palatable. ⏎ ⏎ this ☝️
<FromGitter>
<Blacksmoke16> depends on what the user things is `beautiful syntax`
<FromGitter>
<Sija> redundant for someone creating a library, perhaps but definately nicer for an end-user
<FromGitter>
<paulcsmith> A lot of times I'd rather create a separate object than overload properties with lots of annotations. But that may be just me
<FromGitter>
<Sija> bear in mind that people love Crystal for its syntax and brevity
<FromGitter>
<paulcsmith> Annotations are helpful, but I think a lot of times it may mean a class is getting stuffed with too many responsibilities that may be better to split out instead. So one class handles models, another serialization, etc. Rather than one class doing all of it
<FromGitter>
<Sija> @Blacksmoke16 "if every serialization lib for example supported them changing which one you use would just be a matter of changing the annotation, and not have to worry about shard specific macros" if… ;)
<FromGitter>
<Blacksmoke16> @paulcsmith yea, i like to write the least amount of code i can
<FromGitter>
<Blacksmoke16> so one class that handles everything nicely is my preference
<FromGitter>
<paulcsmith> One downside to that approach is it can make it hard to extend. For example, what happens when you have two JSON serializers. One for v1 of the api and one for v2. What do you do?
<FromGitter>
<paulcsmith> If you have separate classes you create a new class. If you use annotations you have serialization happening in the main class and in some other class. That is ok, but it is a tradeoff
<FromGitter>
<dscottboggs_gitlab> oh wow, haven't run into that yet
<FromGitter>
<dscottboggs_gitlab> that would certainly be an issue
<FromGitter>
<Blacksmoke16> in my perfect world each one would have their own annotation that each lib would know how to implement
<FromGitter>
<Blacksmoke16> and it would be that easy, no need to have new classes here and there
<FromGitter>
<paulcsmith> This is indeed less code, but I feel that it is difficult to parse. I think with a reasonably sized serializer it would be difficult to figure out what "admin" renders. Those annotations could be all over
<FromGitter>
<paulcsmith> I think this may just be a different viewpoint. I just think annotations have their pros and cons. And for some people the downsides may not be worth it.
<FromGitter>
<Blacksmoke16> it would just render properties on the `User` class that are part of that group
<FromGitter>
<Blacksmoke16> which can easily be seen by looking at return type of the action
<FromGitter>
<Blacksmoke16> pretty much
<FromGitter>
<Blacksmoke16> > Those annotations could be all over ⏎ Thats the point of having everything in the one `User` class. the its all centralized
<FromGitter>
<Blacksmoke16> but we're arguing semantics atm
<FromGitter>
<paulcsmith> Maybe. Personally I think something like this: https://gist.github.com/paulcsmith/6a2d8596f985baf8bbf692973fef13d9 is difficult to read. It would be hard to look at that class and visualize what an "admin" would look like since they are now scattered on multiple lines. And this is with a fairly small serializer.
<FromGitter>
<paulcsmith> I think to some degree this comes down to preference is what I'm getting at. Annotations are not necessarily better or worse
<FromGitter>
<Blacksmoke16> aye, also comes down to if it was your codebase you would know what an "admin" represents
marius has joined #crystal-lang
<FromGitter>
<Blacksmoke16> vs an abstract example w/o context
<FromGitter>
<paulcsmith> Yeah that is true. For smaller teams this may be perfect to use annotations. But for medium sized teams it is unlikely everyone would know what all the serializers look like
<FromGitter>
<dscottboggs_gitlab> Yeah, I have to agree. I think there are a lot of cases where annotations make sense, but a `group "group name" do...` DSL would be a lot nicer for his example.
<FromGitter>
<paulcsmith> Because you can look at it and see only what an admin should look like
<FromGitter>
<dscottboggs_gitlab> oof would that even work? ugh
<FromGitter>
<paulcsmith> Or yeah a group macro or something
<FromGitter>
<paulcsmith> I dunno if it'd work but something like that would definitely help
<FromGitter>
<Blacksmoke16> now we're back to `so like everything kinda just "works" vs i need this macro DSL for my ORM, this one for my REST API, this one for my validation/serialization`
<FromGitter>
<Blacksmoke16> :P
<FromGitter>
<Blacksmoke16> which in the end it doesnt really matter, whatever works for you
<FromGitter>
<dscottboggs_gitlab> well, no, Paul's exaple just inherits from a certain type which defines the macros by default.
<FromGitter>
<paulcsmith> You can not use annotations and still not have a DSL
<FromGitter>
<paulcsmith> Yeah exactly
<FromGitter>
<paulcsmith> It has almost no macros. It is basically one method that returns a data object. Super easy to extend. You can downcase or do whatever you want to values.
<FromGitter>
<paulcsmith> It is not perfect, but it is not some giant DSL :P
<FromGitter>
<Blacksmoke16> yea fair enough
<FromGitter>
<dscottboggs_gitlab> I like how `JSON::Serializable` et al do it, where annotations are available for options but there are sensible defaults which don't require annoations
<FromGitter>
<Blacksmoke16> ^
<FromGitter>
<vladfaust> ^
<FromGitter>
<Blacksmoke16> is how i tried to setup my stuff, ability to expand upon but sensible defaults
<FromGitter>
<dscottboggs_gitlab> if every property needs an annoation, I feel like there's probably a better way to do it, like inheriting from a type which defines macros based on it's `instance_whatever`s or a DSL.
<FromGitter>
<paulcsmith> Another problem I've had with ActiveModel Serializers and similar "put it all in one spot" thing is that it can be hard to expand. For example. How would you add the number of todos to a todos serializer with annotations?
<FromGitter>
<Blacksmoke16> hence, properties w/o annotation are assigned `default` group, so its not like you *have* to annotation everything, just those that need it
<FromGitter>
<dscottboggs_gitlab> or including a module
<FromGitter>
<paulcsmith> You could add a property like `count` but then it'd need to be nilable since sometimes you don't care about that. This is the main problem I have with stuffing classes with stuff. It can quickly break when new stuff is added which leads to weird hacks, nilable values, etc.
<FromGitter>
<paulcsmith> However this is not the case with all projects. Just something I think people should keep in mind when deciding on one route v. the other
<FromGitter>
<Blacksmoke16> id have to test it but something like
<FromGitter>
<paulcsmith> Yeah, so now you have a nilable value which will almost certainly lead to bugs
<FromGitter>
<paulcsmith> You could forget to pass the count in one call and then your users would get `count: nil`
<FromGitter>
<Blacksmoke16> you wouldnt have to touch it
<FromGitter>
<Blacksmoke16> it would just be there as a virtual property for serialization
<FromGitter>
<paulcsmith> By making a new class just for serializing that type of object you can set it to non nil and it would be nearly impossible to forget that
<FromGitter>
<paulcsmith> Yeah but you will not get compile time guarantees
<FromGitter>
<Blacksmoke16> i mean you also could set it not nil and default to 0
<FromGitter>
<Blacksmoke16> hard to say without an actual example
<FromGitter>
<dscottboggs_gitlab> I'm sorry, I don't understand...crystal is null-safe, you can't have a null reference bg
<FromGitter>
<paulcsmith> I'll show an example. One sec
<FromGitter>
<paulcsmith> It would not raise, it would just be incorrect
<FromGitter>
<dscottboggs_gitlab> it would be a pain in the dick to do `if count = something.count` every time but it wouln't ever result in an error
<FromGitter>
<paulcsmith> `Example.new(posts: posts).to_json` would incorrectly have `count: nill`
<FromGitter>
<dscottboggs_gitlab> how?
<FromGitter>
<dscottboggs_gitlab> wouldn't count be `posts.size`?
<FromGitter>
<paulcsmith> It could, but you could also forget that and then introduce a bug
<FromGitter>
<paulcsmith> Not a runtime error, but still a bug
<FromGitter>
<dscottboggs_gitlab> fair enough
<FromGitter>
<paulcsmith> Or if you had a `0` default it is the same thing, maybe worse. Because you'd accidentally send `0` when there may be more than that
<FromGitter>
<dscottboggs_gitlab> yeah, why is `#count` nillable?
mps has quit [Ping timeout: 250 seconds]
<FromGitter>
<dscottboggs_gitlab> I agree, that would be worse for sure
<FromGitter>
<paulcsmith> This example wasn't the best, but what if I had a `User` model. It would be weird to give it a count
<FromGitter>
<paulcsmith> So `User.first` shouldn't return a user with a count because it isn't an array. This is the problem with annotations in my mind. It makes it easy to do the simple case, but when you want something a little different it forces you into things that result in fewer compile time guarantees or strange hacks
<FromGitter>
<Blacksmoke16> i tried it
<FromGitter>
<dscottboggs_gitlab> @Blacksmoke16 yes, in your case it worked, but bugs happen to the best of us
<FromGitter>
<Blacksmoke16> yea for sure
<FromGitter>
<paulcsmith> I'm also just obsessed with compile time guarantees. Not necessary but I like to make it as hard as possible to do the wrong thing. Sometimes it means a bit more code, but I think it is worth it to reduce bugs
<FromGitter>
<dscottboggs_gitlab> @paulcsmith now I'm *more* confused! haha
<FromGitter>
<paulcsmith> I have to go right now for dinner, but I can post what I mean. I've been meaning to do a more in-depth blog post, but I'll try to post examples later
<FromGitter>
<paulcsmith> Cool if I ping you guys on those (assuming your interested)
<FromGitter>
<Blacksmoke16> would like to come up with ideas for how to handle those cases in my shard but yea, hard to come up with *all* the use cases on your own
<FromGitter>
<Blacksmoke16> as thats a good point of wanting to include something on serialization only thats not really part of the object