ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
<FromGitter> <> If I have a macro method on an abstract struct, will they be inherited by children such that the `@type` is expanded for the concrete struct?
<FromGitter> <Blacksmoke16> If you put it in a macro inherited probably
<FromGitter> <> Ok.
<FromGitter> <> Probably not, but is there an existing library for outputting tabulated numbers, particularly floats? I would like to define an `#inspect` method for 4x4 matrices so it looks like: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ except: ... []
<FromGitter> <Blacksmoke16> id maybe look into
<FromGitter> <Blacksmoke16> dunno if its possible with it, but might be best bet with stdlib
<FromGitter> <> Hmm ok
<FromGitter> <> tablo looks very close to what I want. I would definitely need it to work for 1D StaticArray's though which it doesn't support...wonder if I can overload something.
<FromGitter> <Blacksmoke16> doesnt support how?
<FromGitter> <> docs mention it supporting only `Array` type, and 2D
<FromGitter> <Blacksmoke16> could call `.to_a` on it
<FromGitter> <Blacksmoke16> ofc that would allocate memory and stuff tho but might not be terrible just for UI output like that :shrug:
<FromGitter> <> Would have to convert it to `[][]` too
<FromGitter> <> err
<FromGitter> <> array of arrays
<FromGitter> <> I'll see. I don't need most of its features and need to see if I can opt out of them, PR it, or what
<FromGitter> <> like, don't want bars drawn, nor column/row labels
<FromGitter> <Blacksmoke16> problem is going come down to it storing the data as an ivar, which can't be a generic `Indexable`
ua_ has joined #crystal-lang
<FromGitter> <Blacksmoke16> generics might solve this but :shrug:
<FromGitter> <> Yeah it'll all be a learning experience. Been using my over-engineered Lisp math library for about a decade, and I'm always annoyed at how difficult it is to read tabular matrix data when debugging stuff.
<FromGitter> <Blacksmoke16> whats it look like now if you just do `pp @data`?
<FromGitter> <> Or rather, unformatted data period
<FromGitter> <Blacksmoke16> prob wouldn't be too bad
<FromGitter> <> Ah, I don't have a matrix type yet
<FromGitter> <> But in Lisp it looks like this, which is readable only because the PRNG seed made mostly the same digits to the left of the point: ⏎ ⏎ ```code paste, see link``` []
<FromGitter> <Blacksmoke16> ah `pp` by default prints a long list, not a 4x4 grid
<FromGitter> <> So those `rand` methods in the `ClassMethods` module...
<FromGitter> <> If I use inheritance, and stick those in an abstract parent struct, that isn't going to cause issues with eg; `.new` being undefined for the abstract type?
<FromGitter> <Blacksmoke16> if you're using inheritance now just define them as class methods in the parent and call it a day
<FromGitter> <Blacksmoke16> i dont think so?
<FromGitter> <> Ok. Inheritance does seem better by far
<FromGitter> <> Unsure if I will even need any mixins for the code I have so far anyway
<FromGitter> <Blacksmoke16> id test that tho, but it should be fine assuming each child has an argless constructor
<FromGitter> <> wait why?
<FromGitter> <> oh i see what you mean
<FromGitter> <> Yes, that's a given
<FromGitter> <> The one thing I'm unsure about is how to get my `T` type parameter to resolve for the topmost was passed into `include` before
<FromGitter> <> Ah.
<FromGitter> <> My intention is to only allow instances in this library to have Float64 for elements in the various containers, and I don't want type inference to permit anything else, so should be able to just make sure all contructors restrict their types, in addition to the above.
<FromGitter> <Blacksmoke16> then why do you need generics?
<FromGitter> <Blacksmoke16> yea just do that and dont use generics
<FromGitter> <> Probably don't anymore. I only needed it before because Indexable required a type parameter.
<FromGitter> <Blacksmoke16> generic inheritance can be kinda buggy
<FromGitter> <Blacksmoke16> well it would be `Indexable(Float64)`
<FromGitter> <> Yeah I was only using T because a lot of function signatures became too long with Float64 everywhere
ur5us has quit [Ping timeout: 252 seconds]
<FromGitter> <> iirc anyway
<FromGitter> <Blacksmoke16> :S
<FromGitter> <Blacksmoke16> i always find its better to be explicit
<FromGitter> <Blacksmoke16> even tho crystal allows you to not use them, i always do
<FromGitter> <Blacksmoke16> at least on publicly facing libs and APIs
<FromGitter> <> I do agree.
<FromGitter> <> It may be that I have to support Float32 in the future, I'm not sure. It depends how FFI works in Crystal
<FromGitter> <> It's a performance trap to use doubles on the GPU in most cases, so prob have to send them to the driver with single precision
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <> and also what opengl binding libraries expect I suppose
<FromGitter> <> The Scalar module was/is bothering me, and much moreso with inheritance
<FromGitter> <Blacksmoke16> how so?
<FromGitter> <Blacksmoke16> cant those 2 methods just live on the parent and not worry about it
<FromGitter> <> It is unrelated to any of the aggregate defines some functions for Float64 elements themselves
<FromGitter> <Blacksmoke16> if they're unrelated put em in a Utility namespace?
<FromGitter> <> I could, but how would I make it private to users...they're sort of just an implementation detail of some of the aggregate types' methods
<FromGitter> <Blacksmoke16> nodoc it
<FromGitter> <Blacksmoke16> wouldnt show up anywhere since you're not including/extending anything
<FromGitter> <> Sold
<FromGitter> <Blacksmoke16> not sure im a fan of the `=~` method name tho for a class method
<FromGitter> <> For a class name?
<FromGitter> <> oh
<FromGitter> <> I cannot read
<FromGitter> <Blacksmoke16> works better when its between instances, but a more english name might be better
<FromGitter> <> That was suggested in this chat quite a few days ago by someone, because 99% of use cases are going to be in the form of a binary operator, not the method call syntax...and can only use a whitelisted set of symbols there
<FromGitter> <> I'm not sold on it either, but
<FromGitter> <> `Origin.Vector3.nearly_equal? v1, v2` user code calling `Origin.Util.nearly_equal? f1, f2, rel_tol, abs_tol` internal code isn't too bad I suppose
<FromGitter> <Blacksmoke16> wait
<FromGitter> <Blacksmoke16> why not `v1 =~ v2`
<FromGitter> <Blacksmoke16> or is that how it was?
<FromGitter> <> You just said you didn't like that, and neither do I tbh
<FromGitter> <> Or did I misunderstand?
<FromGitter> <Blacksmoke16> oh sorry no, looking at the code
<FromGitter> <Blacksmoke16> it looked like it was used as `Origin::Scalar.=~ v1, v2`
<FromGitter> <Blacksmoke16> due to the `extend self`
<FromGitter> <> It is internally, because you cannot use the method call notation without a module prefix
<FromGitter> <> The extend self was needed too
<FromGitter> <Blacksmoke16> id still use `nearly_equal` but have `def =~` instance method use that internally
<FromGitter> <Blacksmoke16> id also look into `def ===`
<FromGitter> <Blacksmoke16> which is used for case equality, which could forward to `=~`
<FromGitter> <> This topic is both complicated and subjective. I left something out.
<FromGitter> <> You pretty much never want to use `==` on two floats, let alone 2 aggregates of floats, so `==` calls out to `=~` incase the user didn't use the more explicit approximation method, which would clearly be an error. The problem is, `==` must take exactly 1 receiver and 1 argument, so the defaults for `rel_tol` and `abs_tol` *must* be used in that case.
<FromGitter> <> Which is also an error, albeit a lesser one
<FromGitter> <> So there is no good solution that I know of
<FromGitter> <> The reason for using the `=~` symbol over `==` to begin with is because of this...the parser treats all `=` suffixed method names as setters, and errors on arity overloading away from that.
<FromGitter> <> I think we discussed this already though :)
<FromGitter> <Blacksmoke16> yea, i figured it was because `=~` represents matches
<FromGitter> <> I personally don't think an operator should be used for a variadic function, and also because `=~` doesn't mean the usual to Crystal programmers.
<FromGitter> <> SO I will more than likely move to `nearly_equals?`
ur5us has joined #crystal-lang
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <> I might even go as far as to `def ==; `{{ raise ... }; end` for vector types.
<FromGitter> <> err with an `other` in there somewhere :)
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
<FromGitter> <> Hmm, so with inheritance those pesky class methods are giving me issues again
<FromGitter> <Blacksmoke16> Oh?
<FromGitter> <> It's saying that a .new method with 2 arguments doesn't exist when calling .rand...but i can call .new manually with 2 args...i haven't quite figured it out yet...
<FromGitter> <Blacksmoke16> Can you push up an example
<FromGitter> <> done
<FromGitter> <> Shoved everything in 1 file for now, sorry if it's hard to read like that
<FromGitter> <> I bet those constantly are eagerly evaluated before inheritance
<FromGitter> <> I dunno though
<FromGitter> <Blacksmoke16> is the idea that they're a singleton?
<FromGitter> <> what is they?
<FromGitter> <Blacksmoke16> i mean if those constants are just meant to an easy way to get that type in a specific state just do like
<FromGitter> <Blacksmoke16> ```code paste, see link``` []
<FromGitter> <Blacksmoke16> but if they're expected to be a singleton. I.e. each call to `V2::ZERO` returns the same instance then you could use a lazily initialized class getter
<FromGitter> <> They are constants to prevent allocation during tight loops when comparing instances against common values, etc
<FromGitter> <Blacksmoke16> so they're expected to return the same instance everytime
<FromGitter> <> Yes, their values are expected to be inlined into the machine code.
<FromGitter> <> THey exist purely for having stable values that cannot change or needing to be allocated
<FromGitter> <Blacksmoke16> moreso mean is this correct: `V2::ZERO.object_id == V2::ZERO.object_id`
<FromGitter> <Blacksmoke16> nvm, these are structs
<FromGitter> <> assuming object ID is an address in memory, then definitely, yes
<FromGitter> <Blacksmoke16> I'd just do this then
<FromGitter> <Blacksmoke16> ``` macro inherited ⏎ ZERO = new 0.0 ⏎ ONE = new 1.0 ⏎ end``` []
<FromGitter> <Blacksmoke16> so they get defined on each child
<FromGitter> <> That was my guess, but didn't want to run into similar issues as before
<FromGitter> <Blacksmoke16> or could just duplicate the constants :shrug:
<FromGitter> <> Next issue (pushed)
<FromGitter> <> Oh there is no instance
<FromGitter> <Blacksmoke16> `def self.`
<FromGitter> <Blacksmoke16> yea
<FromGitter> <> I'm starting to get the hang of this
<FromGitter> <> In Lisp, everything is dynamic, but some implementations have gradual typing for some level of static type checking...but not this nice.
<FromGitter> <> My only concern with Crystal is how awful the context of errors is, and the stacktraces
<FromGitter> <> Maybe it just takes some time getting used to...
<FromGitter> <Blacksmoke16> what about them?
<FromGitter> <> Well, for example, if I write a macro that internally calls some 3rd party library macro, and 6 months later i mess up the input to my macro and I'm left with an error message and the first call site is internals of the 3rd party library's macro, not the call site where the error originated
<FromGitter> <> nested macro issues mostly
<FromGitter> <Blacksmoke16> you know about `--error-trace`?
<FromGitter> <Blacksmoke16> also yes
<FromGitter> <> and also, this constant error wasn't completely intuitive why it was occuring
<FromGitter> <> stuff like that
<FromGitter> <> Yeah I do
<FromGitter> <> Oh I'll keep an eye on them, thanks.
<FromGitter> <Blacksmoke16> its what makes the athena compile time errors not super great :/
<FromGitter> <> Anyway. I would say inheritance was a better fit here for sure. But I'm glad I got to learn mixins and why they weren't great here...I think the module system is pretty nifty :)
<FromGitter> <Blacksmoke16> at least what the error points to in the trace
<FromGitter> <Blacksmoke16> yea they deff have their uses
<FromGitter> <> My editor mangles the indentation that it's practically unreadable when I have a macro in a nested module, which is why I made them all toplevel forms with `::` separators...I dunno whats wrong with the crystal vim plugin :/
<FromGitter> <Blacksmoke16> :shrug: i use sublime
<FromGitter> <> Is vscode or atom the more popular solution for crystal? i never liked them much over vim or emacs, but if its a better experience i might try one of them again
<FromGitter> <Blacksmoke16> vscode is deff the most popular
<FromGitter> <> cool
<FromGitter> <Blacksmoke16> esp when setup with one of those lsp or something server
<FromGitter> <Blacksmoke16> crystalline or something like that iirc
<FromGitter> <> that's what i'm using for vim
<FromGitter> <Blacksmoke16> gotcha
<FromGitter> <> Alright thanks for the feedback. I'll clean this up and work on matrices tomorrow
<FromGitter> <Blacksmoke16> 👍
ur5us has quit [Remote host closed the connection]
ur5us has joined #crystal-lang
ur5us has quit [Ping timeout: 252 seconds]
ur5us has joined #crystal-lang
ur5us has quit [Ping timeout: 240 seconds]
iskra has quit [Ping timeout: 252 seconds]
iskra has joined #crystal-lang
hightower2 has joined #crystal-lang
ua_ has quit [Read error: Connection reset by peer]
<FromGitter> <> Much better Crystal experience using vscode (using the Vim extension of course :))
<FromGitter> <> I do have a question if anyone else here uses vscode
<FromGitter> <> I am wondering what it's trying to tell me when some method parameters are rendering with an italic font:
<FromGitter> <pyrsmk> I don't think it's trying to tell anything interesting; I worked on a VSCode theme because I found that many themes weren't suited well with Crystal; anyway, it seems that (currently) the syntax highlighting scheme for Crystal in VSCode isn't that good so some parts can have quirks on screen, depending on how you're formating your code
<FromGitter> <> @pyrsmk: Yes, I've noticed :/
<FromGitter> <pyrsmk> this surely comes from the fact that Crystal is a very flexible language, so it seems complicated to have a good syntax highlighting engine for it... just my opinion, maybe somebody will prove me wrong
<FromGitter> <pyrsmk> when we're used to it, that's not really an issue :p
<FromGitter> <> Yeah, I was using neovim previously, which uses tree-sitter for parsing the syntax, and didn't notice anything wrong ever. Oh, well...
<FromGitter> <pyrsmk> this is only a thing to fix for the community :) maybe I will get my hand on this at some point..
<FromGitter> <> In other news, I've been using Crystal for a week now, and I can honestly say I've never had this much fun programming. The language seems like just the right balance between simplicity and power. I don't think I can say the same about any of the two dozen or so languages I've used before over two decades. So thank you to the developers and this wonderful community for making Crystal so great, and
<FromGitter> ... continuing to improve it!
hightower2 has quit [Ping timeout: 265 seconds]
<FromGitter> <> @Blacksmoke16: You must have an ultra wide monitor or something. Hard to read your source files :)
<FromGitter> <Blacksmoke16> 1440p :P
<FromGitter> <> 319 columns in the first file I tried to read :)
<FromGitter> <Blacksmoke16> haha which one is that?
<FromGitter> <> athena/
<FromGitter> <> I just remember you saying you don't like to scroil horizontally :)
<FromGitter> <Blacksmoke16> *most* of the time, i could prob chop some macro stuff down but im not too bothered
<FromGitter> <Blacksmoke16> iirc the macro stuff is hard to format as well
<FromGitter> <Blacksmoke16> which prob is part of the reason i didnt worry about it too much
<FromGitter> <> If I have a struct `A::B::C`, in instance methods, is there a more concise way to refer to module-level macros located in `A::B` without full qualification or an alias?
<FromGitter> <Blacksmoke16> prob could just do `B.some_method`
<FromGitter> <> Oh nice
<FromGitter> <> Does relative take precedence over absolute?
<FromGitter> <> Like if there happened to be a root module named B?
<FromGitter> <Blacksmoke16> iirc it would find the closest one
<FromGitter> <> Ok thanks
<FromGitter> <> There is one big thing I don't like about putting all requires in the main file
<FromGitter> <Blacksmoke16> hm? that shouldnt have anything to do with it
<FromGitter> <> When I'm working in some other file, both vim and vscode do semantic analysis on save etc, and report errors if things being referenced aren't included in that file. It really gets distracting trying to mentally separate real problems from these errors.
<FromGitter> <Blacksmoke16> ah
<FromGitter> <> I don't think anything acceptable can be done about that though :/
<FromGitter> <> If I mark an abstract type as `:nodoc:`, the concrete type has a list of inherited methods, with 404 links. Is there any way possible to inline the docs for inherited nodoc methods into the concrete type's docs?
notzmv has quit [Ping timeout: 276 seconds]
Flipez9 has joined #crystal-lang
Flipez has quit [Read error: Connection reset by peer]
Flipez9 is now known as Flipez
Flipez has quit [Changing host]
Flipez has joined #crystal-lang
<FromGitter> <asterite> I don't think so. But I would file a bug for that, there shouldn't be links to those methods if they aren't visible
<FromGitter> <> Thanks. I'll wait for my distro to update to 1.1.0 to be sure first.
<FromGitter> <> @Blacksmoke16: I have a question about your code style. You said that it is considered good practice to name types according to their directory hierarchy. I see several places where you don't do this. Is there any particular reason why you ignored this convention?
<FromGitter> <Blacksmoke16> got an example?
<FromGitter> <> for example athena/view/ -> Athena::Routing::View(T)
<FromGitter> <Blacksmoke16> right, its in the `View` namespace so its in the `view` folder?
<FromGitter> <Blacksmoke16> oh, you can use another type as a namespace
<FromGitter> <Blacksmoke16> it doesnt have to be a module
<FromGitter> <> Oh maybe I'm confused then, because there is an `Athena::Routing` namespace and a `src/routing/`
<FromGitter> <Blacksmoke16> that repo is maybe a it of a bad example as there technically isn't a dedicated routing component, and made `athena` repo itself both the thing that defines that component and the thing that ties everything together into the framework
<FromGitter> <Blacksmoke16> mainly since the router is so tightly coupled to the framework itself
<FromGitter> <> I see, makes sense.
<FromGitter> <Blacksmoke16> yea, are always exceptions :P
<FromGitter> <> 🙌
hightower2 has joined #crystal-lang
notzmv has joined #crystal-lang
<FromGitter> <franciscoadasme> hey everyone, does anyone knows is this intended behavior regarding return type restrictions?, it seems that `Nil` is ignored when checking for the return type ⏎ ⏎ ```code paste, see link``` []
<FromGitter> <> Nil is a special return type that overrides all branchs' return types so you don't have to specify `return nil` everywhere.
<FromGitter> <> But I don't see Nil as a return type annotation here, so I'll leave it to the experts to answer.
<raz> grkek: grip-spec needs fixing!
<FromGitter> <Blacksmoke16> Abstract def return types allow the implementation to be more specific
fifr has quit [Ping timeout: 252 seconds]
<FromGitter> <> How does that work with a union?
fifr has joined #crystal-lang
f1refly has quit [Remote host closed the connection]
<FromGitter> <Blacksmoke16> not as i'd expect
f1refly has joined #crystal-lang
<FromGitter> <> Even more confusing:
<hightower2> mjfiano: in your example you need 1u32, not just 1 as return value
<FromGitter> <> Ah, right
<FromGitter> <Blacksmoke16> yea that ones expected atm
<FromGitter> <Blacksmoke16> sec
<FromGitter> <> What is going on here? ⏎ ⏎ ```code paste, see link``` []
<hightower2> mjfiano: macros are compile-time. So @def.args == [a : Float64], and it thinks you're trying to re-define a
<FromGitter> <Blacksmoke16> Yes ^ that method returns an array of Arg
<FromGitter> <> Ok, and hightower2, that link is invalid i think
Stephie- has joined #crystal-lang
Vexatos has joined #crystal-lang
Stephie has quit [Quit: Fuck this shit, I'm out!]
Vexatos_ has quit [Quit: Client Quit]
<FromGitter> <> What would be the best way to fill a static array with all of the same value?
<FromGitter> <> manually loop, or some method exists?
<FromGitter> <Blacksmoke16>
<FromGitter> <> It is already allocated
<FromGitter> <Blacksmoke16> this one then
<FromGitter> <> Thanks
<FromGitter> <> Hmm, I have an abstract class that I want to define some overloads of the same method in, and have the concrete subtype define additional overloads, not replace them. What is the solution here?
<FromGitter> <Blacksmoke16> prob just do it
<FromGitter> <Blacksmoke16> assuming the overloads are all unique it should just work
<FromGitter> <> I have an abstract struct with 1 initialize method. I subclass it, and define an overloaded initialize, and calls to the first method say it doesnt exist
<FromGitter> <Blacksmoke16> ah, for a constructor it works a bit diff
<FromGitter> <Blacksmoke16> prob just copy it and call `super`
<FromGitter> <Blacksmoke16> or maybe you just want to override `.new`
Stephie- is now known as Stephie
<FromGitter> <> ``` def initialize(value : Float64 = 0.0) ⏎ super ⏎ end``` ⏎ ⏎ Like this? Seems to work, but I have no idea how that is interpreted to do that. []
<FromGitter> <Blacksmoke16> same as `super value`
<FromGitter> <> Ah so super is the super method not the super type?
<FromGitter> <Blacksmoke16> yea
<FromGitter> <Blacksmoke16> calls the parents implementation of it
<FromGitter> <> 🤦‍♂️
<FromGitter> <> Better idea
<FromGitter> <> No need to add it to the child types and call super
<FromGitter> <> Just put the parent's methods in `macro inherited` and it seems to get the super and current methods
<FromGitter> <> No duplicated code
<FromGitter> <Blacksmoke16> that works too
hightower3 has joined #crystal-lang
hightower2 has quit [Ping timeout: 240 seconds]
<FromGitter> <Blacksmoke16> TIL that MIME type and MIME mean diff things
<FromGitter> <YusufCakan> when i try to install an extension for crsytal in vscode. There are multiple which come up. Its not clear which one is the best or the latest. Which extension would you recomment.
<FromGitter> <YusufCakan> *recommend
<FromGitter> <> I would recommend the official one. It was odd to me how the third-party extension had more installs
<FromGitter> <YusufCakan> which one is the official one
<FromGitter> <> Well it's the one from the Crystal Language Tools organization, which has an official ring to it, but unsure how official it actually is (it corresponds to the GitHub organization of the same name)
<FromGitter> <YusufCakan> ok thanks.