ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
<FromGitter> <Blacksmoke16> yea idt you can do that
<FromGitter> <> i'm not sure how that'd work as a method
<FromGitter> <Blacksmoke16> wont be able to iterate the ivars within a method, and you of cant create a method while you're in a method
<FromGitter> <Blacksmoke16> just manually create the constructor
<FromGitter> <Blacksmoke16> or use a macro to generate it if you really want
<FromGitter> <> yeah... a macro doesn't really give much in this case then :)
<FromGitter> <Blacksmoke16> you could do like `def_constructor nomad_base_url : URI, ...`
<FromGitter> <> sure, but `def initialize(@nomad_base_url : URI)` is pretty much the same and less confusing
<FromGitter> <Blacksmoke16> exactly :)
<FromGitter> <Blacksmoke16> this is a case of macro over complicating something that is simple
<FromGitter> <> i'm mostly exploring macros at this point, so was just wondering how recursive it can get :)
<FromGitter> <Blacksmoke16> I *think* there's away you can get this to work, but it's not recommended, give me a sec
<FromGitter> <> i could generate Nomad::Config when creating Common::Config though, that should cause less problems i think
<FromGitter> <Blacksmoke16> ```code paste, see link``` []
<FromGitter> <> just trying to reduce the number of places to change when i change options, while giving sub-commands only the minimum set of options they need for easier testing and invocation, while avoiding accidental dependencies
<FromGitter> <> oh, that is kinda cool :)
<FromGitter> <> didn't know _ => _ was a thing
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <Blacksmoke16> i will say, yes it *works* but im not a fan at all of this mutable concept approach
<FromGitter> <Blacksmoke16> imo it still over complicates the process of just defining a constructor manually
<FromGitter> <> yeah
<FromGitter> <> i'll try one other idea i just had though
<FromGitter> <Blacksmoke16> Mmk
<FromGitter> <> i think it'd be beneficial to encode the hierarchy in a single pass instead of throwing it all over the code
<FromGitter> <> not sure if i'll like the result, but gotta try it anyway :)
<FromGitter> <Blacksmoke16> Fwiw, constructors are inherited
<FromGitter> <> yeah
<FromGitter> <Blacksmoke16> 👌
<FromGitter> <> atm i have for example a server that needs options [a,b,c], and it calls sub-components that require options [b] or [a,c], or [c,d] etc...
<FromGitter> <> each sub-component can be called without the server, in which case you would only need to pass their specific options
<FromGitter> <> so inheritance is a bit weird there...
<FromGitter> <Blacksmoke16> Are these like config values, or like unique types
<FromGitter> <> mostly configs
<FromGitter> <> should be immutable after initial parsing
<FromGitter> <Blacksmoke16> Have you considered passing in a single config obj versus specific values?
<FromGitter> <> yeah
<FromGitter> <> but that means i'd need to make the value types either optional, or use totally wrong default values...
<FromGitter> <Blacksmoke16> How so?
<FromGitter> <> or the user has to pass 50 options even if that command would only need 2 or so
<FromGitter> <Blacksmoke16> How are the values provided?
<FromGitter> <> either config file, cli flags, url params, default values, or env vars
<FromGitter> <Blacksmoke16> Gotcha
<FromGitter> <> here's an older version of the actual code:
<FromGitter> <> so that pass-the-full config approach is what i had before, and it sucked :)
<FromGitter> <> when you wanna run db migrations, all you need is the db url, for example
<FromGitter> <> but it will fail for not finding a github token...
<FromGitter> <Blacksmoke16> You could use lazy getters maybe
<FromGitter> <> at that point it may fail at runtime, which also sucks
<FromGitter> <Blacksmoke16> Only would try to load when called, but would raise if not available
<FromGitter> <Blacksmoke16> Or really, maybe even getter! Would be sufficient here
<FromGitter> <> anw, i gotta get some sleep, thanks for the feedback :)
<FromGitter> <Blacksmoke16> o/
ua_ has quit [Ping timeout: 265 seconds]
ua_ has joined #crystal-lang
ua_ has quit [Ping timeout: 268 seconds]
lucf117 has quit [Quit: Leaving]
ua_ has joined #crystal-lang
<FromGitter> <> @didactic-drunk: should we add Process.fork to crystal-posix? @kevinsjoberg was asking about lack of `Process.fork`.
f1reflyylmao has joined #crystal-lang
f1refly has quit [Ping timeout: 268 seconds]
f1reflyylmao is now known as f1refly
<FromGitter> <> I'm trying to solve a visibility issue. ⏎ I have private class method `` at the module level in one file, and in another file I have a struct defined in the same module. I would like some of the instance methods of the struct to be able to use the private foo method at the module level, but I cannot fully qualify it, and it is not part of the struct so I'm not sure if this is possible. I'm
<FromGitter> ... trying to write a file of private helper methods that are used in several other files/structs
<FromGitter> <> Cancel that. I seemed to have figured out the right incantation to extend the module with private methods according to `crystal doc`.
<kevinsjoberg> @postmodern, great idea!
miihael has joined #crystal-lang
miihael has quit [Quit: Client closed]
<FromGitter> <Blacksmoke16> could you just make it protected
<FromGitter> <> @didactic-drunk @kevinsjoberg hmm nevermind, looks like `Process.fork` does exist but isn't documented / part of the private API.
<FromGitter> <> @Blacksmoke16: Maybe, though I'm not sure what that means for module methods...the docs talk about instances. I found a way with private though.
<FromGitter> <Blacksmoke16>
<FromGitter> <> @Blacksmoke16: Interesting. I did something like this:
<FromGitter> <> Mine probably doesn't do exactly what I expect. ⏎ ⏎ Also, stupid question: I've never seen the double colon syntax for module name as in your example...where is this documented?
<FromGitter> <Blacksmoke16> It's equivalent to creating two modules and nesting them
<FromGitter> <> Is there a convention when naming methods that side-effect their instance? Some languages use a `!` suffix.
<FromGitter> <naqvis> yes, Crystal follows same conventions. methods ending with bang represents inline mutation. stdlib have few of them
<FromGitter> <> Thank you
<FromGitter> <naqvis> similarly methods returning bool are usually end with `?`
<FromGitter> <Blacksmoke16> ! Can also represent methods that raise, while ? Returns nil
<FromGitter> <Blacksmoke16> But I see more of like .foo Versus .foo!
<FromGitter> <> FYI: This convention is very old, derived from Scheme (a Lisp)
<FromGitter> <> I think I decided on classes over structs. pass-by-value is sort of convoluting my API already.
<FromGitter> <> re: yesterday's discussion
<FromGitter> <Blacksmoke16> 👍 usually the suggested approach is just use classes to start
<FromGitter> <Blacksmoke16> then can fix bottlenecks as needed, OR if the obj is for immutable and small
<FromGitter> <> Yeah I chose structs first because this is ultimately going to be for high performance math routines used in math visualization animations
<FromGitter> <> But that was a mistake...for now
<FromGitter> <Blacksmoke16> are you created a lot of objects in a loop or something?
<FromGitter> <Blacksmoke16> that would prob be noticable diff
<FromGitter> <> The math routines will typically have 2 different methods for that allocates, and one that, using classes should be fine, and I can always mutate a pre-allocated object before the loop
<FromGitter> <> I mean I can always mutate inside the loop, a pre-existing object
<FromGitter> <> My Lisp code I'd like to replace is over-optimized. I create temporary objects at init time and never allocate at runtime...heh
<FromGitter> <Blacksmoke16> 👍 sounds like a plan
<FromGitter> <> One thing that I still haven't gotten used to is blocks. It's very strange how methods are not first-class functions, coming from Lisp and a bit of Rust.
<FromGitter> <Blacksmoke16> Hm?
<FromGitter> <> top-level variables being inaccessible in methods, intentionally restricting closures in favor of a separate construct (blocks).
<FromGitter> <> I'm just not sure why that is the case compared to first-class functions. Maybe I don't fully understand blocks
<FromGitter> <Blacksmoke16> Have you read about procs?
<FromGitter> <> Yeah, and I don't know how that differs from a lambda/anonymous function in other languages.
<FromGitter> <Blacksmoke16> It's the same concept
<FromGitter> <Blacksmoke16> A method with a block is similar to a method that accepts an anonymous callback function
<FromGitter> <>'s just confusing me because lambda calculus is so simple and doesn't require any of that to do the same things.
<FromGitter> <Blacksmoke16> :shrug:
<FromGitter> <> ```code paste, see link``` ⏎ ⏎ Interestingly, this can be called as a fully-qualified method: `Origin.=~(a, b, rel_tol: c, abs_tol: d)`, or a binary operator without qualification if the defaults are sufficient: `a =~ b`. I'm not sure why the former requires qualification. []
<FromGitter> <> I think mayhbe my code is wrong and it is calling the wrong overload
<FromGitter> <> No it is calling the same method in both cases.
<FromGitter> <> I think everything is fine actually. If anyone has any suggestions for improvements on this snippet, I'd appreciate it:
lucf117 has joined #crystal-lang
<FromGitter> <Blacksmoke16> you can just do `property x : Float64, y : Float64`
<FromGitter> <Blacksmoke16> save you 2 lines :p
<FromGitter> <> Oh thanks
<FromGitter> <> I just found what I think is a very minor compiler bug
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <> I tried to see if I could overload `==` instead of `=~`, and the error message says I'm trying to define a setter with more than 1 parameter. I know why this is the case, but maybe a special-cased error for arity-overloading == should exist
<FromGitter> <Blacksmoke16> pretty sure thats moreso an accepted limitation
<FromGitter> <Blacksmoke16> related
<FromGitter> <> Odd
<FromGitter> <> I would expect <, > to be symmetrical with <=, <=.
<FromGitter> <> err <=, >=
<FromGitter> <Blacksmoke16> right, hence the bug :p
<FromGitter> <Blacksmoke16> which would be more likely to make the others only 1 arg as well
<FromGitter> <> Has a stropping feature been shut down yet, like Nim?
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <> Stropping lets the user re-use reserved keywords in a different context, usually by escaping the symbol in some way. In Nim for example, you can define an `==` function by wrapping it in backticks
<FromGitter> <Blacksmoke16> ah no, the Crystal way would use a diff word
<FromGitter> <> Ah k
<FromGitter> <> I suppose I would have to manually define my property methods if I were to use a static array as storage and I wanted to map those x, y names to indices?
<FromGitter> <Blacksmoke16> im pretty sure that offers no benefit over a struct with getters
<FromGitter> <> I'm using a class, and for different vector lengths, and especially matrices, it'd allow me to write iteration macros to define a lot of routines for all shapes simultaneously
<FromGitter> <Blacksmoke16> you meant to use a static array as a property within the class?
<FromGitter> <Blacksmoke16> mean*
<FromGitter> <> Yep
<FromGitter> <Blacksmoke16> cant you also just store a struct in the class?
<FromGitter> <Blacksmoke16> be easier than knowing what index is what
<FromGitter> <> Are you familiar with GLSL?
<FromGitter> <Blacksmoke16> nope
<FromGitter> <> mfiano ( what's your question
<FromGitter> <> I want to implement "swizzling", with a macro. That means, for a 2-dimensional vector that has an X and Y property, a macro would generate permutations of the accessors: x, y, xx, yy, yx
<FromGitter> <> I have done such in Nim before. Just trying to figure out the best way with Crystal
<FromGitter> <> mfiano ( well if your question can be more generally rephrased as "generate GLSL at compile time", here you go:
<FromGitter> <> No no
<FromGitter> <> but like... why doesnt it solve your problem
<FromGitter> <> This is not for generating GLSL in any way. It is for CPU computations. I was just pointing at the feature in GLSL
<FromGitter> <> mfiano ( ok nevermind. then you can just use macros, yeah
<FromGitter> <> i would suggest to still use a struct as storage, not a static array
<FromGitter> <> I would like to use classes, containing an array, in order to support chained methods (mutations that return `self`)
<FromGitter> <> pass by value would prevent that
<FromGitter> <Blacksmoke16> static arrays are also pass by value
<FromGitter> <> Right, but I wouldn't be returning them
<FromGitter> <Blacksmoke16> so then just use a struct within the class and return `self` as you would?
<FromGitter> <> you can use classes but they're too heavy if you want to store many vectors
<FromGitter> <> methods on structs can be chained but they're always by-copy, that is true
<FromGitter> <> Yeah, I want the user-facing type to be a class for this reason. The storage is up for debate
<FromGitter> <> internal storage*
<FromGitter> <> oprypin ( Are you a game developer? Your github looks interesting
<FromGitter> <> mfiano ( i really want to make a game but i'm not good at it
<FromGitter> <> I worked on a game from scratch for about 10 years and never finished. It takes a lot of time, and code is the least amount of time, which...says a lot
<FromGitter> <> These days I pretty much have given up and just like to write math visualizations; games without the game-y part :)
<FromGitter> <> oh my
<FromGitter> <> Do you have a repo that sets up/explains the embedded crystal shader stuff?
<FromGitter> <> mm definitely no explanation of it. i just tore these out of my private repository
<FromGitter> <> Ah ok
<FromGitter> <> it's just plain though. and you can ask questions if it's unclear
<FromGitter> <> When am I required to `require` modules from the stdlib. The ones I've used so far (`Math` and `Random`) seem to be accessible without importing them.
<FromGitter> <Blacksmoke16> only some of the more non-standard ones like json, yaml, uuid, option_parser etc
<FromGitter> <> Ok. It's nice the prelude includes useful things and I don't have to keep importing the same stuff everywhere
<FromGitter> <Blacksmoke16> mhm
<FromGitter> <Blacksmoke16> reall you'd only have to include them once
<FromGitter> <Blacksmoke16> its not like JS or something where you need the imports in every file
<FromGitter> <> Yeah I meant like for each project I am used to including a bunch of common stuff from the language core
<FromGitter> <> There's probably multiple things wrong here. Help? :)
<FromGitter> <Blacksmoke16>
<FromGitter> <> :think
<FromGitter> <> Well I had an array for a reason. I will need to take sub slices of it in more complicated functions
<FromGitter> <Blacksmoke16> but regarding you're actual issue, you're calling the argless constructor, which would leave `@data` uninitialized, hence the error
<FromGitter> <Blacksmoke16> your*
<FromGitter> <Blacksmoke16> `{x, y}` would actually be of type `Tuple(Float64, Float64)`
ur5us has joined #crystal-lang
<FromGitter> <Blacksmoke16> is the idea that index 0 is x and index 1 is y?
<FromGitter> <> Yes
<FromGitter> <Blacksmoke16>
<FromGitter> <Blacksmoke16> i still dont understand why you want the static array tho
<FromGitter> <> It will matter more for matrices tbh, where I'm processing individual rows or columns at a time.
<FromGitter> <Blacksmoke16> how would you model that with static arrays? like 2 array or something?
<FromGitter> <> No idea how it maps to Crystal yet. Here is how I did the same in Nim with a static array as storage (and was able to re-use a lot of code because of it):
<FromGitter> <Blacksmoke16> 404
<FromGitter> <> 1 sec
<FromGitter> <> fixed
<FromGitter> <Blacksmoke16> hmm
hightower3 has quit [Ping timeout: 252 seconds]
<FromGitter> <> To answer your question, no, it'd be a single flat array
<FromGitter> <> It makes some things easy, like extracting a column from a matrix to a vector:
<FromGitter> <Blacksmoke16> are there only ever going to be like 2..4 types?
<FromGitter> <Blacksmoke16> idk, nvm, deff not familiar with this stuff
<FromGitter> <> 2-4 for vectors.
<FromGitter> <> The matrices I need are the same sizes squared: 4, 9, 16
<FromGitter> <> which means rows x cols
<FromGitter> <> But, np. I'm almost ready to take a break for today
ur5us has quit [Ping timeout: 255 seconds]
<FromGitter> <> oprypin ( Were you talking about size or instruction overhead wrt classes vs structs?