How's CL's GC performance for games nowadays? I've been slightly eyeing the upcoming Autumn Lisp Game Jam myself, but last I checked all the major libre CL impls, including SBCL, still used a full stop-the-world collector, which feels like a recipe for latency spikes. I saw flashes of stuff on sbcl-devel about someone working on a lower-latency one, but I don't know whether it got anywhere.
Re “configured”—what's your locale? In en_US.UTF-8 on my Arch system it's in the system file (/usr/share/X11/locale/en_US.UTF-8/Compose) as <Multi_key> <minus> <underscore>.
This is interesting—my observations on Windows 10 (mostly with a layout arranged via MSKLC) have always been that it does some kind of QWERTY-on-Control thing which I'd actually like to turn off but never found out how to; my keyboard shortcut memory seems to indirect through keysyms in a way loosely symmetrical with how my Cinnamon FDO/Linux desktop handles things, rather than being position-based, with the exception of WASD-like game controls which are positional. Is the main difference with your utility that it handles Alt as well?
Not the parent commenter, but I've encountered “people from the counterparty organization get confused and wonder whether you're part of it too / pretending to be part of it too”. This can be mitigated with some obscuring transformation.
> LuaJIT is really good software, it is hard to beat it as its own game. Pallene tries to get its edge elsewhere: it tracks Lua 5.4, whereas LuaJIT diverged around 5.1 and will stay that way forever.
Last I saw (admittedly some years ago), this also meant that an awful lot of the authors of Lua libraries/bindings diverged around then and de facto intend to stay that way forever and give up on anything that doesn't have LuaJIT's FFI implementation compared to mainline Lua's C bindings, and then a pile of Lua embedders also did this either because they had to keep tracking that crowd or because they really wanted the performance, and… so on. Unless this has changed in the meantime, I'm not sure what kind of edge you're hoping to get there.
In binary floating point, 4.0 = 1.0×2^2, so the mantissa of the multiplicand will stay the same (being multiplied by 1.0) and the exponent will be incremented by 2. Scaling by exact integer powers of 2 preserves the relative accuracy of the input so long as you stay in range. The increase in absolute error is inherent to the limited number of mantissa bits and not introduced by any rounding from the multiplication; there are no additional bits.
I would like to half-seriously recommend that you overwrite a different character than the first when mangling the environment variable name. Specifically one beyond the third, so as to stay within the LD_ namespace (not yours exactly, but at least easier to keep track of and more justifiably excludable from random applications) and deny someone ten years from now the exciting journey of figuring out why their MD_PRELOAD environment variable is overwitten with garbage on some systems. How do you feel about LD_PRELOAF?
Also it's probably better to leave LD_PRELOAD properly unset rather than just null if it was unset before; in particular I wonder if empty-but-set might still trip some software's “someone is playing tricks” alarms.
There are probably other ways this is less than robust…
(hi, I kind of have a Thing for GNU and Linux innards sometimes)
The first part is true for ‘normal’ string literals, but there's suffixed string literals since I think C++17: "foo"sv is a std::string_view if you have operator""sv from std::string_view_literals visible.
Yeah, I agree that the way that comes out is really awkward. The first line there is reporting the context from in the Task module (because task.ex includes it explicitly in the exit call), and then the second is reporting a strerror-like translation of the :timeout reason, but the lines aren't clearly linked together that way and look more like chained events. All of the %Task{} stuff of course is just the inspection of the argument, but if your eye jumps to the “pid” part it can look like it's reporting that that's the exiting process even though it's not. And then the part where the first “exited” is written in past tense as though the exit happened, when in fact it's describing what the trap just caused to not actually fully happen, is probably the most confusing of all.
> If the timeout is exceeded, then the caller process will exit. If the task process is linked to the caller process which is the case when a task is started with async, then the task process will also exit.
Reasoning is the same though; self() preceding/following it in the IEx session still shows the same evaluator process alive.
Task.await tries to exit the calling process when the timeout hits, but IEx traps the exit in that process, so it doesn't terminate and thus the linked task process doesn't either, I think? If I do all of this wrapped in another task, rather than directly in IEx, then I observe the innermost process get terminated by the process link after the intervening one doesn't trap the exit.
> If the timeout is exceeded, await will exit; however, the task will continue to run. When the calling process exits, its exit signal will terminate the task if it is not trapping exits.
FWIW, in C++11, a class C can similarly cooperate to enable reconstructing a shared_ptr from a raw one by deriving from std::enable_shared_from_this<C>.
Do you not count LispWorks in this? I haven't had a chance to play with the commercial Lisps myself, but anecdotally it seems to still have some currency.
Asking for “set language français” at the beginning of a session seems to vastly increase the chance of responses barrelling through the user's ‘turn’ and initiating various ‘commands’ on their own. I wonder whether that's causing alterations in what are meant to be delimiter tokens or something.
I agree; I meant “including” in the non-restrictive sense, not “including only”. Stack allocation is a special case where the lifetimes are arranged in a convenient way—see also escape analysis in languages where stack allocation isn't explicitly supported at the language level but can be added by the compiler.
I have to wonder whether some of this is semantic drift over time or context. My recollection since undergrad (a few decades ago) involves treating “garbage collection” as referring to tracing garbage collection, and “reference counting” as a separate mechanism. There is still a term for the category including both, only that term is not “garbage collection” but “automatic memory management”. But what I see nowadays is closer to what you describe.
I do observe it applying to video games in many circles. This is more true for social (cooperative or competitive) games and in game-adjacent social contexts like Twitch streaming, but it's also applicable to recognizing references and plot beats from widely-known classics or having similar experiences over particular moments or levels, even in single-player. Pokémon, Final Fantasy, Minecraft…
Not the OP, but I have a similar desire, not because I make lots of progress, but mostly because progress comes from many different directions, and then in some ways because I make little enough progress at a given time, between other things, that if I don't have an easy way to reload the context, there'll never be a way to string all the little bits of progress into anything coherent.
The usual way to generate an exit status for a signal that normally terminates the process is to explicitly unset the handler and then raise the signal yourself. In C, the latter half of that can be done with the ‘raise’ function; on (at least one) Linux with glibc, this uses tgkill underneath. I assume Rust doesn't expose this though from what you said?
Light correction: hexl-mode is the hex editor proper. hexlify-buffer called by itself just does a transformation to a side-by-side hex/chars view; it doesn't set up for hex-editor navigation or transforming back to binary on save or anything like that.