ChanServ changed the topic of #crystal-lang to: The Crystal programming language | https://crystal-lang.org | Fund Crystal's development: https://crystal-lang.org/sponsors | GH: https://github.com/crystal-lang/crystal | Docs: https://crystal-lang.org/docs | Gitter: https://gitter.im/crystal-lang/crystal
renich has quit [Quit: Leaving]
ur5us has joined #crystal-lang
_ht has joined #crystal-lang
ur5us has quit [Ping timeout: 244 seconds]
ur5us has joined #crystal-lang
Sankalp has quit [Ping timeout: 244 seconds]
Sankalp has joined #crystal-lang
ur5us has quit [Quit: Leaving]
ur5us has joined #crystal-lang
ur5us has quit [Ping timeout: 264 seconds]
jmdaemon has quit [Ping timeout: 268 seconds]
SamantazFox has quit [Remote host closed the connection]
SamantazFox has joined #crystal-lang
_whitelogger has joined #crystal-lang
Guest80 has joined #crystal-lang
Guest80 has quit [Client Quit]
jmdaemon has joined #crystal-lang
<FromGitter> <asnewman> Hello! Is it possible to do string literal types in Crystal, much like how one would do `let variable1: "a" | "b" | "c";` in TypeScript?
<FromGitter> <Blacksmoke16> do the string values have meaning? like need to explicitly be some specific value?
<FromGitter> <asnewman> My specific use case is that I'm defining events that are being sent over a websocket. An event looks something like: ⏎ ⏎ ```{ ⏎ type => "new", ⏎ data => "hello world" ⏎ }``` ⏎ ⏎ I'm hoping to restrict the `type` field to a specific set of defined string (e.g. "new", "edit", "delete") [https://gitter.im/crystal-lang/crystal?at=62f7fc013a42316d33375a51]
<FromGitter> <Blacksmoke16> https://crystal-lang.org/api/master/JSON/Serializable.html#use_json_discriminator%28field%2Cmapping%29-macro is prob what you want
<FromGitter> <asnewman> Cool I'll have a look 🙂
<FromGitter> <Blacksmoke16> er well assuming you want to (de)serialize from JSON
<FromGitter> <Blacksmoke16> otherwise https://crystal-lang.org/api/master/Enum.html
<FromGitter> <asnewman> Oo yeah enums with `.to_s` is exactly what I need
<FromGitter> <Blacksmoke16> can override `to_s` to make it like all lowercase or something too if you dont want the all cap default
_ht has quit [Remote host closed the connection]
<FromGitter> <stellarpower> I seem to have a call into a shard that is blocking in my code. I've put the other things I want to do in their own fibres, but it looks to me like this blocking code is preventing any other fibres from being executed. Is it the case at all that if a fibre doesn't e.g. call `sleep`, that it'll continue execution indefinitely?
<FromGitter> <Blacksmoke16> if a fiber never does anything that blocks to give room for another fiber to run yes
<FromGitter> <stellarpower> Right, that scuppers it
<FromGitter> <stellarpower> Is there somethin else I ought to do?
<FromGitter> <Blacksmoke16> related: https://github.com/crystal-lang/crystal/issues/1454
<yxhuvud> try with -Dpreview-mt and pray there isn't anything that gets co-scheduled at the same thread :D
<FromGitter> <Blacksmoke16> i dont have any ideas other than find what lib is doing it and allow it to switch to another fiber if available?
<FromGitter> <Blacksmoke16> like a `sleep 0` every now and then
<FromGitter> <stellarpower> I can pray!
<FromGitter> <stellarpower> It's the Qt bindings
<FromGitter> <Blacksmoke16> ah
<FromGitter> <stellarpower> So I presumne it's the event loop in the C++ side
<FromGitter> <stellarpower> I mean I could add aQTImer easily
<FromGitter> <stellarpower> I had meant ot leanr the difference between Threads and Fibers
<yxhuvud> qt bindings shouldn't block unless they are doing somethign *wrong* binding wise
<FromGitter> <stellarpower> Well, it's starting the event loop, and that would be a blocking call in c++ I suppose
<FromGitter> <stellarpower> Maybe I can call that differently, but I am not sure off the top of my head
<FromGitter> <stellarpower> Thing is usually one would be using the application as the main point of entry
<yxhuvud> depends how the event loop works. If it is based on a file descriptor it should be possible to avoid blocking
<FromGitter> <stellarpower> And in my case I am running an OSC server, so I want to use the GUI as a service to call into, rather than that being the main thread
<FromGitter> <stellarpower> Afraid I don;t know, but it's deeply-embedded into the internal libs
<yxhuvud> and it blocks even if you `spawn` qt in its own fiber?
<FromGitter> <stellarpower> I will just try a timer loop, that will ghet it sdorted for now
<FromGitter> <stellarpower> I tink so, that was what I was doing, then as I am testing I read from a channel for when it exits
<FromGitter> <stellarpower> So my worker fibre never gets called basically
<yxhuvud> ouch.
<FromGitter> <stellarpower> IDK if I can kinda make it async...
<yxhuvud> my gui bindings don't behave like that, but they are 1: not done, and 2: they don't provide widgets anyhow..
<FromGitter> <stellarpower> somehow run the event loop in the background ,and have it write to something on exit instead, and then wait for that
<FromGitter> <stellarpower> So the blocking is Crystal-side
<FromGitter> <stellarpower> So... A GUI without a GUI ;P
<FromGitter> <stellarpower> I like your style
<yxhuvud> well. Wayland. The user gets a buffer and the ability to define regions and places that listen to input :)
<yxhuvud> but it will lack certain common use cases, like even the ability to render text or builtin support for 2d graphics.
<yxhuvud> anyone that needs that will have to provide that by themselves
<FromGitter> <stellarpower> oh nice
<FromGitter> <stellarpower> I have spent quite a bit of time trying to get wayland all working
<FromGitter> <stellarpower> It takes effort but there's some seriously neat stuff that can be done
<FromGitter> <stellarpower> So it'd be more like a 3D graphics situation, where you could get a hold of some region and give that to GL?
<yxhuvud> yeah. The environment is so stupidly fragmented as everything is its own addon, but it ends up pretty powerful
<yxhuvud> so far I only have memory backed buffers working, but i plan to provide graphics card based solutions too
<yxhuvud> thoguh i suppose it depends on how much trouble it is to get it working. i havn't found any tutorials for that :X
<FromGitter> <stellarpower> Yeah I know what you mean
<FromGitter> <stellarpower> It's like
<FromGitter> <stellarpower> Well it's repeating X to be frank
<FromGitter> <stellarpower> I mean cleaner, but
<FromGitter> <stellarpower> It makes sense it is a protocol not a specific implementaton and keeps the core transport and messages and hwatever separate
<FromGitter> <stellarpower> But thewn you get this combinatorial explosion again where nothing that works in wlroots ever works on KDE or anyhting else
<FromGitter> <stellarpower> Waypipe is really cool if you get the chance to look at it
<yxhuvud> the really silly stuff is how it doesn't even provide window decorations by default. (thankfully there is libdecor)
<FromGitter> <stellarpower> NGL I feel being in C is also a pain. I mean, most stuff is, but
<yxhuvud> i kinda get their reasoning behind it but it make the basic stuff so much more complciated
<FromGitter> <stellarpower> IT would put me off ever hacking it, it was difficult just tryin to unpick some gamma correction stuff last weekend, to bind in Crysta
<FromGitter> <stellarpower> If you want linux people to take it seriously, then anything other than C woinlt achieve that, but I just would never start a project in C, I don;t have that much spare time to go to all the manual effort it requires
<FromGitter> <stellarpower> It just gets ugly too
<FromGitter> <stellarpower> The number of symbols with underscores and what have you, trying to make it like OO but it isn;t
<FromGitter> <stellarpower> I think I'll try the praying method
<yxhuvud> it also doesn't help that like a third of all functions are declared `static inline`, so it doesn't link clean, so there needs to be shims and stuff.
<FromGitter> <stellarpower> Parallel fibres presumably can just make this go away, I hope
<FromGitter> <stellarpower> It's kinda the only real solution, it is, rightly, a blocking call in C++ as that's the point of setting up the event loop
<FromGitter> <stellarpower> Ah right
<FromGitter> <stellarpower> I didn;t even know C did inlining
<yxhuvud> static inline means it doesn't exist in the .so but get defined in whatever C file that includes the header. Which for crystal means it doesn't exist :X
<yxhuvud> so I have to create a C file that is just the same thing without static inline. Not at all annoying
<FromGitter> <stellarpower> shards build -Dpreview-mt
<FromGitter> <stellarpower> Is that all I need to do?
<FromGitter> <stellarpower> Yeah, it's not a combo I ever see in C++
<yxhuvud> Hmm. No idea if shards command support the command. Potentially you need to do crustal build -D..
<FromGitter> <stellarpower> I guess decorating for static linkage isn;t that common anyway
<FromGitter> <stellarpower> inlining is, but I was not aware the C compiler did that yet
<yxhuvud> it is not super common. Many (especially older) libraries doesn't use it, but some use it all over the place.
<FromGitter> <stellarpower> yay for obscurity
<FromGitter> <stellarpower> IT's still not happy.
<FromGitter> <stellarpower> I think either I'll need to trigger processing the event loop manually from Crystal side, or conversely, get Qt to check back in with the Crystal scheduler to run other fibres
<yxhuvud> Hmm. It looks like it *should* be possible to integrate QT event loop with other event loops in a proper way. https://doc.qt.io/qt-6/qsocketnotifier.html
<yxhuvud> because if you have a fd you can use wait_readable and then invoke the callback
<FromGitter> <stellarpower> But if the main fibre is blocked on waiting to read that socket, won't that kinda be the same?
<yxhuvud> No, that is the point, wait_readable doesn't block the crystal event loop. It sleeps until it can be read from
<FromGitter> <stellarpower> Asi f something else is ready to run, I still need a separate thread able to notify the Qt event loop daemon that it can wake up now
<FromGitter> <stellarpower> Oh wait so
<yxhuvud> well, possible. I don't know the architechture of Qt.
<yxhuvud> but it should give you a method to tell you to run whatever events it has, and then return
<FromGitter> <stellarpower> Okay I think I get you
<FromGitter> <stellarpower> I was assuming that events wouldn;t even get posted into Qt without being in that thread.
<FromGitter> <stellarpower> I may be wrong there though
<yxhuvud> well that is why you wait until the file descriptor is readable, then invoke qt in a nonblocking way, and then wait again
<FromGitter> <stellarpower> Yee, I just wasn't sure that the file descriptor would ever be written to if I am running around on the Crystal side
<FromGitter> <stellarpower> I may just need to do as two spearate processes for now TBH
<FromGitter> <stellarpower> `QApplication::exec: Must be called from the main thread`
<FromGitter> <stellarpower> I err
<FromGitter> <stellarpower> Forgot this
<yxhuvud> :x
<FromGitter> <stellarpower> I think I'll just do IPC
<FromGitter> <stellarpower> The multiple threads did work, I realised I was executing the wrong binary cause I [reviouslt built with `shards`
<FromGitter> <stellarpower> Well
<FromGitter> <stellarpower> Worked apart from that
<FromGitter> <stellarpower> And I could put Crystal in the background but that;s just gonna cause problems
<FromGitter> <stellarpower> So we know what the quickest way to communicate between two processes is?
<yxhuvud> communicate how? Just wake the other up or send actual data?
<FromGitter> <stellarpower> Oh okay, we're getting somewhere
<FromGitter> <stellarpower> Send data^
<FromGitter> <stellarpower> I'd like to wrap Boost::Interprocess some day, but for now I believe pipes or Unix sockets etc. are gonna be the only way
<FromGitter> <stellarpower> It so far is going on a ninfinite loop getting Qt to processss events and then just sleeping
<yxhuvud> I'd say pipes are probably the most straightforward way to go. It maaay be possible to do it faster with shared memory, but that is above my head :)
<FromGitter> <stellarpower> Busywaiting now though.
<FromGitter> <stellarpower> This won't be any easier, will it, bevcause now the app will still be blocked, except it's the IPC that won't run
<yxhuvud> dunno. Perhaps you can do wait_readable on the pipe :D
<yxhuvud> but it depends on the diretion the stuff is flowing I suppose. If it is the qt app that needs to wait up due to the pipe then I don't know
<FromGitter> <stellarpower> I think it's the Qt side that's gonna have to wake up
<yxhuvud> bummer
<FromGitter> <stellarpower> Any attempt to commuincate from the main app to the GUI using IPC in Crystal is the same problem I think, because either we busywait or as you said, somehow knock that class in, or we just block
<yxhuvud> fwiw it was pretty easy in wayland client - you get a fd that you can wait on, and then when it is readable you invoke a function to do all the callbacks. Done.
<yxhuvud> so proper event loop integration is like 3 lines.
<yxhuvud> well a couple more if you include the call to get a fd and the call to flush any pending unsent events before waiting
<FromGitter> <stellarpower> Thanks for your help anyway. I will probably have to put this to bed for today
<FromGitter> <stellarpower> So you're saying the Crystal code would wait on that FD?
<FromGitter> <stellarpower> Then call the event loop in Qt to process? IDK how Crystal' sidei s managing things
<FromGitter> <stellarpower> Or the other way around, Qt would wait on that descriptor and then process its loop?
<yxhuvud> Yes, that would probably be the way assuming qt has a way to dispatch all pending events
<FromGitter> <stellarpower> I'm not sure how I can get Qt to write to the FD in the first case
<FromGitter> <stellarpower> Signals/slots is the native mechanism, tbu that's what the event lop is really for
<FromGitter> <stellarpower> So iI don;t thiunk I can get it to emit a signal that a signal has been emitted, or we'd be here for days recursing :D
<yxhuvud> oh signals. That may complicate it further, considering that crystal has its own signal handling. :popcorn:
<FromGitter> <stellarpower> I am wondering if I can just put the rest of my application into a separate fibre and then have the Qt oen be at the front like it wants
<FromGitter> <stellarpower> And run with parallelism
<FromGitter> <stellarpower> Sorry
<FromGitter> <stellarpower> Signals/Slots signals, not Unix signals
<FromGitter> <stellarpower> I don;t wanna handle Unix signals
<FromGitter> <stellarpower> in the C++
<yxhuvud> phew
<FromGitter> <stellarpower> We don;lt have any good OSs out there 😅
<FromGitter> <stellarpower> It's all so ancient whn it comes down to it
<FromGitter> <stellarpower> Okay anyway, I need to go, TYVM for your help though
<yxhuvud> no worries, it was fun to talk
<FromGitter> <stellarpower> I am trying to see how this socket notifier fits in; it is exported in the shard already, it's just not clear to me how it can be used to bridge eventt loops. I see it mentioned specifically in the docs but will need to dig
<FromGitter> <stellarpower> ty
<FromGitter> <stellarpower> Have a good one
<yxhuvud> yeah it wasn't super clear how it was supposed to be used.
<yxhuvud> there might be better docs out there
<FromGitter> <stellarpower> I think The Qt GUI will always need to be in the main thread, so I'll just try seeing if I can work that in any way and go from there