ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
[jamez] has joined #crystal-lang
<FromGitter> <> Can I define my own operators using Unicode glyphs?
<FromGitter> <Blacksmoke16> Probably
<FromGitter> <Blacksmoke16> Maybe
<FromGitter> <Blacksmoke16> Have to try it :p
<FromGitter> <> I did, and I got a big error :)
<FromGitter> <> Come to think of it, it's probably hard-coded in the compiler, since it doesn't let you specify precedence
<FromGitter> <Blacksmoke16> :shrug:
hexreel has joined #crystal-lang
szutt has joined #crystal-lang
ur5us has quit [Ping timeout: 255 seconds]
maria_elis has quit [Ping timeout: 268 seconds]
maria_elis has joined #crystal-lang
<FromGitter> <HertzDevil> `Number` is real by definition
<FromGitter> <HertzDevil> `Complex` isn't a subclass of it
Nik- has joined #crystal-lang
Nik- has quit [Quit: Textual IRC Client:]
ur5us has joined #crystal-lang
sorcus has quit [Quit: WeeChat 3.2]
sorcus has joined #crystal-lang
ur5us has quit [Ping timeout: 240 seconds]
ur5us has joined #crystal-lang
ur5us has quit [Ping timeout: 255 seconds]
<hightower2> What would it entail to make crystal and crystal i share variables, when crystal i would be running inside a crystal program like an interpreter for script files loaded in runtime? And would this, as a side effect, also enable having shared libs with crystal?
<hightower2> Is it hard, or not doable given current architecture?
<straight-shoota> You mean using interpreted Crystal as a kind of scripting engine from a Crystal program?
<straight-shoota> I'm not sure how difficult it would be to share data with the embedded interpreter context.
<straight-shoota> But should be doable
<straight-shoota> I don't see any relation to shared libraries, though. The hassle with shared libs is Crystal's stdlib runtime.
<hightower2> aha ok, thanks. I thought the issues were (also) with gc
<straight-shoota> GC is part of the runtime, yes
hightower2 has quit [Ping timeout: 268 seconds]
sagax has quit [Ping timeout: 258 seconds]
hightower2 has joined #crystal-lang
<hightower2> Looks like wasn't updated to list 1.1.0 as latest release
ua__ has joined #crystal-lang
ua_ has quit [Ping timeout: 255 seconds]
<FromGitter> <> What does it mean to have an instance method at the module level, if the module isn't a partial type? Can this method be invoked somehow?
<FromGitter> <Blacksmoke16> this goes back to `include` and `extend`
<FromGitter> <> Right, so it's only usable when the type is completed with one of those?
<FromGitter> <> and not from the partial type
<FromGitter> <Blacksmoke16> yea, at that point its a mixin not meant to be used on its own
<FromGitter> <Blacksmoke16> you *can* do `extend self` that allows it to be a mixin, but still call methods on the module itself
<FromGitter> <> I only ask because a class method at the module level can be invoked without mixing it
<FromGitter> <> Wasn't sure about instance methods
<FromGitter> <Blacksmoke16> also worth pointing out class methods on a module aren't ignored when you include/extend
<FromGitter> <Blacksmoke16> thats a key point
<FromGitter> <Blacksmoke16> sorry, *ARE* ignored
<FromGitter> <> Interesting
<FromGitter> <> Wondering if I can get some feedback on a small part of my first bit of code in this language, ignoring the missing documentation :)
<riza> is there an obvious way that I can specify an argument type be "any hash"?
<FromGitter> <Blacksmoke16> `arg : Hash`
<riza> :|
<riza> it's so easy!
<FromGitter> <Blacksmoke16> and just to clarify this only would work for an argument or return type restriction
<riza> well I've been overthinking that problem for a week
<FromGitter> <Blacksmoke16> you cant type an ivar to `Hash`
<riza> yeah, for sure
<FromGitter> <Blacksmoke16> 👍
notzmv has quit [Ping timeout: 258 seconds]
notzmv has joined #crystal-lang
hightower2 has quit [Ping timeout: 258 seconds]
szutt has quit [Quit: Client closed]
szutt has joined #crystal-lang
avane has quit [Quit: o/]
avane has joined #crystal-lang
szutt has quit [Quit: Client closed]
hexreel has quit [Quit: nyaa~]
<FromGitter> <> Decided to poke around with the compiler source and wow i've never experienced having to run the compiler specs... takes like 30 minutes
<FromGitter> <asterite> yeah... we kept adding more and more specs and it became like that. In general you never need to run them locally, we usually run specs for things we change, and then let CI run all of them
<FromGitter> <> i just don't know the build system well enough to run only the specs i changed and i'm waiting for the CI to finish before i make a pull request because i already had a few dumb mistakes...
<FromGitter> <> I wonder if non-dependent specs, could be run in parallel
<FromGitter> <Blacksmoke16> `./bin/crystal spec /spec/path/to/file/or/directory`
<FromGitter> <Blacksmoke16> related:
<FromGitter> <> what a lifesaver..
<FromGitter> <> I will say its better than over in Nim. Just a few tests takes forever to compile, not to mention run, and outputs in tens of thousands of lines of C code iirc
<FromGitter> <> omg it even tells me the command to run a failed spec for each failed spec... i'm just blind
<FromGitter> <Blacksmoke16> 😅
<FromGitter> <> Is there a decent way to call a method with arguments being the elements of a (small) StaticArray? I'm coming up with hacky stuff without diving into macros
<FromGitter> <Blacksmoke16> if you used a tuple you could `*tuple`
<FromGitter> <> Sort of like splatting, but without a tuple or intermediary sequence
<FromGitter> <Blacksmoke16> `arr[0], arr[1]`
<FromGitter> <> Yeah I thought I could do function application from the result of a functional map or something
<FromGitter> <> Oh well
<FromGitter> <> are tuples stack objects or are they collected?
<FromGitter> <Blacksmoke16> stack
<FromGitter> <Blacksmoke16> ofc if you used a struct you could just pass the struct thru and use its getters
<FromGitter> <> i would assume a tuple is fixed in length then
<FromGitter> <Blacksmoke16> yes
<FromGitter> <> Ok good
<FromGitter> <> What are the performance characteristics compared to a StaticArray?
<FromGitter> <Blacksmoke16> not sure, probably similar?
<FromGitter> <> Yes, I am there. That page is nearly empty :)
<FromGitter> <Blacksmoke16> API docs have a bit more info
<FromGitter> <> I see. Main difference I see is SA is a homogeneous container, which might be more contiguous/better for cache
<straight-shoota> @mjfiano What exactly do you want to do?
<FromGitter> <> straight-shoota: I'm pretty new, just experimenting mostly. But right now I have Vector (math) types in 2-4 dimensions, and currently using separate float ivars. Would like to back their storage in some container, so the method logic can map over them and reduce code by being generic for all 3 types.
sagax has joined #crystal-lang
<FromGitter> <> Most operations are element-wise, so could reduce quite a bit of code by iterating over a generic container of some size to produce results for a given operation/vector type.
<FromGitter> <> THat is the idea anyway. Not sure where to start yet :)
<FromGitter> <Blacksmoke16> fwiw its fairly easy to make a struct that is iterable
<FromGitter> <> Interesting
<FromGitter> <Blacksmoke16> that you could use with `.each` or `.map `etc
<FromGitter> <> I need to learn that too then
<FromGitter> <> So how does that work? Is it an abstract type where I have to implement some methods?
<FromGitter> <Blacksmoke16> its a module that you include in your type, an implement a method
<FromGitter> <Blacksmoke16> 2 methods*
<FromGitter> <Blacksmoke16> 1 that returns the size of your container, and another that gets the value at the given index
<FromGitter> <> Oh does that page say which 2 methods?
<FromGitter> <Blacksmoke16> search for `abstract`
<FromGitter> <> Oh that's very nice.
<FromGitter> <> Thank you
<FromGitter> <Blacksmoke16> might also be helpful to
<FromGitter> <Blacksmoke16> makes it super easy to do like `arry.sort!`
<FromGitter> <> I am beginning to see how Crystal is very extensible with these mixin modules
<FromGitter> <> It seems I have to study generic type parameters more because the compiler can't infer the type parameter and I'm not sure what to specify.
<FromGitter> <> Heh, you're right. That *is* easy. I do have one complaint about the compiler here though.
<FromGitter> <Blacksmoke16> oh?
<FromGitter> <> When i `include Indexable(T)`, the compiler was smart enough to tell me I didn't implement `unsafe_fetch`. After I implemented that and tried using it, the compiler ended up overflowing the stack due to recursing infinitely. It wasn't until I implemented `size` that it worked. It makes me wonder why it just blew the stack instead of complaining that I didn't implement `size`.
<FromGitter> <Blacksmoke16> hm
<FromGitter> <Blacksmoke16> got a small example of that behavior? I have a theory
<straight-shoota> The problem is that `Indexable#size` is actually implemented by it's ancestor `Enumerable#size`
<FromGitter> <> I will make one on play
<FromGitter> <Blacksmoke16> yea that was my guess ^ which its implementation just iterates the whole thing to figure out
<straight-shoota> Relevant issues are
<FromGitter> <> @Blacksmoke16:
<FromGitter> <Blacksmoke16> yea, reason is what @straight-shoota said
<FromGitter> <> Ah I see
<FromGitter> <> This ability to make anything indexable/iterable/whatever-able is fantastic.
<FromGitter> <> Thank you for opening my blind eyes after reading the docs/api multiple times
<FromGitter> <> It appears more has to be implemented, or what is the error here?
<FromGitter> <> wouldn't you unsafe_fetch here return a nilable value
<FromGitter> <> because there's no else in the case
<FromGitter> <> Hmm how do I fix it?
<FromGitter> <> have an else which throws an exception?
<FromGitter> <> speaking of, is there no way to view the `--error-trace` on
<FromGitter> <Blacksmoke16> prob raise if index isnt 0 or 1 then just do like ` ? @x : @y`
<FromGitter> <> Yeah for this type. Also have 3d (x y z), and 4d (x y z w) types
<FromGitter> <Blacksmoke16> case + else with exception prob be the way to go then
<riza> how does log.context get "inherited" when a fiber is spawned? I had assumed there was something in spawn/Fiber that called a .dup or .clone on the ivars on Fiber at .new time but I don't see it
<FromGitter> <Blacksmoke16> does it inherit context?
hexreel has joined #crystal-lang
<FromGitter> <> Spent a while trying to figure out why Number#negative? was erroring out. Looks like I am still on 1.0.0. Also looks like I need a break :/
<FromGitter> <Blacksmoke16> hey that was my feature :P
<riza> @blacksmoke16 as far as I can tell, when a fiber is created, nothing is passed in from the current fiber:
<riza> but maybe that's implicit somewhere else
<FromGitter> <Blacksmoke16> right, so what makes you think it does get inherited?
<riza> hhhhhhhhhhhhhhhhhhmmmm I don't know where I saw that
<riza> the log context metadata does have the ability to inherit
<riza> this test seems to point that you're right and things aren't getting inherited though
<riza> if they were being inherited I'd expect there to be an assertion in here which proves that a == 1 too
<FromGitter> <Blacksmoke16> yea, makes sense
<FromGitter> <Blacksmoke16> pretty sure there's a way to set the context on a fiber tho
<riza> there is, for sure
<riza> Fiber#current_context= is available
<riza> that's fine. I was hoping there was some magic which let log inherit instances of itself from the parent fiber
<riza> thanks :)
<riza> man, now my head is spinning. this looks right to me:
<riza> same result here:
<riza> man how is so fast when `crystal play` is so slow
<FromGitter> <Blacksmoke16> i think only metadata is serializable, not context
* riza derp
<riza> this api is kind of confusing, because you call #set on the context but if you want to render all the things you've set you have to call context.metadata
<FromGitter> <Blacksmoke16> context represents global fiber data, while metadata represents data on a specific log message
ur5us has joined #crystal-lang
<FromGitter> <> ```code paste, see link``` ⏎ ⏎ @Blacksmoke16 Curious if this is a bug, but the latter version results in a compiler error when using some Indexable methods: `Error: no overload matches 'Array(Float64)#<<' with type (Float64 | Nil)` []
<FromGitter> <Blacksmoke16> unsafe_fetch can return `nil`
<FromGitter> <> I mean it is still exhaustive i would think
<FromGitter> <Blacksmoke16> because thats the default return value of a case w/o an else
<FromGitter> <> I would think it could either return x, y, or NoReturn
<FromGitter> <Blacksmoke16> which is why you need to put it in the else if you're using case
<FromGitter> <> the raise catches not a 0 or 1, doesn't it?
<FromGitter> <Blacksmoke16> :shrug: guess it's not that smart?
<FromGitter> <> Which has the special NoReturn type
<FromGitter> <> What class does #[]= come from?
<FromGitter> <> I would like to include the 5 overloads for `#[]=` into my Indexable struct type. Any ideas?
deavmi has quit [Read error: Connection reset by peer]
deavmi has joined #crystal-lang
hexreel has quit [Quit: nyaa~]
sagax has quit [Ping timeout: 245 seconds]
<FromGitter> <> Is there a better way to perform an element-wise operation on my Indexable struct? ⏎ ⏎ ```code paste, see link``` []
<riza> #map
<FromGitter> <> But the point is to mutate while traversing
<FromGitter> <> I don't see how to do that with map
<riza> from your code there, I don't see what you're trying to achieve that map doesn't
<FromGitter> <> map returns an iterator which can be converted to an array
<FromGitter> <> in my code, i am mutating the ivars of an Indexable struct
<FromGitter> <> Not constructing an intermediate sequence
<riza> `dup`?
<FromGitter> <> Yeah I'm doing it on a copy as a test to prevent some foot guns that were bothering me
<riza> okay, I see. It looks like Indexable doesn't include map anyway
<FromGitter> <> But `self.each_with_index { |elt, i| self[i] = elt.round }` doesn't return anything, unlike map
<FromGitter> <> It modifies my struct in place
<riza> sure, whats your end goal with this which each_with_index doesn't achieve?
<FromGitter> <> each_with_index is what I came up with, and it works. I was only wondering if there was something more concise/more idiomatic for this use-case :)
<FromGitter> <> I've only played with a tiny bit of the API, and no 3rd party libraries or anything yet
<riza> dealing with the indices manually doesn't feel idiomatic to me, but it's not at all wrong
<riza> (I would run a .map so I didn't need to deal with the indices)
<riza> ` {|e| e.round}`
<FromGitter> <> that will produce an array, right?
<riza> Well, #map isn't available on an Indexable so it wouldn't compile
<riza> what led you to use an Indexable instead of just an Array?
<FromGitter> <> array is a generic class, not a module. Blacksmoke16 recommended me to `include Indexable` on my struct so that I can implement the abstract methods to be able to index/iterate over it
<FromGitter> <> Which I have done and therefor get Enumerable and Iterable too
<FromGitter> <> I'm not sure what you mean by #map not being available. It is inherited in Indexable from Enumerable
<riza> oh I see, this is an exercise in implementing the modules
<FromGitter> <> I mean what I have works. The map suggestion is only half of the work required.
<riza> oh sure enough it is. I thought Indexable only included Iterable.
<FromGitter> <> This is more than constructing a sequence of values. It is modifying the input sequence in the process, so does not need an intermediary sequence.
<FromGitter> <> That's why I chose each_with_index. Maybe this is not idiomatic, but I don't see another way to do it efficiently
<riza> you're probably right about that
<riza> a bunch of the crystal community sheds a lot of sweat about saving bits of memory... I try to avoid dealing with memory concerns
<riza> it's not wrong by any means, I'd just rather solve problems that aren't already more-or-less solved for me by the language
<riza> if that weren't the case, I'd write a lot more C
<FromGitter> <> Usually a good decision, at least until profiling says you shouldn't
<riza> yep, exactly
<FromGitter> <> Ok thanks for the help :)
<riza> thankfully in Crystal, it's pretty uncommon to need to care about an extra loop or copy of the data
<FromGitter> <> Speaking of the Crystal community. It is small, but probably the most helpful for a newcomer than any of the few dozen languages I've used.
<FromGitter> <> Very friendly crowd around here
<riza> well I think we all count that as a win, for everyone. glad you found it welcoming, it often is exactly that
<FromGitter> <> I left Nim, which is a similar language, due to a very toxic community (among other reasons, but mostly that)
<FromGitter> <> It was sad, but I am liking everything about Crystal much better anyway
<riza> Nim's a pretty neat language. It's difficult to keep a community from getting toxic or divided as it grows.
<riza> @mjfiano what kind of programming do you do which you were using Nim for and are now evaluating crystal?
<FromGitter> <> riza: Mostly 3D games, or 3D math visualizations/simulations that require soft real time performance.
<riza> nice, sounds fun! Anything published? I believe there have been people working on 3D engines at some point, but I don't know if there are any active projects anymore.
<FromGitter> <> I mostly do so in Common Lisp, which gives me the performance of C with the productivity of Python, and the ability to extend the language with macros. But, having used it for nearly 20 years exclusively, I have recently started looking for other languages, primarily to learn all the different ideas there are out there.
<FromGitter> <> Nothing complete enough, or interesting enough worth publishing yet :)
<FromGitter> <> I'm a researcher mostly, so just like to implement cool graphics techniques in academic papers :)
<FromGitter> <> Haven't made much of anything I would call an application, but I would like to one day.
<riza> I can't imagine being productive in a Lisp... I always have to sit and stare at the screen for 3 hours before typing a line. But it's a neat language, and I imagine if I spent the time on it maybe that 3 hours would shrink a bit...
<FromGitter> <> I guess you have to have a good teacher/learning resource. I switched to Common Lisp from Python and was more productive after a week, which says a lot I think.
<riza> The thing that slows me down about Crystal is the lack of a REPL. I spent years in the Ruby REPL and the lack of instantenous feedback makes the development process feel very slow to me.
<riza> I wonder what the performance benchmarks of common lisp against crystal are
<riza> maybe you wouldn't need to think about performance anymore!
<FromGitter> <> I hear you there. Lisp is very interactive, with many more tools than the REPL, so this is very new to me.
<FromGitter> <> Curious, do you think reading a book about Ruby would help me to learn Crystal better, or would I just confuse myself even more?
<FromGitter> <> I know absolutely zero Ruby, but been using Crystal for about a week and loving it so far.
<riza> there's just enough divergence between the ecosystems that I wouldn't recommend it
<riza> just stick with the reference and the api docs
<FromGitter> <wyhaines> @riza, @asterite demo'd a instant feedback REPL for the Crystal Conference 1.0 a couple weeks ago.
<riza> from an algorithms perspective, there are probably more reference implementations on the internet in ruby
<riza> neat! have a link? I had a ticket but couldn't go at the last minute
<FromGitter> <wyhaines> The talks aren't published yet. As for the code....I don't know if he has committed it to a branch in the repo yet, or not.
<FromGitter> <wyhaines> But it's pretty slick.
<FromGitter> <> Is this the new `crystal i` PR?
<FromGitter> <wyhaines> Yeah
<FromGitter> <> That looked interesting, but will take some time to iron out for sure. I really like how Crystal is managed and coming together.
<FromGitter> <> If I'm being honest, I'll share the major reason besides the toxic community that I left Nim, and I'm not seeing it here.
<FromGitter> <> The project seemed like an experimental sandbox of the lead developer, pushing out new features that didn't need to exist, and before testing them, making the compiler very complex and fragile. There's like 7 garbage collector choices, and a bunch of other features that makes it feel more like C++ than a well thought out language.
<FromGitter> <> I need some help with `blocks`. Not sure if what I want is possible.
<FromGitter> <> I'm trying not to get into macros at this point, so ignoring them. I have a bunch of methods that all repeat a lot of code. Here's 2 of them: ⏎ ⏎ ``` def round ⏎ element_wise { round } ⏎ end``` ⏎ ⏎ or something or other. []
<FromGitter> <> Is this even possible or should I abort now? :)
<FromGitter> <Blacksmoke16> ```v = dup ⏎ v.each_with_index { |elt, i| v[i] = yield elt } ⏎ v``` []
<FromGitter> <Blacksmoke16> actually what you want is prob `v[i] = with elt yield`
<FromGitter> <Blacksmoke16> at which point you could prob just do like
<FromGitter> <Blacksmoke16> ```element_wise &.round ⏎ ``` []
<FromGitter> <Blacksmoke16> but this is probably a good use case for macros
<FromGitter> <Blacksmoke16> as the methods are all the same