• 0 Posts
  • 17 Comments
Joined 4Y ago
cake
Cake day: May 31, 2020

help-circle
rss

I have no idea about MIDI controllers using keyboard keys, but it seems quite popular for DAWs and similar software to support this. I’ve tried LMMS, Ardour and MilkyTracker so far and they all had it.
For quickly trying out a melody/chord, I also like to keep VMPK installed, which is basically just a software to play piano on your PC keyboard. I believe, it could also be hooked up like a MIDI controller to DAWs.

I will say that using a PC keyboard for this does not always work terribly well, since most PC keyboards are not built for pressing many keys at the same time. They will just not accept certain keys being pressed together.
There is PC keyboards with “n-key rollover” which don’t have this problem, but you might as well get a proper MIDI piano keyboard at that point…


Well, as it says in the documentation I linked:

unlike canonicalize absolute does not resolve symlinks and may succeed even if the path does not exist.

Primarily, the latter part is what I want. There’s just sometimes situations where a path doesn’t exist (yet), but you want to know what it would look like as an absolute path.


I only really understand half of it without getting my fingers on it, but sounds like some good stuff.

The path::absolute() that’s hidden in the stabilized items is definitely something I’ve wanted for a while, though.


I jumped into both Rust and gamedev a few years ago, before Bevy existed. So, I don’t have much outside perspective, but I did enjoy Bevy, too, once that became a thing.

One thing to be aware of, is that Bevy kind of bypasses Rust’s memory management by using an ECS (as game engines generally do). That’s not a bad thing, Rust encourages implementing own memory management, if its own doesn’t work for a use-case.

But yeah, if you ever stumble because you’re building big games, while a small business application has you scratching your head, then you skipped properly learning about the borrow checker, ownership, lifetimes etc… None of it is terribly hard, but it does need some learning anyways. (This happened to me. 🙃)


Yeah, been considering migrating to a non-Mastodon instance. Not sure where, though. Wouldn’t mind using Lemmy as my entrypoint to the Fediverse, but I don’t think, you can follow individual users here…


Eh, this fork was born out of an unwarranted shitstorm (disagreement over a trademark policy proposal which was literally made public to collect feedback). So, I don’t see this fork gaining popularity.

It’s easy to declare a fork, but you need to build up infrastructure, an own ecosystem and ultimately actually be a better language.


I would also definitely recommend hierarchical sorting. So, at the top would be a type typically used when calling your API or the aggregate type holding your internal state etc. and then right below each of these, the types they are composed of.

Reading code requires sifting through tons of complexity and it requires not-sifting through irrelevant complexity. So, I want to know that I need a type before I care about its precise definition.

For multiple, not hierarchically related types, I try to put the most important, most frequently used type at the top.

And I usually put types above functions, as functions can entail a lot of code + details, so I don’t want them ‘displacing’ any relevant types.

But yeah, I’m not a fan of hard rules and there’s definitely exceptions to these.

In a codebase at $DAYJOB, we often have Configuration types, which are just boilerplate to read out part of a config file and make it easily accessible to the code in this module.
No one cares how those Configuration types look, so we place them below all the functions.

And sometimes, you’ll have a module with many types and not really a reason to deem one more important than the other. Then just sorting them alphabetically can be more readable.


I usually sort them like this and feel like that’s roughly what most people are doing:

  • Imports from third-party libraries
  • Imports from std
  • Imports from own crate
  • mod statements and respective (pub use) imports from sub-modules
  • pub types & functions
  • private types & functions
  • Unit tests

Generally, the logic is public API at the top, internals at the bottom, so that other devs using your module find everything they need at the top.

One exception to that are the imports. Aside from pub use, those would be better placed at the bottom. We just seem to put them up top for reasons of We’ve Always Done It This Way™.


Oh yeah, I have no problem with using a metaphor, whether it’s from a religious book or not. It just weirds me out how it is told as if it’s a historical record with no doubt of it having happened that way.

For an atheist, the stories in religious books are more like fables – you don’t believe that it happened that way, but you can still draw a learning from it. And when talking of fables, you don’t recount them as facts, rather you point out every few sentences that you’re simply recounting what’s being told in the book.

You can do that in a neutral way, too, where you just say “the Bible reads…” and then people can choose to believe in it or not. And this text rarely does that, while also throwing in some opposite tropes. Had the author not stated that they’re an atheist, I would have assumed they’re basically a religious fundamentalist.


This is the most often I’ve read someone talk of “God” or the bible in an assertive stance in many months and it’s from a self-proclaimed atheist no less. 😵‍💫

I wonder, if the Wired editors made him change it, so that no religious people would be offended…


Yeah, I’m quite fond of the Scala syntax:

val a: Int = 1
val b = 1
val c = {
  1+1
}

def foo(x: Int): Int = x+1
def bar(x: Int): Int = {
  x+1
}

Yeah, in inline functions, you have to use implicit returns, whereas in regular/named functions, you have to use explicit returns.

Although, there is yet another special case to that rule in that you can use labeled explicit returns in inline functions like so:

list.map { value ->
    return@map value*2
}

Yeah, at work, we (regrettably) elected to use Kotlin for a project instead of previously Scala and those braces are definitely something I miss.

Kotlin does support basically the same thing with the run { } function, but Kotlin is so incredibly inconsistent with when implicit returns are allowed and when not, that it seems to confuse colleagues rather frequently…


Yeah, I was joking. Some people only want to be Twitter-verified to look important, and they can get that same pseudo-important look on Mastodon by just putting the blue-checkmark-emoji into their display name. Anyone can do that, so yeah, it certainly doesn’t verify anything…



Interesting. The whole async-await stuff has always been a bit risky to me (in any language), because yeah, as soon as you start introducing it, it spreads through your code base limitlessly.
This effort won’t yet quite fix that, but it will at least stop it from spreading under certain circumstances.

I often like to use the actor pattern, which gives you relatively nice asynchronous code without language-level support, and well, that too spreads over your code base, but it spreads differently.
It requires core components to be turned into actors and communication between them needs to be done with messages instead of method calls, but on the plus side, within those actors, you write synchronous code, so utility functions and such don’t need to know about this async-vs-sync problem.

So far, it always felt like this was just the better solution, if you were willing to pull through with the whole message-based communication. But yeah, I’m curious to see what the Rust team comes up with. If they can ‘fix’ async-await enough, maybe that’s worth another look.


I don’t, but I do think that humanity has produced a lot of terrible programming languages and Rust is not one of them.

So, it may not be the ideal tool for every job, but it gets a lot of stuff very right and really not a lot wrong.