Hello and welcome to my little nock of the internet. Here I have my blog which mainly contain posts about tech, the outdoors, cooking, and some times mead brewing.
A bit of background information before you step into my world of crazy. I am Lars, a.k.a. looopTools, a Software Engineer living in East Jutland, Denmark. I have 10+ years of experience from industry mainly through student positions, but also as self-employed consultant, or full-time employee. I mainly work in low-level user space, high-level kernel space, and storage systems in general. Besides research and software development, I also love the outdoors and try to go out as often as possible (not enough at the moment) and I am an aspiring author currently working on a few different novels. I also dabble in being a more advance home cook and baker, which you may see some posts about. Finally I like the ancient art of brewing mead, a.k.a. honey wine, and experiment with different flavour combinations and ageing times.
Apps for macOS I cannot live without?
A while back I made these two blog posts “Why I prefer physcial notebooks over software-based” and “Writing my notes by hand”. This resulted in me getting a few emails about note Apps I should try for both mac and Linux which totally would get me to drop the physical notebook. Well it has not, I tried Notion for Notes & Docs but it simply is not me. Honestly, I still prefer Emacs with org-mode if I have to take notes on a computer. Now, I actually also got some questions about what applications do I use and mainly I was asked for macOS. So I this bog post I will cover which Apps I cannot live without on macOS and later I will make a similar post for Linux. So let us get started!
Emacs
Emacs is my drug of choice and by the application I use the most. Not just on macOS but also on Linux. Although it is an old text editor, it can be modernised quite a lot through modifications and plugins. I use it for writing blog post for this blog, writing my books, coding, note taking using org-mode and more. It is my multi-tool and I love it.
I will ammend here that the learning curve is quite steep and I might not recommend vanilla Emacs to most people. There are alternatives such as doomeacs which suites modern people a lot more. Although I have not made that leap yet myself… I have actually considered setting up a virtual machine and testing how much I like it.
Apple Pages
For the rare occasion where I need something written which I need in .docx format I do not use Microsoft Word, I use Apple Pages. But why do I use Pages over let us say OpenOffice, LibreOffice, or ONLYOFFICE. Well first of all! I honestly dislike Microsoft Words user interface. I find it very confusing and very unintuitive, which from the get go removes ONLYOFFICE. Then there is {Open,Libre}Office and while LibreOffice is my go to on Linux, I find it really unstable on macOS doing some very weird things from time to time. But, that is not the only reasons I use Pages. I also use Pages because:
- The UI is simply
- It does what I need
- It is stable
- I have iCloud sync between my personal devices (even my Linux machine(s))
- The online editor when I need it is reasonably good, and miles a head of Google Docs and Office 365.
It is a solid what you see is what you get editor and it never surprises me which I really, really like. Here I particular scowl at Microsoft Word and OpenOffice.
Apple Music
I do not understand the hatred people have towards this application. Did I prefer it when it was called iTunes and the layout was less website like… YES! But do I hate it? No! Apple Music lets me listen to my music and that is really all I want from it. I only really use the Apple curated play lists I do not use custom play lists so much… Yet.
Additionally, I love the automatic synchronisation between my phone, tablet, and computers. Side note here! For the blog post on Linux applications I will talk about Cider which I use to listen to Apple Music on Linux.
Things
I am a todo alcoholic and I have been a heavy user of Apple Reminders and I love it. However, I need a more sophisticated app with some feature in terms of note taking for a todo in the todo app. Enter Things. I had been eyeing this app for quite a while and people promised it would beat Apple Reminders by miles and quite honestly it does. The organisation of projects and areas are unparalleled compared to any app I have tried both on Linux and Mac. I was lucky to get it for iPad, macOS, and iPhone last year at black Friday and I have not regretted buying the App.
So that is the apps I cannot live with out.
./Lars
Difference of opinion is okay!
I have thought long about whether or not I should publish this particular piece of writing. Mainly because I cannot foresee the consequence. Which ironically is one of the reasons I wanted to write it in the first place. So let us see what happens.
Also this is a work in progress I will probably reiterate this post many, many times as I give it more thought.
I was born in 1989 which means I got to grow up in the nineties and beginning of the new millennium. It means that by the time I turned twenty, I had experienced the mobile phone and internet become mainstream. I watch opinion providers going from being experts on TV, on the radio, or in papers, to be whomever wanted to shouter their opinion out on the internet. I saw this rice of the comment section on news articles, the hatred it sparked, the rudeness, the unkindness, in particular to people of a different opinion. I witnessed the rise of the opinion influence, with this I mean those influence whom provide opinion on any topic be it political or not. And honestly it frightens me what I have witnessed and what it has become. It frightens me because the nuance of debate has been lost. I has become us versus them and they need to disappear
Enter almost any subreddit (for the uninitialised subforum) on Reddit and you will at minimum see one active “debate”. Where people are throwing slurs at one another because mentality “your dumb arse is wrong and I am write” is strong. Go to Facebook and read the comment track for a news article and see the anger and hate, even if people did not read the article. It is insane. But what is even worse, no one really debate. People stand first on their own opinion with no desire to even try and understand the other side. From arguing about if pineapple on Pizza is sacrilegious, to which band it better, to which political direction is better. No one wants to give up on their opinion and their, in lack of better words, right to be right.
We have become unable to see the side of an opponent. To see that their may be some truth in what the opponent say. It is a lost skill. I have heard and read in many places that this in part can be blamed on information warfare from Russia, China, and other adversaries of the west. But can it really? I have not actually seen a fully convincing argument for it being the sole reason. Others argue that it is the media, their click bait, the dividing stories. But is it? I would argue, no. The reason is that whilst the news do bring these stories that polarise, they do so because it is the once we read and interact with. With todays need for likes, clicks, and interactions, who can blame them? Would you pay for a media that do not do this? I know I want to but right now I do not. For instance I know Zetland exists, an amazing danish news outlet. But do I subscribe… No. Instead I subscribe to a none local news outlet, the New York Times and mainly due to their book and tech sections, not the news. But I should reconsider.
Therefore we should relearn that difference of opinion is okay. We should relearn to accept the opinions of others. We should relearn to evaluate our own opinions. It is a must.
./Lars
QueryC++ 4.0.0
FINALLY!!! We are releasing QueryC++ 4.0.0 and I could not be happier and you can get it here: codeberg.org/ObsidianWolfLabs/querycpp/releases/tag/4.0.0. It has been a much slower process than I hoped and we are already working on release 4.1.0.
Sadly, the documentation is not quite ready yet for the new version, but it will be available here: querycpp-doc.obsidian-wolf-labs.com ASAP.
What have we done? A lot!
- We fully changed the library to use all lowercase function naming, As a request from users and this is the main reason that it is a major release… you know breaking changes.
- We add more functions for SQL commands. Amongst others you can now do joins.
- We add integration test with SQLite which also serves as our example for SQLite.
- We started working on our mdbook based documentation, which we will also release soon.
- We improved the PostgreSQL integration test and again it serves as our example for PostgresSQL.
- We expanded our unit tests.
Over all we are really proud of this release. This will be the last release announcement on this blog for QueryC++. The next one will be at blog.obsidian-wolf-labs.com when we get around to set up our blog there.
./Lars
The Death of Slim Shady
It may come as a surprise to many, but I love Rap music. Old school rappers from the seventies and eighties, the nineties with its more aggressive and offensive rappers, all the way to modern day with Kendrick Llama. I even listen to Rap in multiple languages German, English, Danish, Spanish, and Farsi. I also listen to it in languages where I have no idea what is been said. It is the chain of words combined with the rhyme and beats that leads me to rap. In the beginning I did not know it was black music, I did not even know the artist I was listening to where black. Doc, Ice-T, and MC Hammer are just a few examples. Then in the Late ninties I heard a song called the Real Slime Shady and I was an instant Eminem fan.
Here over 2 and half decades later Eminem released a new Album called The Death of Slim Shady and frankly, I love it. But why do I love it? Well we get the best of both worlds. For those whom do not know, Slim Shady is Eminems dark alter ego. The character he use when he does very dark, aggressive, and right out horrifying rhymes. Slim Shady came in part from Eminems substance abuse and was powered through it. However, in April of 2008 he went on the straight and narrow, and have been for sixteen years now. As part of this he made some albums which focused more on the technical part of rapping rather than just being obscene. Which also left Slim Shady in the dirt. The music he has produced in this period has still been amazing to me. It has been different but amazing.
Then back in 2020 we got the album Music to be Murdered by. When I listen to this album, I felt like there was a change. It felt more like an old school Eminem album, almost like Slim Shady was rearing his head again. Even though I do not know Eminem in person, I was a little nervous if he had dabbled in substance again. But this year, he shared a post (I believe on Instagram), with his sixteen years sober token. Quite frankly amazing feat.
But why did I speak of all this, when discussing why I love the new album? Well, because we got Slim Shady back and in way I believe few expected. On the album there is a song called Houdini, for which the music video ends with Eminem and Slim Shady fuses into a single person. And that is why the album is magical, because that is what has happened it is what album gave. It gave us EminemSlimShady. He morphed his two sides and create music that was technically amazing and very old school Eminem/Slim Shady. He showed that he do not need the substances to be Slim Shady. Somehow, magically, he found a way to merge them both and create a nostalgic trip for us whom haven listen to him for ever and a new version of himself.
I hope we do not lose the very technical Eminem we got, for I love that part to. But thank you Eminem for giving us this.
./Lars
For element in range in C++
While I was a teacher assistant and during my time helping new employees move from Python to C++, I have gotten one question often.
Why can I not do a for loop like this for elm in range(0, 10)
and you know what that is actually a fair question.
In particular for arithmetic types… but what if you could part of the way?
Well first, let us look at a concept to define a type that must be an arithmetic type.
This can be done fairly easy like this template<typename NumericType> concept Numeric = std::is_arithmetic<NumericType>::value;
.
Basically what this does is to create a type that must be numeric. I will show a little later what happens if you use one that is not.
Next let us generate the range, here I will use std::vector
as my range container.
This can be done very simply with the function below.
This assume that start
is smaller than end
, otherwise it will not work.
template <Numeric T> constexpr std::vector<T> range(T start, T end)
{
T size = end - start;
std::vector<T> data(size);
for (T i = 0; i < size; ++i)
{
data.at(i) = start + i;
}
return data;
}
Now let us test it.
For this we will make a print_range
function which takes start
and end
and calls range
and prints the resulting “range”.
Again we use the Numeric
template type constrained to be a arithmetic type.
template <Numeric T> void print_range(T start, T end)
{
std::cout << "[";
for (const auto val : range(start, end))
{
std::cout << " " << std::to_string(val);
}
std::cout << " ]\n";
}
Finally our main function, where we test with size_t
, int
, and float
.
int main(void)
{
print_range(static_cast<size_t>(1), static_cast<size_t>(10));
print_range(1, 10);
print_range(1.0, 10.0);
}
The expected result is:
[ 1 2 3 4 5 6 7 8 9 ]
[ 1 2 3 4 5 6 7 8 9 ]
[ 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 ]
The program should be compiled with clang++ -std=c++20
or g++ -std=c++20
.
The full program is listed below:
#include <vector>
#include <concepts>
#include <iostream>
#include <string>
template<typename NumericType> concept Numeric = std::is_arithmetic<NumericType>::value;
template <Numeric T> constexpr std::vector<T> range(T start, T end)
{
T size = end - start;
std::vector<T> data(size);
for (T i = 0; i < size; ++i)
{
data.at(i) = start + i;
}
return data;
}
template <Numeric T> void print_range(T start, T end)
{
std::cout << "[";
for (const auto val : range(start, end))
{
std::cout << " " << std::to_string(val);
}
std::cout << " ]\n";
}
int main(void)
{
print_range(static_cast<size_t>(1), static_cast<size_t>(10));
print_range(1, 10);
print_range(1.0, 10.0);
}
Now let us say we had called print_range
with "a"
as start
and "z"
as end
.
Well then you would get the following compilation error:
main.cpp:34:5: error: no matching function for call to 'print_range'
34 | print_range("a", "z");
| ^~~~~~~~~~~
main.cpp:19:27: note: candidate template ignored: constraints not satisfied [with T = const char *]
19 | template <Numeric T> void print_range(T start, T end)
| ^
main.cpp:19:11: note: because 'const char *' does not satisfy 'Numeric'
19 | template <Numeric T> void print_range(T start, T end)
| ^
main.cpp:6:50: note: because 'std::is_arithmetic<const char *>::value' evaluated to false
6 | template<typename NumericType> concept Numeric = std::is_arithmetic<NumericType>::value;
| ^
1 error generated.
Some final remarks. First,this can be made MUCH prettier (which I may show in a later post). Secondly, this is not very optimised and only serves as inspiration. Finally, play around with it.
./Lars