ChanServ changed the topic of #crystal-lang to: The Crystal programming language | http://crystal-lang.org | Crystal 0.29.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
<FromGitter> <watzon> Yeah it's basically an abstract over machine code that allows you to easily target multiple arches
<FromGitter> <watzon> Like an adapter
<FromGitter> <Blacksmoke16> Yea pretty much
<FromGitter> <Blacksmoke16> @girng ^
<FromGitter> <girng> this is a dumb question, but why not
<FromGitter> <girng> so, for example, in c++ you have classes. in crystal you have classes. what happens when you do `class Test end` in LLVM?
<FromGitter> <girng> does it literally transform that into a low level c++ class?
<FromGitter> <girng> "in LLVM" i mean, when crystal'scompiler uses class Test to conform to LLVM's api
<FromGitter> <watzon> You have to define how that code translates to LLVM IR
<FromGitter> <girng> so what is it really creating in c++ code then?
<FromGitter> <watzon> It doesn't create anything in C++
<FromGitter> <watzon> LLVM is written in C++
<FromGitter> <watzon> It doesn't compile to C++
<FromGitter> <watzon> Major difference
<FromGitter> <girng> i thought you could generate crystal to c++ code. i remember asterite saying this somwhere
<FromGitter> <girng> but ioculd be wrong, don't quote me please
<FromGitter> <watzon> There may be a way to do so that I'm not familiar with, but LLVM doesn't generate C++
<FromGitter> <watzon> It generates machine code
<FromGitter> <girng> so class Test is finalized through LLVM and transformed into bytecode
<FromGitter> <meltheadorable> I don’t think so
<FromGitter> <girng> this is really interesting stuff, it's got my brain on fire
<FromGitter> <meltheadorable> I am relatively sure that crystal has to decide the IR representation of classes before LLVM gets its hands on them — it’s possible you can give LLVM some metadata about classes, but that’s not my understanding — classes are a construct of higher-level languages
<FromGitter> <watzon> Exactly
<FromGitter> <meltheadorable> LLVM IR is very low level, it’s basically machine code + metadata for a processor that’s ever so slightly more expressive than like, x86 assembly
<FromGitter> <watzon> Everything goes through a tokenizer, is parsed, and then crystal tells LLVM how to transform the parsed AST into bytecode
<FromGitter> <watzon> By the end it's all very abstract
<FromGitter> <watzon> Because LLVM doesn't have a concept of classes
<FromGitter> <girng> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3b96216ec2e14223f7bd7b]
<FromGitter> <girng> Good lord
<FromGitter> <girng> > Everything goes through a tokenizer, is parsed, and then *crystal tells LLVM how to transform* the parsed AST into bytecode ⏎ ⏎ this is where i'm so interested at
<FromGitter> <girng> where does that happen
<FromGitter> <watzon> I don't care enough to go searching
<FromGitter> <girng> i wonder if it's possible to print out the AST
<FromGitter> <girng> into a cool looking graph
<FromGitter> <girng> of your codebase, lol
<FromGitter> <watzon> I believe you can
<FromGitter> <watzon> You can also use the parser directly
<FromGitter> <girng> lol epic
<FromGitter> <girng> hey watzon and melody thx for the info on this stuff, it's very interesting. i think this low level compiler stuff is really something a dev that is extremely knowledgable about it should fiddle around with. like core contributors, etc. i'm not gonna research into it any further as it's too daunting. but very cool nonetheless
<FromGitter> <tenebrousedge> so the veggies were definitely the best part of that meal. I added a dash of white truffle oil, and baked them until the apples were tender. The chops were okay but not really memorable
<FromGitter> <Blacksmoke16> @kinxer https://www.youtube.com/watch?v=G3OceKgL_Uc
<FromGitter> <kniknoo> Yeah, thanks for that y'all, that helped clear up a bit I don't yet understand as well.
<FromGitter> <Blacksmoke16> TIL you can use `do`/`end` in macro land
<FromGitter> <Blacksmoke16> also made DI stuff not depend on current PRs
<FromGitter> <Blacksmoke16> bit less clean but meh
lucasb has quit [Quit: Connection closed for inactivity]
<FromGitter> <dscottboggs_gitlab> @Blacksmoke16 could you show an example of `do`/`end` in macros? I remember trying ⏎ ⏎ ```{% [1, 2, 3].each do |x| %} ⏎ put {{x}} ⏎ {% end %}``` ⏎ ⏎ and it not working, which is why we need `for`/`in` in macro land... kinda bugs me a bit that it's like that TBH [https://gitter.im/crystal-lang/crystal?at=5d3ba075422eab0d333caa17]
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3ba089f3e76e1327137637]
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3ba093ad9a483d8c4937dc]
<FromGitter> <Blacksmoke16> is the full block
<FromGitter> <dscottboggs_gitlab> Oh i see, it's all wrapped up in one `{% %}` block
<FromGitter> <Blacksmoke16> yea, there isnt `.each` in macro land, but seems to work for other methods that take a block
<FromGitter> <dscottboggs_gitlab> well, your example is building out a macro variable. Mine was a little different... building out the code from a block
<FromGitter> <Blacksmoke16> right but in your example the array is an `ArrayLiteral` right?
<FromGitter> <Blacksmoke16> which doesnt have `.each` on it
<FromGitter> <dscottboggs_gitlab> oh i see
<FromGitter> <watzon> There are a lot of methods that need to be ported to macro land still
<FromGitter> <watzon> Specifically array methods
<FromGitter> <tenebrousedge> will they be?
<FromGitter> <tenebrousedge> why haven't they been ported?
<FromGitter> <Blacksmoke16> prob just needs done
<FromGitter> <tenebrousedge> ...
<FromGitter> <Blacksmoke16> what? thats a valid answer :P
<FromGitter> <tenebrousedge> yeah, I'm just gonna check out the code real quick
<FromGitter> <tenebrousedge> people use `zsh` right? the `d` command is <3
<FromGitter> <tenebrousedge> ~/s/h/canhascodez ❯❯❯ d ⏎ 0~/src/html/canhascodez ⏎ 1~/src/crystal/scanf ⏎ 2~ ⏎ 3/media/kai/32740abf-3992-470c-b57a-ca619f8aeb88 ... [https://gitter.im/crystal-lang/crystal?at=5d3ba44217279f5506c3c0d3]
<FromGitter> <Blacksmoke16> huh di refactor didnt help response time as much as i thought it would
<FromGitter> <Blacksmoke16> oh well
<FromGitter> <dscottboggs_gitlab> performance is hard to predict
<FromGitter> <Blacksmoke16> apparently im last on the web-framework benchmark list now for some reason lol
<FromGitter> <dscottboggs_gitlab> wtf lol
<FromGitter> <Blacksmoke16> 230ms or so
<FromGitter> <Blacksmoke16> locally i get 23 so :shrug:
<FromGitter> <Blacksmoke16> subjective to docker and the computer that it runs on i guess
<FromGitter> <dscottboggs_gitlab> I thought you were second behind some like barebones not-super-usable libs? I mean, you can't be slower than Lucky! :p
<FromGitter> <Blacksmoke16> after i implemented the service container stuff perf went down a bit
<FromGitter> <Blacksmoke16> 8ms to like 20 some
<FromGitter> <dscottboggs_gitlab> hm
<FromGitter> <Blacksmoke16> but not really trying to have the fastest one so meh
<FromGitter> <Blacksmoke16> still hella fast, plus is only one with DI framework so +1
<FromGitter> <dscottboggs_gitlab> fair enough 💯
<FromGitter> <tenebrousedge> ...why are all the `ArrayLiteral` methods defined with empty bodies?
<FromGitter> <Blacksmoke16> because what you're looking at is just for the api docs
<FromGitter> <dscottboggs_gitlab> `Crystal::Macros` is some weird fake module
<FromGitter> <tenebrousedge> where's the real code?
<FromGitter> <Blacksmoke16> have fun :p
<FromGitter> <tenebrousedge> 2115
<FromGitter> <tenebrousedge> as long as it has `map` and `reduce` I see no point in `each`
<FromGitter> <dscottboggs_gitlab> oh boy
<FromGitter> <Blacksmoke16> find and select are my most used ones
<FromGitter> <Blacksmoke16> making a blog post on some DI patterns with examples
<FromGitter> <Blacksmoke16> should be quite helpful in showing some of the power it brings
<FromGitter> <Blacksmoke16> if theres anything anyone would like me to include just let me know
<FromGitter> <Blacksmoke16> question/topic wise that is
<FromGitter> <meltheadorable> I’ve honestly never understood the point of DI
<FromGitter> <tenebrousedge> `new` is frequently problematic
<FromGitter> <Blacksmoke16> sharing objects between classes
<FromGitter> <Blacksmoke16> making testing easier
<FromGitter> <Blacksmoke16> able to swap out services without much code changes
<FromGitter> <meltheadorable> I’m not saying there is none, I’ve just never been able to see the point, attempts to make DI happen in ruby were always met with sort of just confused blank stares, I think it struck a lot of people as a pointless javaism
<FromGitter> <Blacksmoke16> maybe my blog post will sway your opinion 😉
<FromGitter> <Blacksmoke16> its deff more common on some langs than others
<FromGitter> <meltheadorable> I am open to being persuaded, even if it’s only interesting because of the ways Crystal is different from Ruby
<FromGitter> <meltheadorable> in ruby it never seemed to make any sense
<FromGitter> <Blacksmoke16> ill ping you when its done if you want to look at a draft
<FromGitter> <dscottboggs_gitlab> ☝️ July 26, 2019 9:47 PM (https://gitter.im/crystal-lang/crystal?at=5d3bad3e6cf91f06f28a8caf) ⏎ ⏎ Huh?
<FromGitter> <dscottboggs_gitlab> @tenebrousedge ☝️
<FromGitter> <tenebrousedge> constructor injection is pretty common
<FromGitter> <meltheadorable> ruby is the only language i’ve ever really been deeply fluent in, so that’s just where i draw most of my experience from
<FromGitter> <Blacksmoke16> its not a super common thing in Ruby afaik
<FromGitter> <tenebrousedge> `new` is kind of a hard binding. You don't get to change the object that you get back
<FromGitter> <dscottboggs_gitlab> I'm not sure I understand... one could certainly define ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bae8b6f38443976681d5d]
<FromGitter> <Blacksmoke16> thats what `def initialize` does
<FromGitter> <Blacksmoke16> plus some extra stuff to allocate memory
<FromGitter> <dscottboggs_gitlab> well, initialize also registers the reference with the GC
<FromGitter> <tenebrousedge> but if you ever want to mock that out, you're stuck
<FromGitter> <tenebrousedge> the problem is calling `new` within the body of a method
<FromGitter> <dscottboggs_gitlab> Hm?
<FromGitter> <Blacksmoke16> this example
<FromGitter> <tenebrousedge> ```def a ⏎ b = Foo.new ⏎ end``` ⏎ ⏎ You can't change what `b` is without overriding the `a` method [https://gitter.im/crystal-lang/crystal?at=5d3baf14c356af25e035a1f3]
<FromGitter> <Blacksmoke16> ^ that
<FromGitter> <dscottboggs_gitlab> oh.
<FromGitter> <Blacksmoke16> imagine `Foo` is like `ApiClient`
<FromGitter> <dscottboggs_gitlab> wait.
<FromGitter> <dscottboggs_gitlab> what if `Foo.new` gets overwritten to return `Bar`
<FromGitter> <tenebrousedge> then you have two things to test
<FromGitter> <Blacksmoke16> which you shouldnt care about when testing `Baz` class
<FromGitter> <tenebrousedge> but if you have ⏎ ⏎ ```def a(b = Foo.new) ⏎ end``` ⏎ ⏎ Then you can swap `Foo` out arbitrarily [https://gitter.im/crystal-lang/crystal?at=5d3baf68ef58b93a88646a0c]
<FromGitter> <tenebrousedge> alternately, you can use a DI container
<FromGitter> <dscottboggs_gitlab> oh I see where you're going with this
laaron- has quit [Remote host closed the connection]
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3baf98071bb025dff96aa4]
<FromGitter> <Blacksmoke16> wich is much easier to test when you can do like
<FromGitter> <dscottboggs_gitlab> but Crystal has interfaces with modules
<FromGitter> <Blacksmoke16> or parent classes
<FromGitter> <dscottboggs_gitlab> yeah
<FromGitter> <dscottboggs_gitlab> well, but not multiple inheritance, so including modules as interfaces is more useful
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bafdece271b4acd13719a]
<FromGitter> <Blacksmoke16> yea
<FromGitter> <Blacksmoke16> should have used `ApiClientInterface` in the type restriction, my bad
<FromGitter> <Blacksmoke16> but this would allow you do do like
<FromGitter> <Blacksmoke16> ```klass = SomeClass.new MockApiClient.new ⏎ klass.get_data.should eq "DATA"``` [https://gitter.im/crystal-lang/crystal?at=5d3bb009ecf3bf7b1a43b02d]
<FromGitter> <Blacksmoke16> allows you to not worry about what the api client is doing, and focus only on testing `SomeClass`
<FromGitter> <Blacksmoke16> another example is like could easily swap out the implementation of a class by changing what class gets injected
<FromGitter> <dscottboggs_gitlab> so what is the point of DI if you can just say "`@x` is an `Y`" where `@x ` is an instance variable, and `Y` is a module which implements (perhaps abstractly, perhaps not) the methods needed to perform said tests?
<FromGitter> ... subtly different APIs anyway, so you’d be better off creating wrappers or adapters in a lot of cases where you’d need to refactor, it’s rarely trivial to just swap `FooClient` for `BarClient` in practice, they don’t implement the same interface
<FromGitter> <meltheadorable> because ruby lets you overwrite fucking anything at runtime, you can avoid a lot of the problems with testing hardcoded interactions between classes that more rigid languages don’t have, so there’s a lot fewer benefits to not just going ahead and hardcoding that call to `Foo.new`, especially if it’s unlikely you’re going to need to swap out `Foo` for something else, and most clients would have
<FromGitter> <Blacksmoke16> `RedisCache` vs `FileSystemCache` for example
<FromGitter> <meltheadorable> in crystal i can see maybe more need for this, but will have to think about it
laaron has joined #crystal-lang
<FromGitter> <dscottboggs_gitlab> yeah but `RedisCache`and `FileSystemCache` are going to implement the same interface -- perhaps `.write` or `<<`. EIther way you can just declare your type's variable as implementing that interface, and have `RedisCache` and `FileSystemCache` include that module.
<FromGitter> <Blacksmoke16> pretty much yea
<FromGitter> <tenebrousedge> probably where I jump off the DI boat is with the DI containers
<FromGitter> <Blacksmoke16> thats the idea, you can make the type restriction the interface
<FromGitter> <dscottboggs_gitlab> I'd like to point out that all of the above discussed abstractions have notable negative runtime performance impacts.
<FromGitter> <Blacksmoke16> like what? the overhead of the container?
<FromGitter> <dscottboggs_gitlab> if Crystal is implemented like C++ (which I'm sure they had no choice about), the virtual function defined on the interface is chosen at runtime, not compile-time
<FromGitter> <dscottboggs_gitlab> I mean, a DI container is just an interface with some sugar right?
<FromGitter> <Blacksmoke16> a DI container is where the objects live that get injected into stuff
<FromGitter> <dscottboggs_gitlab> but like... how does that happen at a low-level?
<FromGitter> <Blacksmoke16> like how is it implemented?
<FromGitter> <dscottboggs_gitlab> that's kinda what I meant
<FromGitter> <dscottboggs_gitlab> like how is the memory allocated? what is this "container" and the "objects" it contains in memory? Structs, classes, interfaces, instances?
<FromGitter> <Blacksmoke16> athena does it by creating a hash of service name => obj
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bb304bdfdb22bbb4fe4a1]
<FromGitter> <dscottboggs_gitlab> so only one object can occupy a service at a time?
<FromGitter> <Blacksmoke16> a service is just an instance of a class with a name
<FromGitter> <Blacksmoke16> like notice the facebook and google services
<FromGitter> <Blacksmoke16> just diff instances of the same class
<FromGitter> <dscottboggs_gitlab> holy crap
<FromGitter> <dscottboggs_gitlab> what's the type signature of `@services` in this case??
<FromGitter> <Blacksmoke16> `Hash(String, Athena::DI::Service)`
<FromGitter> <dscottboggs_gitlab> I See
<FromGitter> <Blacksmoke16> have you seen the `"!partner"`/manager example i posted the other day?
<FromGitter> <dscottboggs_gitlab> nope
<FromGitter> <dscottboggs_gitlab> this week has been nuts
<FromGitter> <Blacksmoke16> `"!partner"` tells it to inject all services that have that tag ⏎ which allows you to then have another service that can be injected into controllers or param converters ⏎ which could for example, resolve/return the correct obj based on id ⏎ ie. `GET /partners/GOOGLE` ⏎ and if you want to add a new one just add another `@[Register("YAHOO", "Yahoo", name: "yahoo", tags: ["partner"])]` ...
<FromGitter> <tenebrousedge> (this solves a problem that I don't tend to have) ⏎ (I think)
<FromGitter> <Blacksmoke16> is quite powerful, but yea not saying every application/project needs this
<FromGitter> <Blacksmoke16> also relates to my uuid example, let me see if i can dig it up
<FromGitter> <Blacksmoke16> ☝️ July 23, 2019 6:58 PM (https://gitter.im/crystal-lang/crystal?at=5d379112b2db751dabb941fd)
<FromGitter> <Blacksmoke16> id be curious to hear how others would solve that w/o DI
<FromGitter> <Blacksmoke16> in lucky or whatever
<FromGitter> <dscottboggs_gitlab> yeah, if my drunk ass were to guess based on what I've been reading about C++ lately, that's probably what took you from first to last place on performance. You're basically creating a weird `Any` type with the `service` thing. Not only that, the `!partner` macro is creating a variably-sized (which increases overhead and isn't strictly necessary due to everything being known at compile time) array of
<FromGitter> ... pointers to some unknown interface. ⏎ ⏎ This means that if you want to access some function or data on some partner in this example, you're going to look up an address on the stack, then find that address on the heap, and then you can access the *address* of the object after doing a bounds check.
<FromGitter> <Blacksmoke16> probably, but `!partner` isnt a macro
<FromGitter> <dscottboggs_gitlab> I really have to wonder how crystal does structs with functions impelmenting interfaces as instance variables, because C++ just won't do that.
<FromGitter> <Blacksmoke16> its literally just doing `@services["partner_manager"] = PartnerManager.new [@services["google"].as(FeedPartner), @services["facebook"].as(FeedPartner)].as(Array(FeedPartner)) ⏎ `
<FromGitter> <dscottboggs_gitlab> I see
<FromGitter> <Blacksmoke16> which happens once at compile time, so every time you new up a container its executing the same static code
<FromGitter> <dscottboggs_gitlab> wait, where does the `@services["google"].as(FeedPartner), @services["facebook"].as(FeedPartner)` part come from?
<FromGitter> <dscottboggs_gitlab> that part has to come from a macro right?
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bb6cd84536e27e055e8e6]
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bb6e9ecf3bf7b1a43d8e6]
<FromGitter> <Blacksmoke16> is what gets added to the program via macros
<FromGitter> <Blacksmoke16> all the hard work happens in macro land
<FromGitter> <Blacksmoke16> finding registered services, resolving dependencies etc
<FromGitter> <dscottboggs_gitlab> I think ⏎ ⏎ ```manager_for Partner do ⏎ def names ⏎ @managed.map &.name ⏎ end ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5d3bb90ca9200c242804e7ce]
<FromGitter> <Blacksmoke16> hmm static array, not a bad idea
<FromGitter> <Blacksmoke16> prob could also set the size of the tags/`@services` ivars as well
<FromGitter> <Blacksmoke16> hmm, how would that dsl work?
<FromGitter> <meltheadorable> I think I’d need to see more practical examples to connect this to anything & decide whether I care ^_^;;; I’m struggling to see the usefulness here in the abstract
<FromGitter> <Blacksmoke16> ill have some more soon
<FromGitter> <Blacksmoke16> most practical would be the uuid example i linked a little while ago
<FromGitter> <Blacksmoke16> hmm, problem with static array is the user would also have to do like `def initialize(@partners : StaticArray(FeedPartner, 2)); end`
<FromGitter> <Blacksmoke16> vs it just working if they add more elements
<FromGitter> <meltheadorable> i’m not seeing how DI helps the UUID example actually
<FromGitter> <Blacksmoke16> how else would you get the uuid set in the http handler into the log processor?
<FromGitter> <Blacksmoke16> without having a way to share the same obj instance between them
<FromGitter> <meltheadorable> I’m not seeing how DI lets you share the same instance between them, or at least, I’m not sure what the advantage of your style of DI is over any other kind of what is effectively global state at that point
<FromGitter> <Blacksmoke16> `def initialize(@store : UuidStore); end`
<FromGitter> <Blacksmoke16> DI would auto inject the same instance from the container into both
<FromGitter> <Blacksmoke16> and since its a class, its passed by reference
<FromGitter> <meltheadorable> I’m still not seeing it.
<FromGitter> <Blacksmoke16> how would you handle it without DI then?
<FromGitter> <meltheadorable> I’m not sure, that depends on implementation details I can’t really make up off the top of my head
<FromGitter> <Blacksmoke16> fair enough
<FromGitter> <meltheadorable> the entire example feels contrived in a way i’m struggling to reason around
<FromGitter> <Blacksmoke16> yea, maybe the blog post will be better, will have some actual working code and stuff
<FromGitter> <meltheadorable> Yeah, mostly I can’t like, infer a context that would make the example make sense, and that disconnect is a struggle
<FromGitter> <Blacksmoke16> the back story to that little example is something we did at work recently
<FromGitter> <Blacksmoke16> when a request comes in we generate a uuid and store it in a store like that
<FromGitter> <Blacksmoke16> we inject that same store into a monolog processor, which adds it to all the logs that happen during that request
<FromGitter> <Blacksmoke16> we also inject it into our rabbit message builder thing that adds it to enqueued messages that happen during that request
jhass has quit [Ping timeout: 272 seconds]
<FromGitter> <Blacksmoke16> also gets added to response headers
<FromGitter> <Blacksmoke16> main point being say an error happens, you're able to search centralized logging for that uuid to find all relevant messages, logs etc
jhass has joined #crystal-lang
<FromGitter> <Blacksmoke16> im sure there are other ways to do it, but symfony makes it easy, not much more to do than make the classes and add them to the constructor
<FromGitter> <meltheadorable> that seems vaguely useful, but not that the expense of having to add a UUID store to the signature of every object initialization that happens during any request
<FromGitter> <Blacksmoke16> > having to add a UUID store to the signature of every object initialization that happens during any request
<FromGitter> <Blacksmoke16> hM?
<FromGitter> <meltheadorable> and it just seems like there has to be a better way for a web framework to expose a request ID throughout the duration of the request
<FromGitter> <meltheadorable> like presumably something at a higher level is controlling enough of the request flow to persist information like that
<FromGitter> <Blacksmoke16> there might be, but would depend on how flexible it is
<FromGitter> <Blacksmoke16> since we needed it outside of the framework itself
<FromGitter> <meltheadorable> i mean, you could send it to the outside through whatever mechanism you are using to communicate with the other components
<FromGitter> <Blacksmoke16> right, which is DI :P
<FromGitter> <Blacksmoke16> is how symfony works for the most part
<FromGitter> <meltheadorable> DI seems to imply more than just “having methods that take arguments”
<FromGitter> <Blacksmoke16> its more DI + service container
<FromGitter> <Blacksmoke16> most of the magic is the container
<FromGitter> <Blacksmoke16> which handles what should be injected into each class's constructor
<FromGitter> <meltheadorable> yeah i’ve never used symfony but this strikes me as alternately so obvious it shouldn’t have such a weird name or so weird i want nothing to do with it, i’m trying to understand but i am just not connecting the dots
<FromGitter> <Blacksmoke16> it took me a while to wrap my head around it
<FromGitter> <Blacksmoke16> but its amazingly powerful now that i know what its doing
<FromGitter> <Blacksmoke16> like, want to abstract some common logic to do x?
<FromGitter> <Blacksmoke16> just do like
<FromGitter> <Blacksmoke16> ```class SomeNewService ⏎ { ⏎ }``` [https://gitter.im/crystal-lang/crystal?at=5d3bc2592136933a87fa1edb]
<FromGitter> <Blacksmoke16> then in the class that would use it
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bc2888aab922429c9d111]
<FromGitter> <Blacksmoke16> and thats it
<FromGitter> <Blacksmoke16> its deff just based on what you're used to
<FromGitter> <Blacksmoke16> everything has its pros and cons, and depends on what you're doing what would make sense
<FromGitter> <Blacksmoke16> im mostly just bringing what im used to to crystal, id truly be interested in hearing how others more familar with Ruby side of things would approach this
<FromGitter> <Blacksmoke16> scenarios like this*
<FromGitter> <meltheadorable> I think often I’d just approach the problem with an entirely different architecture, so it’s tough
<FromGitter> <meltheadorable> like this scenario feels like its an accumulation of other decisions I would not have made
<FromGitter> <meltheadorable> so it’s hard to make an apples to apples comparison
<FromGitter> <Blacksmoke16> for sure
<FromGitter> <Blacksmoke16> fair enough
<FromGitter> <tenebrousedge> Ruby you can arbitrarily redefine behavior
<FromGitter> <tenebrousedge> you can even do ⏎ ⏎ ```a = 5 ⏎ def a.meow ⏎ "bark" ⏎ end ⏎ a.meow #=> "bark"``` [https://gitter.im/crystal-lang/crystal?at=5d3bc3d0c356af25e036227c]
<FromGitter> <Blacksmoke16> :S
<FromGitter> <tenebrousedge> actually
<FromGitter> <tenebrousedge> I lied, you can't do that with integers
<FromGitter> <tenebrousedge> but any other object
<FromGitter> <tenebrousedge> integers are pseudo-objects
<FromGitter> <meltheadorable> I don’t think I have ever made use of that but you can
<FromGitter> <meltheadorable> with other objects I mean
<FromGitter> <girng> @tenebrousedge wait what, that's valid code in ruby?
<FromGitter> <tenebrousedge> I've done it precisely once, and just because submitting an upstream patch would have taken too much time
<FromGitter> <girng> you can assign an Int type a method?
<FromGitter> <tenebrousedge> not integer, but any other objectt
<FromGitter> <tenebrousedge> ```a = "123" ⏎ def a.foo ⏎ "bar" ⏎ end ⏎ a.foo #=> "bar"``` [https://gitter.im/crystal-lang/crystal?at=5d3bc46d071bb025dff9e6ce]
<FromGitter> <girng> wtf LOL
<FromGitter> <girng> i don't know if i like that or hate it
<FromGitter> <meltheadorable> i never do it
<FromGitter> <meltheadorable> but you can
<FromGitter> <meltheadorable> i encountered one really gnarly bug that required me to monkeypatch a ruby standard library method once
<FromGitter> <girng> is fibers a crystal thing or ruby thing
<FromGitter> <tenebrousedge> the use case was that neo4j.rb had done an upgrade, but forgotten to implement some obscure ActiveRecord method on their model, which was being called by some other third-party serialization code. I didn't have the time to patch either other library directly, but the method just needed to return `self` or something simple like that
<FromGitter> <tenebrousedge> so you just define the method on the object and everyone is happy
<FromGitter> <tenebrousedge> could probably have done `class Foo; def bar; self; end; end` but meh
<FromGitter> <meltheadorable> the tl;dr is that a misconfigured SMTP relay was apparently doing something weird like proxying SMTP via `s_client`instead of doing whatever it would have to do to actually natively speak the protocol, and when ruby sent it `RCPT` the SMTP relay was interpreting that as an instruction to reconnect/renegotiate the SSL handshake and dropped the connection, so I had to patch the Net::SMTP library to send
<FromGitter> ... the commands in lowercase
<FromGitter> <tenebrousedge> D: SMTP
<FromGitter> <meltheadorable> that took me about 4 days to diagnose?
<FromGitter> <tenebrousedge> I bet
<FromGitter> <meltheadorable> it was amazingly weird
<FromGitter> <tenebrousedge> @girng fibers is a Crystal thing
<FromGitter> <meltheadorable> but other than that i have rarely had to monkeypatch anything and i’ve never had to define new methods on an object instance
<FromGitter> <tenebrousedge> Ruby you can safely monkeypatch with `refine` though <__< Crystal has very limited abilities for that
<FromGitter> <meltheadorable> (i probably would have reopened the class to add the method, in your case, fwiw)
<FromGitter> <meltheadorable> I really really wish neo4j.rb had not tried to mimic ActiveRecord so much, I love AR but something-pretending-to-be-AR tends to just make me to expect it to have capabilities it doesn’t, and to mentally model things incorrectly
<FromGitter> <girng> @tenebrousedge thanks. how were sockets handled in ruby
<FromGitter> <girng> if they didn't have fibers
<FromGitter> <girng> like, new connections of sockets at a time (multiple)
<FromGitter> <tenebrousedge> Ruby has Fibers, I'm not sure what they're used for
<FromGitter> <tenebrousedge> I'm not sure how sockets are implemented
<FromGitter> <girng> ic
<FromGitter> <girng> If anyone wants to chime in there, please do thanks
<FromGitter> <meltheadorable> I need to layer a graph over top of my relational DB in one of my rails projects and I find myself wishing Neo4j.rb had a more graphy semantic API
<FromGitter> <meltheadorable> because that would make it more natural to model it
<FromGitter> <tenebrousedge> `abstract` usually means that it's not implemented there
<FromGitter> <tenebrousedge> wait, using neo4j.rb with a relational database‽ how? why? which?
<FromGitter> <tenebrousedge> so usually with an ORM there's a point of complexity where it doesn't get you much of anything over using the query language directly. I feel like neo4j reaches that point very quickly; neo4j.rb reduces boilerplate but doesn't provide a lot of the features that Cypher has. The idea of using it with SQL is just boggling to me
<FromGitter> <meltheadorable> @tenebrousedge i need both database types, is all — postgres is handling a lot of my mundane stuff like integration with devise and more mundane relationships, and lists that are a little bit easier to model relationally than as a graph, then I’m layering a graph DB over top, with references to instance IDs for my relational models, so that I can model more complex relationships between things and
<FromGitter> ... expose some of those relationships as well — my relational `Model` will be able to start graph traversals by finding `self.id` from the `ModelNode`
<FromGitter> <tenebrousedge> I tried very hard to avoid combining a relational and graph DB in the same app
<FromGitter> <tenebrousedge> synchronizing between the two sounded like a massive pain
<FromGitter> <tenebrousedge> also, doesn't postgres have some support for graphs?
<FromGitter> <meltheadorable> Yeah, it will be, for my use case it’s a relatively clear split between the info I’ll be storing in the graph vs the info i’ll be storing in the relational DB, so there’s no syncing, and I’m using UUID primary keys already, so the only shared info can just be forced to be used as the primary ID for both
<FromGitter> <meltheadorable> that simplifies things a lot
<FromGitter> <tenebrousedge> what is the graph db used for?
<FromGitter> <meltheadorable> Making connections/recommendations between things, I’ll be kind of lazily constructing it with some offline data processing
<FromGitter> <watzon> @tenebrousedge graph databases are useful when handling data or in social situations
<FromGitter> <watzon> Facebook uses a graph
<FromGitter> <tenebrousedge> I'm aware of what a graph db is useful for @watzon
<FromGitter> <watzon> Oh sorry
<FromGitter> <tenebrousedge> usually fewer things than people try to use them for
<FromGitter> <watzon> Misunderstood lol
<FromGitter> <meltheadorable> I may also be exposing some ability for users to define similar types of connections for arbitrary relationships
<FromGitter> <meltheadorable> that would also go in the graph DB
<FromGitter> <tenebrousedge> I think I found that difficult
<FromGitter> <meltheadorable> but there’s no need for that to be reflected back in postgres
<FromGitter> <meltheadorable> neo4j is poorly documented for it, but I think I figured out how to make it work
<FromGitter> <meltheadorable> im not building that layer of things right now though, so it’s nbd
<FromGitter> <meltheadorable> and if i can’t do it i can’t do it
<FromGitter> <tenebrousedge> hmm. I don't recall what problem I had with somewhat-arbitrary user-defined relationships. There was something ugly
<FromGitter> <meltheadorable> Yeah, I have no doubt it will be ugly
<FromGitter> <meltheadorable> but it’s not a super important bit of functionality either
<FromGitter> <meltheadorable> anyway tl;dr i’m using the graph DB to store kind of a secondary layer of interrelationships between instances of data in my normal models, but i can drive most of the basic functionality with relational models, so the graph will just be storing some richer/enhanced interrelationship data — some of that will be exposed to users, and some of it will be used to try to analyze and mine useful
<FromGitter> ... information from the graph offline, but because both will share primary IDs and there’s no syncing burden, it’s relatively trivial to hold references to both the node and model objects to combine information from them
<FromGitter> <meltheadorable> when needed
laaron has quit [Remote host closed the connection]
laaron has joined #crystal-lang
<FromGitter> <meltheadorable> @girng i dont have an account on the forums so im just gonna answer here, using the “abstract” keyword when defining an interface is a way of telling the compiler you WANT it to throw an error when you try to create a class to make the interface without defining the necessary methods — an abstract class/interface is defining an API/Specification, not behavior, so `abstract def write` will error if
<FromGitter> ... behavior for `write` is never defined, `def write` will compile but silently fail because `write` has no behavior and the implementing class never defined it, errors are good sometimes, when they are telling you something is wrong
<FromGitter> <girng> so abstract def is not for a method's functionality. just for api/specification?
<FromGitter> <tenebrousedge> yes
<FromGitter> <meltheadorable> correct
<FromGitter> <girng> i swear i've seen abstract def having functionality though
<FromGitter> <girng> can it be both?
<FromGitter> <girng> ..or maybe i havn't
<FromGitter> <tenebrousedge> I don't think the compiler checks that the method body is empty? but it won't ever be executed
<FromGitter> <tenebrousedge> it might check
<FromGitter> <tenebrousedge> I'm not going to check :P
<FromGitter> <meltheadorable> I don’t think you can give it a method body?
<FromGitter> <girng> is this the same for classes and def?
<FromGitter> <girng> blacksmoke's example has a abstract class
<FromGitter> <tenebrousedge> yes, they're not supposed to have bodies
<FromGitter> <tenebrousedge> giving it a body is a syntax error, apparently
<FromGitter> <watzon> Abstract def's cannot have a body
<FromGitter> <watzon> They are completely abstract
<FromGitter> <watzon> Abstract classes can contain normal defs though
<FromGitter> <meltheadorable> abstract classes cannot be instantiated, abstract methods can not have bodies, and abstract defs cannot exist in a non-abstract class
<FromGitter> <watzon> Yup pretty much
<FromGitter> <meltheadorable> You can apparently do this ⏎ ⏎ ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bd201ecf3bf7b1a447ef7]
<FromGitter> <meltheadorable> Which is an odd thing to do and I’m not sure why you would ever
<FromGitter> <watzon> That you can, but in that case you may as well just skip the `abstract def`
<FromGitter> <meltheadorable> For sure — I was just curious
<FromGitter> <watzon> Unless you want then to have to overload it, but then you'd need different parameters
<FromGitter> <meltheadorable> a lot of ruby programmers fake abstract classes & methods by doing a `raise NotImplementedError` in the method definition on the base class — I’d much prefer having real support for abstract classes & methods 😂
<FromGitter> <watzon> Yeah I prefer it
<FromGitter> <meltheadorable> but since it’d have the same behavior at runtime anyway it doesn’t make a lot of practical difference in ruby — here it’s great
<FromGitter> <watzon> I don't understand what's so hard to understand about abstracts though
<FromGitter> <watzon> But that's just me
<FromGitter> <tenebrousedge> probably the abstraction :P
<FromGitter> <watzon> I guess after 10 years of this stuff things just make sense
<FromGitter> <meltheadorable> I also think less experienced programmers can often struggle to wrap their heads around the fact that sometimes you *want* errors that could have been avoided, so writing code that does nothing except make other code throw errors can take a minute to see the value of
<FromGitter> <meltheadorable> somewhere there’s a tipping point between “my job as a programmer is to make the code stop yelling at me” and “my job as a programmer is to make the code yell at me when something is wrong”
<FromGitter> <watzon> I think Granite::Adapter::Base (https://github.com/amberframework/granite/blob/master/src/adapter/base.cr) is a good example of an abstract class and why you might want one
<FromGitter> <watzon> @meltheadorable agreed. I don't even remember when I hit that point.
<FromGitter> <andrius> Sorry guys, ruby way did not worked, how to transform `[{"aaa" => "bbb"}, {"ccc" => "ddd"}]` to the `{"aaa" => "bbb", "ccc" => "ddd"}` right way in crystal?
<FromGitter> <gdotdesign> one way is https://play.crystal-lang.org/#/r/7ate
<FromGitter> <watzon> My question is, do you have any control over the array before it becomes an array of hashes?
<FromGitter> <watzon> Tuples would be better
<FromGitter> <watzon> If you had `[{"aaa", "bbb"}, {"ccc", "ddd"}]` you could just do `arr.to_h`
<FromGitter> <watzon> I believe anyway
<FromGitter> <meltheadorable> i did this https://play.crystal-lang.org/#/r/7atf but it doesn’t feel great
<FromGitter> <watzon> Nothing is going to feel great, it's something you ideally shouldn't have to do
<FromGitter> <watzon> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3bd75def58b93a886568d6]
<FromGitter> <watzon> That is the ideal situation
<FromGitter> <watzon> You can always do this though https://play.crystal-lang.org/#/r/7ath
<FromGitter> <watzon> Which is basically what @gdotdesign did
<FromGitter> <meltheadorable> if i realized it would infer a hash as the accumulator, i probably would have gone with reduce, but i went with the slightly more verbose each trying to avoid dealing with the inline type annotations
<FromGitter> <meltheadorable> which is a habit i will eventually have to break
<FromGitter> <watzon> I love reduce and use it all the time
<FromGitter> <watzon> Wonderful method
<FromGitter> <meltheadorable> I didn’t realize it was that clever, I’ve rarely seen it used without explicitly defining an accumulator in the arguments
<FromGitter> <meltheadorable> I’ll probably use it more now
<FromGitter> <watzon> I generally specify an accumulator just to be more explicit and make it not seem so magical
<FromGitter> <meltheadorable> yeah, in ruby i don’t mind it so much, in crystal it’s sorta ugly to define a hash literal as an argument in a method call, which loses a lot of the elegance of the reduce one-liner over just using each
<FromGitter> <meltheadorable> probably fine for numeric accumulators though
<FromGitter> <watzon> I agree
_whitelogger has joined #crystal-lang
<FromGitter> <watzon> Just wrote a blog post on this topic https://dev.to/watzon/understating-abstract-classes-4ejj
<FromGitter> <watzon> Hopefully it's enough for most people
<FromGitter> <girng> :D
alex`` has joined #crystal-lang
sorcus has joined #crystal-lang
_whitelogger has joined #crystal-lang
absolutejam4 has joined #crystal-lang
absolutejam4 has quit [Ping timeout: 245 seconds]
ht_ has joined #crystal-lang
_whitelogger has joined #crystal-lang
<FromGitter> <girng> why doesn't size work on a float
<FromGitter> <girng> how can get test to return 5?
<FromGitter> <watzon> @girng why would it return 5?
<FromGitter> <girng> how many digits
<FromGitter> <watzon> Convert to string then do size
<FromGitter> <girng> thx
<FromGitter> <girng> to_s cuts off the last 0
<FromGitter> <girng> son of a btch
<FromGitter> <absolutejam_gitlab> There's no `IO::Multireader`?
<FromGitter> <watzon> @girng then use sprintf
<FromGitter> <watzon> `"%.2f" % 25.00`
<FromGitter> <watzon> @absolutejam_gitlab no, just `MultiWriter`
<FromGitter> <girng> @watzon okay wait 1 sec
<FromGitter> <girng> oh @watzon it works https://play.crystal-lang.org/#/r/7axg
<FromGitter> <girng> noiceeeeeee
<FromGitter> <watzon> Yup
<FromGitter> <watzon> `String#%` is awesome
<FromGitter> <girng> i like the [..] syntax for strings too
<FromGitter> <girng> i've never used that before in any language, feels cool
<FromGitter> <watzon> Yeah, although I'd avoid having a ton of logic inside the brackets
<FromGitter> <watzon> Looks messy
<FromGitter> <watzon> Better to put that stuff in variables
<FromGitter> <girng> eh
<FromGitter> <girng> true
Groogy has joined #crystal-lang
<FromGitter> <kniknoo> Oh, that's interesting you say that. I've been making the assumption that I should avoid intermediate variables unless it's my only choice.
<FromGitter> <tenebrousedge> I mean, I would
<FromGitter> <tenebrousedge> but <__< this is where I would use `scanf`, if I were done writing it
<FromGitter> <meltheadorable> that is…one way to do parsing
<FromGitter> <meltheadorable> but it’ll break if somebody types in `25`, `25.0`, or `25.001` — consider https://play.crystal-lang.org/#/r/7axs
<FromGitter> <meltheadorable> (split takes a limit, and it’ll just stop splitting it after you have the number of pieces you asked for)
<FromGitter> <meltheadorable> no need for more intermediate variables and no need for any logic in brackets
<FromGitter> <meltheadorable> and no need to convert the float back into a string to figure out how long it was to try to slice the message back out
<FromGitter> <kniknoo> Thank you for making me look up split limit. I've a lot to learn with processing strings.
<FromGitter> <meltheadorable> I had to look up whether crystal had it, but it’s a trick I’ve used in ruby before ^_^;;
woodruffw has quit [Ping timeout: 244 seconds]
woodruffw has joined #crystal-lang
laaron has quit [Quit: ZNC 1.7.1 - https://znc.in]
laaron has joined #crystal-lang
<FromGitter> <kniknoo> I'm gonna show my ignorance a bit but this is a burning question for me with all this "new" low-level power. So let's say I have a really bad case of Not-Invented-Here syndrome and I wanted to write an audio synthesis library that doesn't piggyback on a C library (I know the simple answer is libasound). At the end of the day, I need to "wiggle" something in a sine wave shape to make sound come out of the
<FromGitter> ... speaker. What within crystal do I need to "wiggle" to make the speaker "wiggle"? I know I'm oversimplifying this, I'm just trying to figure out what documentation I should be reading to grok device/service access.
<FromGitter> <Blacksmoke16> @dscottboggs_gitlab I refactored the registration to use ivars, and didnt affect the performance :/
lucasb has joined #crystal-lang
<FromGitter> <Blacksmoke16> might just chalk it up to docker/system power? :shrug:
<FromGitter> <meltheadorable> @kniknoo i don’t think you can go lower level than libasound without writing kernel drivers, the OS mediates your access to the hardware and I don’t think it will let you do it from userspace, but I could be wrong
<FromGitter> <kniknoo> Thank you, that's great. It gives me a jumping off point to work from.
<FromGitter> <meltheadorable> you probably cannot write drivers in crystal if you are trying to jump that direction
<FromGitter> <kniknoo> Understood, I reckon that would require inline ASM to be a possibility?
<FromGitter> <meltheadorable> No, i just can’t imagine that it’s possible to compile a kernel module — there’s a ton of restrictions and the compilation target can’t use any OS-level APIs, it’s extremely painful to compile kernel modules in rust even, and it’s a lot closer to being C
<FromGitter> <meltheadorable> i don’t think crystal can target bare metal like that but if i’m mistaken that’d be neat
<FromGitter> <kniknoo> Gotcha. Thank you, that answered a lot of questions I had about bare metal and crystal.
<FromGitter> <tenebrousedge> @watzon re: multimedia shells, the one that I was thinking of was TermKit (http://osxdaily.com/2011/05/19/termkit-terminal-reimagined-how-to-install/), which looked very interesting but became unmaintained and unusable almost immediately
<FromGitter> <meltheadorable> looks like it is actually sorta kinda possibleish, there’s a couple proofs of concept — it’s entirely impractical but there’s some discussion here https://github.com/crystal-lang/crystal/issues/2438
<FromGitter> <kniknoo> I read through the TempleOS link from last night and that "multimedia" term really wowed me. Would love to see the idea codified and expanded for crystal.
<FromGitter> <kniknoo> Oh cool, I recognize both of those projects mentioned as on my list to study. Sweet!
<FromGitter> <tenebrousedge> @kniknoo I don't know how well a lot of the embedded multimedia stuff would fare in a unix-compatible environment
<FromGitter> <tenebrousedge> I feel like Powershell might actually have a leg up there
<FromGitter> <kniknoo> Totally understood, I realize it would take a complete overhaul of a few things that have been set in stone for 30 - 50 years.
<FromGitter> <kniknoo> But I honestly think a lot of the ecosystem could use a 21st century remodel so that we don't hit a point where we're out of touch with the core paradigms.
<FromGitter> <tenebrousedge> Well...I would probably not want to use Crystal for that
<FromGitter> <tenebrousedge> I would prefer to do something like set the login shell to use `pry`
<FromGitter> <tenebrousedge> and then build up other commands from there
<FromGitter> <tenebrousedge> in theory you could do the same with `icr`, but `icr` recompiles the whole history for every command
gangstacat has joined #crystal-lang
Groogy has quit [Quit: WeeChat 2.5]
Groogy has joined #crystal-lang
<FromGitter> <meltheadorable> i mean, if i was going to build an OS around hypertext it’d probably end up looking more like chromeOS than anyone wants
<FromGitter> <meltheadorable> a browser’s rendering engine is the most advanced hypertext processor in existence, it’d be absurd not to capitalize on that
<FromGitter> <tenebrousedge> ChromeOS has an HTML-based shell, but it lacks any interesting features
<Groogy> Ugh the trouble of when you linking stuff from C and you aren ot sure if it is your lib code that is broken or the lib
<Groogy> and turns out it was the lib after a few hours and playing around with the 3D model in blender and it is already fixed on github D:
<FromGitter> <meltheadorable> yeah, i mean, it certainly doesn’t embrace what it is much
<FromGitter> <meltheadorable> but something like it would need to be the starting point
<FromGitter> <meltheadorable> https://hyper.is/ also does not embrace what it is much, but it’s just a terminal emulator, it does not include a hypertext shell
<FromGitter> <meltheadorable> but a terminal emulator like hyper would probably be the best home for a shell that could take advantage of it
<FromGitter> <meltheadorable> short of like, building an entire OS around it conceptually
<FromGitter> <nsuchy> How good is MongoDB support with Crystal?
<FromGitter> <nsuchy> Is there a stable-ish driver?
<FromGitter> <nsuchy> I am looking to add a pipe in Amber framework that does request logging
<FromGitter> <denolfe> This one is listed on awesome-crystal: https://github.com/ambercommunity/mongo.cr
<FromGitter> <nsuchy> Thanks @denolfe
<FromGitter> <nsuchy> Looking into exactly how the pipe in amber will work at the moment
<FromGitter> <nsuchy> My intent is to log full request bodies and tag it with helpful info
<FromGitter> <tenebrousedge> another proof-of-concept shell replacement (https://web.archive.org/web/20120229202639/http://lubutu.com/idea/ivo) (that went nowhere)
dingenskirchen has quit [Quit: dingenskirchen]
<FromGitter> <kniknoo> He talks a good talk, a shame that's as far as it went.
<FromGitter> <kniknoo> I see now what you're saying about hyper, neat idea too.
alex`` has quit [Ping timeout: 248 seconds]
<FromGitter> <dscottboggs_gitlab> ☝️ July 27, 2019 9:26 AM (https://gitter.im/crystal-lang/crystal?at=5d3c510def58b93a8868b268) 😞
<FromGitter> <dscottboggs_gitlab> sorry to hear that
alex`` has joined #crystal-lang
<FromGitter> <Blacksmoke16> ended up in a good spot so ill prob just keep it
<FromGitter> <dscottboggs_gitlab> that's cool
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3c6b237e00fc4ace5bdf5d]
<FromGitter> <Blacksmoke16> is what it looks slike now
<FromGitter> <Blacksmoke16> helped remove the need for all the `.as(T)`
laaron has quit [Remote host closed the connection]
<FromGitter> <absolutejam_gitlab> I can't sign in to the gitter app on android. And using the web sucks because the websocket gets broken until I refresh so I don't any new messages
<FromGitter> <absolutejam_gitlab> Can't sign in due to MFA on gitlab and github, and twitter just doesn't work
<FromGitter> <Blacksmoke16> pretty sure you just type the 4 numbers after your password
<FromGitter> <absolutejam_gitlab> Anyone consumed an openapi/swagger spec?
<FromGitter> <Blacksmoke16> yea
<FromGitter> <absolutejam_gitlab> It asks for a separate auth key but it won't do anything when I submit I don't have my NFC yubikey, although I doubt thayd work either
<FromGitter> <absolutejam_gitlab> Any examples @blackbox656_twitter?
<FromGitter> <absolutejam_gitlab> I
<FromGitter> <Blacksmoke16> https://github.com/Blacksmoke16/GESI/blob/master/src/parser/eve_swagger.cr prob quite shitty as i made that like the same month i started learning crystal but it does what i need
<FromGitter> <absolutejam_gitlab> Would be nice to just slurp the docker spec and have docker client in crystal
<FromGitter> <Blacksmoke16> https://github.com/icyleaf/swagger/ prob could also use that with `.from_json`
<FromGitter> <absolutejam_gitlab> Interesting
DTZUZU has quit [Quit: WeeChat 2.2]
DTZUZU has joined #crystal-lang
<FromGitter> <kniknoo> Is anyone else in Crystal as into the whole MINSWAN and Why culture of Ruby as I am? I know making a great web-framework is one way to pull in rubyists, but I'd like to recreate the quirkiness of the culture in our own idiom a bit as well.
<FromGitter> <tenebrousedge> ❤️ _why
<FromGitter> <tenebrousedge> Crystal could probably use a mascot
<FromGitter> <naqvis> Just relased `Pure Crystal` Library and CLI for working with container registries. ⏎ https://github.com/naqvis/containerregistry.cr/ (Library) ⏎ https://github.com/naqvis/opal (CLI - using above library)
<FromGitter> <meltheadorable> im not into MINSWAN, i miss the weird of why but i think crystal is fundamentally pragmatic in a way that cuts crystal off from being as quirky and poetic — crystal is a concession to reality
<FromGitter> <tenebrousedge> I think that's probably accurate
<FromGitter> <meltheadorable> i don’t think that’s a bad thing, but i think it’s possibly just like, fundamentally less inspiring
<FromGitter> <kniknoo> Awesome! I'm heading to lunch right now, but I wanna start a dialogue a bit later on for a working group about some potential ideas. Yeah... I've been imagining that a tutorial would involve a lot of the "other" saying "but that's just Ruby" and the narrator saying "yes, but..."
<FromGitter> <kniknoo> I've been doing a lot of philosophy lately so everything comes to mind as a classical dialogue. :D
<FromGitter> <meltheadorable> i briefly got it in my head to make a crystal version of shoes but it turns out that is…lets call it *very* hard
<FromGitter> <kniknoo> Yeah, would love to have a killer gui library. I have a feeling I'll be using game libraries until I'm more experienced.
<FromGitter> <absolutejam_gitlab> @naqvis what did you write the CLI parsing using?
<FromGitter> <absolutejam_gitlab> Just arg_parser?
<FromGitter> <absolutejam_gitlab> I wrote a CLI shard because I wasn't really happy with what's out there
<FromGitter> <absolutejam_gitlab> Overuse of macros and abstraction
<FromGitter> <naqvis> no, I used `mosop/cli`
<FromGitter> <absolutejam_gitlab> ^ is what I was avoiding
<FromGitter> <naqvis> I also thought of going with implementing own CLI library, but later just went with `cli`, as it does allow me to separate concerns into different files
<FromGitter> <naqvis> I prefer modular approach, instead of making spaghetti code 😆
<FromGitter> <naqvis> only if I had no choice, I would have went with porting excellent `Go` CLI library `Cobra` ⏎ https://github.com/spf13/cobra
<FromGitter> <absolutejam_gitlab> I started writing my CLI app in Go using cobra and took what I thought cobra did and made a version in crystal
<FromGitter> <naqvis> wow, great
<FromGitter> <absolutejam_gitlab> Granted I didn't dig too deep, but I essentially ported what I wanted / what I had so far from Go
<FromGitter> <naqvis> excellent job. Let me check yours
<FromGitter> <absolutejam_gitlab> There was a few out there `cli` and `admiral` but they all missed something, seem a bit indirect or had long overdue MRs
<FromGitter> <absolutejam_gitlab> I need to push it to GH later
<FromGitter> <absolutejam_gitlab> I've been working in my Gitlab but it looks like the shard indexed only look at GitHub
<FromGitter> <naqvis> yeah, I also evaluated them, but didn’t like their approach, or at least that wasn’t something I was expecting
_whitelogger has joined #crystal-lang
dingenskirchen has joined #crystal-lang
<FromGitter> <Blacksmoke16> @meltheadorable i got a draft of that article i was writing if you wanted to check it out?
<FromGitter> <meltheadorable> sure
<FromGitter> <Blacksmoke16> sesnt
bars0 has joined #crystal-lang
bars0 has quit [Client Quit]
bars0 has joined #crystal-lang
<FromGitter> <andrius> I have few JSON data structures with same keys/properties for some data, so in my class I include `JSON::Serializable` and `JSON::Serializable::Unmapped`; described common things with `property` and do use from_json. And a question: is there any elegant way to serialize extra properties in one-shot? Currently I just do dirty job and process json_unmapped hash
fyber has joined #crystal-lang
<FromGitter> <Blacksmoke16> why use unmapped in the first place?
bars0 has quit [Ping timeout: 246 seconds]
<FromGitter> <andrius> otherwise I miss other records
<FromGitter> <Blacksmoke16> got some example of what the json looks like?
<FromGitter> <andrius> sure, sec..
dingenskirchen has quit [Quit: dingenskirchen]
dingenskirchen has joined #crystal-lang
<fyber> What's the shortest way to get context.current_user.email if context.current_user is Nil? I tried (context.current_user.email || "None") but that doesn't work.
<FromGitter> <Blacksmoke16> ```if user = context.current_user ⏎ puts user.email ⏎ end``` [https://gitter.im/crystal-lang/crystal?at=5d3ca27f84bc7a717fd306de]
<FromGitter> <Blacksmoke16> ideally you would have properties for each
<FromGitter> <Blacksmoke16> but you could also prob just do like `Hash(String, String).from_json str`
<FromGitter> <Blacksmoke16> the former being the better approach imo
<FromGitter> <Blacksmoke16> also might be able to do something like
<fyber> Blacksmoke16: Thanks!
<FromGitter> <andrius> @Blacksmoke16 I have three types of data in packages: control headers (like action to execute, shared); actions data by purpose (shared, for example voice call related operations, audio stuff etc) and finally operations related data
<FromGitter> <Blacksmoke16> https://play.crystal-lang.org/#/r/7b02
<FromGitter> <Blacksmoke16> something like that then? ^
<FromGitter> <andrius> to_json is never problem, I have issues with opposite conversion and usage between classes, unless I strictly define `property` in a class. I do have arrays or hashes of hashes in some places
<FromGitter> <Blacksmoke16> oh i thought that was your issue, ` is there any elegant way to serialize extra properties in one-shot?`
<FromGitter> <andrius> sorry. From json
<FromGitter> <andrius> I also have this (specification for some action) https://play.crystal-lang.org/#/r/785u
<FromGitter> <Blacksmoke16> ideally you would have a property per key
<FromGitter> <Blacksmoke16> like define an object for each object in there
<FromGitter> <Blacksmoke16> then could do like
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3ca52f2136933a870035b0]
<FromGitter> <Blacksmoke16> if they're optional can make them nilable
<FromGitter> <andrius> Yes, I am thinking same way, thank you. Then when I do `from_json` (that's a data I receive from AMQP), I yet do not know what is that. Only after parse (and its based on keywords such as `service`, `action` and `operation/method`
<FromGitter> <Blacksmoke16> 😬
bars0 has joined #crystal-lang
<FromGitter> <andrius> Maybe then I shall render only these keywords and then remaining data?
bars0 has quit [Client Quit]
absolutejam4 has joined #crystal-lang
bars0 has joined #crystal-lang
<FromGitter> <andrius> Any comments on this @Blacksmoke16 ? https://play.crystal-lang.org/#/r/7b0h
<FromGitter> <Blacksmoke16> hmm
<FromGitter> <Blacksmoke16> how efficient do you want this to be
<FromGitter> <Blacksmoke16> another option is you use some custom `.from_json` method that parses the whole string then use a case to new up the correct object
<FromGitter> <Blacksmoke16> like
<FromGitter> <Blacksmoke16> ```code paste, see link``` [https://gitter.im/crystal-lang/crystal?at=5d3cad1f7e00fc4ace5dafd5]
<FromGitter> <Blacksmoke16> would have to parse the json twice tho
<FromGitter> <Blacksmoke16> would be super nice to have something to handle discriminator types like this tho, currently there just isnt a good way to do it
<FromGitter> <andrius> I want to be efficient as much as possible, it is heart of the system (basically it is a set of distributed micro-services handled by these action packages through MQ)
<FromGitter> <Blacksmoke16> its just as efficient as your solution
<FromGitter> <Blacksmoke16> but a bit cleaner
<FromGitter> <andrius> @Blacksmoke16 elegant way! :) thanks
<FromGitter> <Blacksmoke16> i wouldnt call it elegant but it works :P
bars0 has quit [Quit: leaving]
rohitpaulk has joined #crystal-lang
ht_ has quit [Quit: ht_]
rohitpaulk has quit [Ping timeout: 246 seconds]
<FromGitter> <absolutejam_gitlab> @Blacksmoke16 about swagger/openAPI
<FromGitter> <absolutejam_gitlab> Did you mean creating an openapi endpoint?
<FromGitter> <absolutejam_gitlab> I meant consuming a spec (json/yaml) and creating classes
<FromGitter> <Blacksmoke16> right, that spec would be in JSON
<FromGitter> <Blacksmoke16> so you could prob do that via that library and from_json
sorcus has quit [Ping timeout: 252 seconds]
<FromGitter> <absolutejam_gitlab> You mean https://github.com/icyleaf/swagger ?
<FromGitter> <Blacksmoke16> yea
dingenskirchen has quit [Read error: Connection reset by peer]
dingenskirchen1 has joined #crystal-lang
dingenskirchen1 has quit [Ping timeout: 248 seconds]
<FromGitter> <Blacksmoke16> @girng its abstract in the sense its defined there, but not implemented yet
<FromGitter> <Blacksmoke16> and sure if you manually write words to say that, then yea it would be known
<FromGitter> <Blacksmoke16> but words do not actually help you develop something
<FromGitter> <Blacksmoke16> hence `abstract`, to make the language help you
<FromGitter> <Blacksmoke16> IMO just keep with it and be open minded to these new concepts and ideas
<FromGitter> <kniknoo> This has been quite the exchange. :D I'm learning a lot, but I also feel like it's from a whole different paradigm to mine.
<FromGitter> <kniknoo> Thank you for all the thorough explanations and examples.
<FromGitter> <tenebrousedge> I would strive to avoid inheritance if possible
<FromGitter> <kniknoo> Do tell... That's how my head organizes at the moment.
<FromGitter> <absolutejam_gitlab> I remember seeing `abstract` in PHP and not knowing what it was
alex`` has quit [Ping timeout: 245 seconds]
<FromGitter> <absolutejam_gitlab> Because I'd only done Python and you basically just define the method with `pass` as the body
<FromGitter> <absolutejam_gitlab> or raise an exception
<FromGitter> <absolutejam_gitlab> But `abstract` basically says 'hey, if you're inheriting me, define this'. Much nicer.
<FromGitter> <tenebrousedge> maybe my Crystal experience will be different, but in Ruby inheritance seemed pretty unnecessary
<FromGitter> <Blacksmoke16> there isnt one pattern that handles all use cases
alex`` has joined #crystal-lang
<FromGitter> <kniknoo> My understanding from what I was listening to today is that an abstract was conceived for C++ but not explicitly labelled until Java. (As far as recognizable languages go). It makes way more sense coming at that from that POV than from a Rubyist POV.
<FromGitter> <Blacksmoke16> but understanding when to use each pattern is the most challenging part
<FromGitter> <absolutejam_gitlab> functional is master paradigm
<FromGitter> <tenebrousedge> function core, imperative shell
<FromGitter> <tenebrousedge> LISP would be perfect if the entire world was made out of LISP
<FromGitter> <kniknoo> Right now I'm doing my own Ruby wrapper for a game API (DragonRuby) so I'm say, building a wrapper for how a generic sprite works and then extending into a class for each type of sprite with an animation and sensation mixin when relevant.
<FromGitter> <Blacksmoke16> that seems sensible
<FromGitter> <kniknoo> LISP is on my list. I was learning about that a little bit the other day. They offer common LISP at exercism so I'll give it a shot.
<FromGitter> <tenebrousedge> https://xuanji.appspot.com/isicp/
<FromGitter> <tenebrousedge> I would also recommend reading either McCarthy's original paper or Graham's take on it
<FromGitter> <tenebrousedge> or both
<FromGitter> <kniknoo> So if you're saying it's functional, would it be a better choice than erlang for the sake of diving into a functional language?
<FromGitter> <tenebrousedge> maybe Elixir rather than Erlang
<FromGitter> <absolutejam_gitlab> Elixir <3
<FromGitter> <kniknoo> Okie doke. I've been hearing a bit about that one but I'll take a good look. Thanks!
<FromGitter> <tenebrousedge> Elixir is also on exercism
<FromGitter> <kniknoo> Just added the course as you said that. I like it so much I check there first for a consice description of the goal.
<FromGitter> <kniknoo> Yay I did my Hello World. :D Neat, I can't wait to jump into this tutorial.
moei has quit [Quit: Leaving...]
absolutejam4 has quit [Ping timeout: 245 seconds]
<FromGitter> <Daniel-Worrall> I got crystal to compile to my pi4 finally
<FromGitter> <Daniel-Worrall> Still struggling with getting it to do it through docker, but I guess I don't need to keep cross compiling now that I have a working crystal
rohitpaulk has joined #crystal-lang
<FromGitter> <tenebrousedge> how did you manage it?
<FromGitter> <dscottboggs_gitlab> awesome :D
<FromGitter> <Daniel-Worrall> turns out it's not working though. I just got excited seeing it spit out version etc
<FromGitter> <Daniel-Worrall> fails specs and can't build itself
rohitpaulk has quit [Ping timeout: 245 seconds]
<FromGitter> <Blacksmoke16> rip
<FromGitter> <dscottboggs_gitlab> ah
<FromGitter> <Daniel-Worrall> I'll share if I manage to get it working properly
_whitelogger has joined #crystal-lang
<FromGitter> <girng> is play.crystal-lang.com in this repo https://github.com/crystal-lang/crystal-website?
<FromGitter> <girng> most likely not, uses another site
<FromGitter> <Blacksmoke16> https://github.com/jhass/carc.in
alex`` has quit [Ping timeout: 245 seconds]
<FromGitter> <girng> thx
<FromGitter> <Blacksmoke16> got a near final draft of the DI article if anyone wants a sneak peak + give some feedback of if there's anything else youd like me to cover/clarify
<FromGitter> <tenebrousedge> Kai will meow at it!
<FromGitter> <Blacksmoke16> rgr moment, reading over it one last time and will pm it to you
<FromGitter> <dscottboggs_gitlab> ☝️ July 27, 2019 7:34 PM (https://gitter.im/crystal-lang/crystal?at=5d3cdf7ec356af25e03dd33c) no
laaron has joined #crystal-lang
laaron has quit [Client Quit]
<FromGitter> <Blacksmoke16> sent
laaron has joined #crystal-lang