musicmatzes blog

As you might have noticed, I'm about to switch to NixOS, the purely functional Linux distribution ™. Here are some toughts on Racket on NixOS.

First, why Racket? Well, my blog here is written using frog, the frozen blog tool which is written in Racket . It actually works really well for me and was not that much effort to setup – I'd recommend it to everyone.

But this isn't about frog, this is about racket. So, I need Racket for my blog. But I also like Racket, I played with it some time ago and it is a neat language, really!

Because of my switch to NixOS I wanted to try whether I can compile my blog on NixOS, so I installed Racket on my NixOS-testing machine. And you know what is awesome?

It. Just. Worked.

When installing racket, the racket language distribution ships everything you need. It ships the racket interpreter, it ships DrRacket, the Racket-IDE, the REPL, the package manager for racket. I was able to install frog and compile my blog in 3 steps.

  1. Install racket
  2. Install frog using the racket package manager
  3. Compile the blog

Well, you actually do not use the nix package manager when doing the upper steps, which is, of course, impure. But I wanted to focus on whether it works or not here, not on purity. Of course it would be much better to be able to install frog via the nix package manager, keeping everything in the nix store. But that's not possible (yet), I guess. tags: #linux #nixos #nix #blog

I love minimalism. I had my prompt long time just beeing a simple status indicator and a pipe, everything which was not that important was ripped out.

At some point, I decided that I need at least the time in my prompt, but I wanted it to be on the right side. I managed to do it. And now, as I have more machines, I need to put the hostname in the prompt. I also added a shell-level indicator in the prompt, a “How many jobs are in the background” indicator was also added some time ago.

This post wants to elaborate how this all was achived while keeping the prompt itself as minimal as possible. At least from my point of view.

Requirements

So first, the requirements:

  • Indicators
    • Did the last command work?
    • How many background jobs do you have?
    • How many shell levels are there?
  • What's the current hostname?
  • What's the time?
  • Where am I?

Also, the bash shouldn't flatter around. I want to have my commands in one column, straight down the line.

The prompt

So, that's what my prompt looks like:

my prompt

As you can see, my hostname is one the left but almost everything else is on the right. Well, there's actually really much on the left!

First, there is the hostname. I managed to get the hostname into a box which is always 8 characters long. So longer host names will fit in there as well and don't break the pipe bar at the end of the left side of the prompt.

Also, the hostname will be green whenever the last command succeeded, turning into red if the last command failed.

After the hostname we have the pipe, which is simply the delimiter between my hostname and my commands. Well, not quite. It also doubles itself in a subshell, tribles itself in a sub-subshell and so on.

On the right side there is another pipe, but this one flutters. After that, we have another two delimiters which could be removed, but I keep them. Then there is the current branch whenever I'm inside a git directory, the current working directory the number of jobs and the time.

Howto

To achive this, you need to write a bit of bash code into your .bashrc, that's all:

#
# ~/.bashrc
#

printfnchr() {
    for i in `seq 1 $1`; do echo -ne "$2"; done
}

shlvl() {
    # I'm always on shell level 4 here, login, xserver, terminal, bash
    # so subtract 3 to get 1 in a normal (non-nested) shell
    echo $((SHLVL - 3))
}

PS1=$'$(if [[ "$?" == "0" ]];then echo "\[\033[32m\]"; else echo "\[\033[31m\]"; fi) $(printf "%8s" "($HOSTNAME)")\e[0m $(printfnchr $(shlvl) "\u2502") '
PS2=$'\[\033[32m\] $(printf "%8s" "($HOSTNAME)") #>\e[0m \u2502 '

rightpromptstring() {
    local tmp=$?
    local dirty=$([[ $(git diff --shortstat 2>/dev/null | tail -n 1) != "" ]] &&
        echo " *")
    local g=$([[ $(git branch 2>/dev/null) ]] &&
        echo " ($(git describe --all | sed 's/^[a-zA-Z]*\///')) ")
    local p=$(pwd | sed "s:^$HOME:~:" | rev | cut -d/ -f 1 | rev)
    local j=$(jobs | wc -l)
    local d=$(date +%H:%M)

    local r=$(echo -n "\u2502 \033[1;30m<<$dirty$g$p [$j] [$d]\033[0m")

    local rl=${#r}
    local t=$(tput cols)
    let "p = $t - $rl + 22"
    printf -v sp "%*s" $p ' '
    echo -ne "$sp$r\r"
    return $tmp
}

PROMPT_COMMAND=rightpromptstring

It is not as complicated as it seems and I'm sure there's room for optimization here and there, but for me it works and it is fast.

Of course, the printfnchr function and also the shlvl function could have been placed right in the PS1 variable, but I want to keep them, maybe I can reuse them later!

The rightpromptstring function is a beast, I know. This would be my first point if I had to optimize this whole thing, but I don't need to, so there is no need to.


I won't go into detail how things work, I assume you know bash. Anyways, feel free to ask me questions about this!


Edit:

To have the pipe character also when logged in via SSH, you have to modify the shlvl function like this:

shlvl() {
    # I'm always on shell level 4 here, login, xserver, terminal, bash
    # so subtract 3 to get 1 in a normal (non-nested) shell
    if [ -z "$SSH_CLIENT" ]
    then
        echo $((SHLVL - 3))
    else
        echo $SHLVL
    fi
}

tags: #linux #bash

This will be a series of blog posts about my experience when switching to NixOS, the Purely Functional Linux Distribution.

It will cover everything: The successes, the issues, the problems, everything you can imagine, including my personal NixOS configuration, so you can learn how to get your feet wet with this blog series.

But, of course, this is not a tutorial on how to write Nix or how to use NixOS. This is an experience report.

The Why

So, why did I switch or do I want to switch? I'm a Archlinux user for more than 7 years now. Archlinux is a great distribution, you can tweak every single bit to fit your needs perfectly. It is truly awesome. But there is a problem with it, I don't want to have anymore: You can really easily break things. You can break your packages by upgrading a version of a library. You can pollute your package database by installing something and shortly afterwards removing it, but forgetting to remove the dependencies it pulled in. You have no option to actually tweak packages. You want emacs? Okay, here is emacs. You want it with GTK3 instead of GTK2? Then, compileit yourself. (I picked emacs as example here because that's the one example on the NixOS page, there is certainly a package for emacs with GTK3 in Archlinux)!

Another big selling point for me is, that NixOS comes with either the stability of Debian, if you want it to, but you can be bleeding-edge like Archlinux if you want to. It's in your hands with NixOS!

Of course, in NixOS, you only have one configuration file for all the things!

Configure all the things!

The How

So, I started playing around with NixOS in a virtual machine. I started with a minimal configuration which is shipped with the system. Of course, I read a lot of blog articles beforehand, so I almost knew what I did. Well, at least I thought, I knew it.

There are great resources online. Well, there are not that much resources around, but at least the ones that are there are really good. My starting point, of course, was the NixOS homepage, the NixOS wiki, but also the great blogging series Nix Pills which explains the Nix language.

What was also worth looking at is the real world NixOS Dotfiles page, where links to dotfiles of NixOS people are collected. Mine are not up there, because I tend to keep my dotfiles private, so you won't find them there. But you find them here!

The requirements

My requirements for NixOS should be listed before I go into detail how I managed to get things done.

Configuration files

So, first, I wanted to be able to track my configurations with git. I track all my configurations with git, as this enables me to mess around with them without actually losing them/information/knowledge/bla. I think you get that point.

Well, that was not much of an issue, actually. I just created a new folder in my dotfiles directory and linked the global NixOS configuration file to it:

mkdir config/nixos
sudo cp /etc/nixos/configuration.nix config/nixos/
sudo chown $USER config/nixos/configuration.nix
sudo mv /etc/nixos/configuration.nix /etc/nixos/configuration.nix.bkp
sudo ln -s config/nixos/configuration.nix /etc/nixos/configuration.nix

As you can see, I backuped the configuration before overriding it, just to be safe here.

Well, this actually works out really well. But! There is a but!

When installing a new machine, you actually cannot do this, because your NixOS installation doesn't know of /home yet (as it is not mounted at this point). To work around this, you simply use the /etc/nixos/confuiguration.nix file until you have set up the basic system!


I also wanted the configuration files to be shareable between several machines, which required me to split them up into several parts. I already described this in another blog post!

KDE!

Well, packages. As I described in the other blog post mentioned above, I have several sets of configuration which I merge into eachother to compile the machine-specific configuration out of several parts then. This works really well and I use it every day!

One big thing I wanted to have was KDE. Yes, me, the Archlinux-i3-minimalistic-terminal-only-loving guy tries KDE. Why? Well, that's another topic!

Turned out that KDE works really good for me! I tweaked some shortcuts, so I'm able to do “tiling” with it (but not with this ugly “Tiling” script for KWin, actually!) so it works really well for me and I really like it.

But there also were some problems, I will tell you later on.

Services

For the services department: I want to be able to run a gitolite instance, I already run a ssh server, synergy (client) and redshift. I did not try the synergy client on my latest install, but beforehand it worked, so I assume it still works. Redshift and ssh work, so that's none of an issue.

What does not work is gitolite. I don't know why, yet, but I will do some further investigation on this.

Overall requirements

Well, one big requirement for me is that things just work. I did not write “work out of the box”, because this requirement was already destroyed when this blog article was written. I don't want to mess around with things every now and then – I want them to work, so I can be productive in things I actually want to do.

So, that's also the reason why I wanted a switch to KDE. I want to use the Kontact suite, including KOrganizer, KMail, KAddressbook and not mutt with abook anymore, which works, but is not that great IMHO. I mean, mutt, yeah! It is awesome and fast and everything. But I cannot do contact managing, scheduling, etc with it. As an email reader it is the best piece of software I ever used and in combination with vim, it becomes even more awesome! But it does not integrate with other tools like an adressbook or day planner.

Also, all these things can integrate my Android phone, which is awesome. I did not try it yet, though.


So, that's enough for the first part. In the next part of the series, I will describe my steps from zero to a basic system and how I installed the configurations and things. Maybe the post will also cover my first problem with NixOS.

Stay tuned!

tags: #linux #nixos

I started my music server after I came yesterday. I mounted the external music hard drive, I started mpd. Then I wanted to start mpdscribble to scrobble to my last.fm account. But it did not start. Here's why.

First, I thought the configuration must be broken somehow. But it looked fine. I had no package update, as I'm running Debian stable on this machine – so no updates for these packages!

I double- and trible-checked the configuration, the method how I started mpd and so on. But I couldn't find an issue. The log file was not written, the journal was slowly filled.

After a while, I noticed that the logfile had an entry for writing to the syslog daemon, which resulted the log to be in /var/log/daemon.log and there I found it: The system time seem'd to be broken. And yes, it was the 28th Dec. 2014. I don't know why, but I guess that's the time when the BIOS battery run out of energy or something like this. Anyways, fixed the system time and got it working!

tags: #music #server #mpd

I'm back from the 31c3, which was absolutely awesome for me! It was my first time at the congress and I met a lot of great people there, so it was a great success.

Richard Stallman, Matthew Garret and other great guys were hanging around at the 31c3, I had a chat with the gnupg maintainer and some students from the Netherlands, people from the Free software foundation and listened to discussions with a gnunet developer.

We, as a project, presented our semester project by giving a lightning talk and hacked a lot on it, too.

So, from my perspective, it were awesome days and I will be there next year again! tags: #programming #software #ccc

So, it's just a few days before christmas, so let me post a short update on waysome! We're currently implementing EGL support and we should be able to implement the API-window interfacing afterwards, which enables one to issue window-moving though the API.

I guess this pretty awesome! Actually, EGL gives us a hard time, because the interface just sucks.

We have already more than 2k commits merged into the development branch, more than 600 issues/pull requests were opened and nearly 600 are already solved. After window moving is implemented, we will start with heavy testing and debugging, to get it to a certain state where it is stable and as much as possible bugs are removed.

I actually hope we can get a basic window manager until the end of the semester, as we're running a bit out of time here.

You are welcome to contribute or just watch it (but we would really prefer that you send us patches, contribute by testing and so on) on github. tags: #programming #open source

I finally made my first steps with NixOS! I started to thnik about how to set up a multi-machine-multi-purpose configuration environment a few days ago, when I wasn't able to sleep half of the night.

And, surprisingly, it works! So here is what I've done...

The idea

My idae was to have one setup which can be combined for every machine I have. So, it must fit:

  • My (future) desktop machine, which will have mutliple drives and multiple monitors. It will be a backup server for my other machines as well. It will be a development/gaming (as little gaming as I do – I still do it)/everything machine.
  • My current main machine: my Thinkpad. It is my current development machine as well as my machine for my university stuff etc.
  • My old notebook, which I play with (in manner of trying out nix configurations). I created the setup on this machine, as it already runs NixOS).
  • My old desktop computer, which is my “home-server” at the moment, mainly for my music and for storage.
  • Eventually for a root server I will have at any time in the future – who knows?

The problem

I had several problems with that. None of these machines will have the same setup, none of them need all packages and hell none of these machines will have the same services running. But all of them will have packages from a specific set of packages. Some of these machines will have the same services with the same configurations. So, I created a matrix of packages and one of services.

Packages

(Well, lets leak my new host names here as well...)

|           | Package-Set   | base  | dev   | desktop   | server    |
| Machine   |               |       |       |           |           |
| --------- | ------------- | ----- | ----- | --------- | --------- |
| lucy      |               | x     | x     | x         | x         |
| nyu       |               | x     | x     | x         |           |
| nox       |               | x     |       | x         |           |
| light     |               | x     |       |           | x         |

Explanation:

  • Hostnames, retreived from “Elfenlied” and “Deathnote” (nox is the opposite from “lumos” from Harry Potter)
    • “lucy” will be my tower machine
    • “nyu” will be my thinkpad
    • “nox” will be (and already is) my second notebook
    • “light” will be my home server
  • Packages
    • “base” is just the basic stuff, like “awk”, “vim”, “coreutils”, htop, etc
    • “dev” is my development stuff, so vim, gdb, git, cmake, make, valgrind, ruby, python, haskell, lua, etc.
    • “desktop” is everything graphical, so a browser, email client, irc client, etc.
    • “server” is everything which a server needs, so things like htop and other utilities

Maybe I will create even more package sets for music, music modifying (tags for example), music creation, movies, gaming, etc. But these are the basic sets I actually created.

As you can see, all hosts will get the basic package set. All desktop machines and notebooks will get the desktop set and just lucy and light will get the server set. Development will be on my current and my future main machine, but not on nox.

Services

When it comes to services, there are also some stuff each hosts needs and others don't:

|           | Service-Type  | X | synergyClient | sshServer | printing  |
| Machine   |               |   |               |           |           |
| --------- | ------------- | - | ------------- | --------- | --------- |
| lucy      |               | x |               |           | x         |
| nyu       |               | x | x             | x         | x         |
| nox       |               | x | x             | x         |           |
| light     |               |   |               | x         |           |

Explanation:

  • “X” is the x server including my i3 setup and so on
  • “synergyClient” is the synergy configuration for the client
  • “sshServer” – nothing to explain here, I assume
  • “printing” – nothing to explain here as well...

Of course, lucy won't have the ssh server enabled (maybe it will, but I'm rather sure I won't need it on lucy). It will be the synergy server, so it doesn't need a synergy client configuration as well.

Filesystem

I already mentioned that lucy will be a storage server as well as my main machine. I'm currently thinking about a 2 * 2 TiB configuration for the host itself but attaching 2 * 1 TiB and 1 * 2 TiB external USB storage as well. This would make “light” outdated, as this is my storage machine by now, but I will continue using it to play around with, especially with NixOps maybe.

So, I have a different filesystem configuration for each host. But that's not a problem, as the next section shows...

The Solution

Of course, this was not everything. More services, more package sets and so on will follow, but they can be attached to my current setup really easily.

So, how did I do it? First, I want to thank “Lethalman” from the NixOS IRC channel, he helped me a lot!

So, I have a base configuration file, which looks like this:

{ config, pkgs, ... }:

{
  imports = [ # Include the results of the hardware scan.
    /etc/nixos/hardware-configuration.nix
  ];

  # Use the GRUB 2 boot loader.
  boot.loader.grub.enable = true;
  boot.loader.grub.version = 2;

  networking.firewall = {
    enable = true;
    allowedUDPPorts = [ ... ];
  };

  # Select internationalisation properties.
  i18n = {
    consoleFont = "lat9w-16";
    consoleKeyMap = "de";
    defaultLocale = "de_DE.UTF-8";
  };

  users.defaultUserShell = "/var/run/current-system/sw/bin/fish";

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.extraUsers.m = {
    name = "m";
    group = "users";
    uid = 1000;
    createHome = true;
    home = "/home/m";
    extraGroups = [ "wheel" "audio" "video" "power" ];
    shell = "/var/run/current-system/sw/bin/fish";
    openssh.authorizedKeys.keys = [ ... ];
  };

  time.timeZone = "Europe/Berlin";
}

(sadly, the fish shell does not work yet and I don't know why).

As you can see, the grub configuration is just partly set, I did not mention on which drive grub shall be installed. Of course, this follows in the host-specific configuration file:

{ config, pkgs, ... }:

let
  configDir = /home/m/config/nixos;
in

{
  imports = [
    # Base configuration
    "${configDir}/base-configuration.nix"

    # Filesystem additions
    "${configDir}/fs/tmpfs.nix"

    # Services
    "${configDir}/services/synergyClient.nix"
    "${configDir}/services/x.nix"
    "${configDir}/services/sshServer.nix"
    "${configDir}/services/printing.nix"
  ];

  # Define on which hard drive you want to install Grub.
  boot.loader.grub.device = "/dev/sda";

  networking.hostName = "nox";
  networking.wireless.enable = true;

  nixpkgs.config = {
    allowUnfree = true;

  # Overrides for chromium, as stated in http://nixos.org/wiki/Enable_Browser_Plugins
    chromium = {
      enablePepperFlash = true; # Chromium removed support for Mozilla (NPAPI) plugins so Adobe Flash no longer works
        enablePepperPDF = true;
    };
  };

  environment.systemPackages = let
    basePkgs    = import "${configDir}/pkgs/basePackages.nix" pkgs;
    devPkgs     = import "${configDir}/pkgs/devPackages.nix" pkgs;
    desktopPkgs = import "${configDir}/pkgs/desktopPackages.nix" pkgs;
  in
    pkgs.lib.attrValues (basePkgs // devPkgs // desktopPkgs);

}

In this file, which is the host configuration for “nox”, I put grub on “/dev/sda”, included some service configuration files and imported some package sets as well as I did some more host-specific configuration.

The service files would look like this:

{
  # Enable the X11 windowing system.
  services.xserver = {
    enable = true;
    layout = "de";
    xkbOptions = "eurosign:e";

    # Display manager configuration
    displayManager.slim.enable = true;

    # Enable the i3 window manager.
    windowManager.i3.enable = true;
    windowManager.default = "i3";
  };
}

for the X-Server configuration. The package files look like this:

pkgs: {
  inherit (pkgs)
  acpid
  acpitool
  bashCompletion
  ...
  zip
  ;
}

And it works like a real charm!

Even more beneficial...

I can actually put this in a git repository. I actually already did this! I have a git repository on the host which will be named “nyu” after the port to NixOS. This git repository contains all my dotfiles. At the moment, I run Archlinux (without nix) on this machine, but I will keep the dotfiles repo, of course, and this enables me to just get the git repository and start using the already modified dotfiles.

More hosts can now be added really easily, as I just have to write one file for them, including everything I need from the other files and add some custom flags and configurations if I want. This file gets then symlinked from /etc/nixos/configuration.nix and I can run nixos-rebuild switch and I'm ready – setup for the machine and dotfiles are present and I can start using it! Awesome!

If you have suggestions how to improve this setup, let me know. If this article helped you with your setup, let me know as well!

tags: #linux #nixos

When creating an open source project it is really important to get stuff done and working as fast as possible. As soon as the initial project phase is over, things calm down and if the stuff is not working properly at this point, people lose interest.

So, you should try really hard to avoid that and get stuff done as fast as you can, so you have something to show. This does not mean that your stuff should be complete or everything should work as expected, but you should be able to show some basic features of the software, so you can inspire others to hack on the project and improve it.

Because that's what keeps a project living: people and contributors which want to bring the project forward. And if you can show them things, they might get enthusiastic about the project and start contributing!

So, you should try really hard to get something which basically works.

Speaking of my semester project, we're almost at the point where we have something which basically works. We have some very basic functionality, which means we can start a terminal and use it (not everything works as it should, but we're working on it). So, we can show something.

The problem with software is that you don't actually see what amount of effort is put into it. An experienced programmer can, of course, see it, but not the average guy from the street. So, with complexity of software and source code, the need to get something which basically works and can be used, increases rapidly. We in our project have written source code since end of September, we just hit and passed the 30k LOC mark. That's great, because we have a great infrastructure of code, which is really powerful in my opinion. But, by now, we “only” can start a terminal and have some background image. We are not yet able to do more things. This will change in the next few weeks, but by now, a user can only see some really basic stuff. But there's a huge amount of effort put into the project.

The User can't see it. This is were things get complicated (also in regard of our assessment of our supervising professor). As soon as some more infrastructure is merged, we can actually start implementing the API, which can then be used to actually show things, so we hopefully won't have this problem in a few weeks anymore. But until then, I consider this stuff as really critical.

We also have to provide a documentation of the project phase, which will be included in our grading as well, so at least that is not as ciritcal as it seems, but I would really love to have a working software at the end of the project phase. And by now, I don't see we get there. It is not that much left to do, but much enough...

So, in my humble opinion, it is really important that one gets working stuff (in a open source project), so it can be shown to others and can advertise itself thereby.

tags: #programming #open source

So I had a post about my frustrations on programming languages some time ago (the actual date of the previous article on the topic is not right, because I did some blog switching foo since). With this article I try to rethink the whole problem. My conclusion will be different from the conclusion of the previous article!

Haskell, Racket and the others

So, I said in the last article that I want to have a look into the following programming languages:

  • Haskell
  • Go
  • D
  • Crystal

And well, I learned a bit of Haskell and it is an awesome language from what I can see so far. But then things changed, I started a semester project I'm now heavily involved in, which is in C. I also had several programming courses at my university where the requirement was C++ and Java, so things got stuck somewhere. I stopped learning Haskell. Sadly.

But in the past few days and weeks, I got my head into a new programming languages, as the careful reader of this blog already knows: Racket. Racket is a Lisp dialect. I comes with an wonderful documentation, a rich feature set (a nice REPL, a documentation tool, package manager which works really well and tries to avoid the dependency hell), is fast and easy to both read and write (at least from what I can tell by now). Racket is kind of my new love in manner of programming languages. I started learning it by implementing problenms from project euler and I want to write a small IRC bot in it, as soon as I consider myself as advanced enough to achieve this.

So, Racket is a functional programming language, but also supports non-functional programming paradigms. This basically means that you also can write OOP-stylish and imperaitvely in Racket. You might say “Yuck!” now, because it is not a pure functional language – but it is really good for me, and I can get my feet wet with functional programming slowly! This matters most for me!

The other languages listed are less important for me. I don't want to learn Go, D or even Crystal anymore. I think, functional programming languages are my next (kind of) goal in life. A lot of people state that they became better programmers after learning a functional language (Haskell in particular). And because my overall goal is to become better at what I love doing, I consider functional programming as one of my main goals in life now. That may sound really vain or limited, but well, I also have other goals in life! They just don't fit into this article, of course!

So,... Haskell?

My goal is still learning Haskell some time, and I will, as soon as I consider myself a good Racket hacker! But for now, Racket has a better learning courve for me. I read a lot about the functional programming languages out there, mainly Lisp/Scheme like languages and Haskell. And a lot of people state that Haskell is a bit more advanced because of its syntax, because you have to consider operator prescendence and some other things, which you don't have to care about in Lisps. So, I can start with a simple language, learning the functional approach, and continue with something like Haskell afterwards.

I saw a wonderful explanation on youtube on Monads just yesterday. I understand everything in this video, except the fourth part, which actually covers Monads. This is also one of the points why I don't start away with Haskell. I want to fully understand the concepts first.

It would be really great to have a course about functional programming at my university, but unfortunately there is none. One Prof has a by-choice-event students can subscribe to, but unfortunately not this or next semester. I hope I will be able to attend the course in one year.

If not, I hope I can do something with functional programming in my bachelors thesis or in my masters degree, if I continue studying. Would be neat. If not, there are maybe some non-university courses around.

But is Racket fulfilling?

Of course it is! You can actually do everything you can do in pure functional programming languages! I just found out how to do function composition and partial application of functions. It is not as simple as in Haskell, but it works exactly the same way (don't consider my statements here too serious, I'm just learning and it feels like it is the same...).

For example, we have this smart piece of Haskell code here:

take5 = take 5

take5 is now a function which is composed of passing 5 to the take function. It takes now 5 values from a list and returns them as new list. Wonderful and simple!

But you can also do this in Racket. I don't know how to do this problem in Racket, as the take function in Racket expects the list as first argument and the number as second. So would need to switch arguments, and I actually don't know how to do this in Racket.

So lets do another example of partial application:

(define (add1-to-list)
  (curry map add1 ))
(add1-to-list (list 1 2 3))
; -> '(2 3 4)

As you can see, I created a function which returns a function that maps the add1 function on a list. Afterwards I applied this function to a list. So it is the same as in Haskell, but with a bit more verbosity, of course.

Side-note: I just found out (thanks to the Racket IRC channel) how to do flipping of arguments:

(define-syntax (flip stx)
  (syntax-case stx ()
                   [(_ f x ...) #`(f
                                   #,@(reverse (syntax->list #'(x ...))))]))

That's the syntax rule, but it is very verbose. Using it is rather short:

(flip / 12 4)
; -> 1/3

But not as nice as you can do it in Haskell. But anyways, that's hairsplitting and I will end this here and now.

Conclusion

  • Racket is awesome.
  • Haskell is Awesome.
  • Functional programming is awesome.
  • Yeah!

So, to finallize this article now: I'm learning functional programming! It is awesome, concise and clean. It seems to be the best approch to abstract complex problems and address the problem of complexity and abstraction (wanna know more about this, watch the linked youtube video)! I'd love suggestions on tutorials, papers and other reading material to get better. Feel free to send me everything you might consider as a good starting point to get my feet even more wet.

tags: #programming #haskell #racket

I already wrote about the project me and some friends at my university are currently doing. One of my team mates came up with the idea of porting the codebase from C to C++, yesterday the appropriate issue was opened Yesterday, to discuss it. I'm not sure what to think.

The idea is to port the codebase as soon as possible to C++. I do not like this idea entirely, as I think the port should be done after the project phase, but not within. I consider myself at a newbie-like level when it comes to C++ and I think other project members feel almost the same, maybe better, but not on an expert level or whatsoever. Given the fact that we're already running out of time, I think a port of the (30K LOC) codebase would quite take some time and would cause the project to be delayed even more.

So I'm trying to push back on that part. A port after the project phase would be another question, which I want to talk about here.

First of all: I don't think a port to another language is required, as I consider the codebase as very clean and carefully designed. The architecture is good, the code is well documented, the abstractions are clearly defined. A port to another programming language would have a certain level of impact on this, but I think we are able to handle that. I see the improvements which could be made by a port to a OOP(-like) language, though.

Having inheritance build into the language, having a template-like system in the language and having methods, virtual functions and the like would cause some redesign but also some improvements.

My project mate suggested C++ as language. Now, the careful reader knows that I don't like C++ that much. Some of my points are maybe valid, some not. But well, this is a very opinion-based topic, and I won't go into further detail or discussion about that topic here. What I think, though, is that it would be nice to port to a language which gives us more power (simplifying to the terminus “power” here to refer to possibilities to do abstractions, building complexity and the like) and security. I think C++ gives us more power about the code, which is very good. I don't think C++ gives us more security, meaning secure code. I think one can very simply do the same mistakes in C++ as in C, speaking of semantics of the code. For example you can create data races, thread related problems or memory corruption in C++ as well as in C.

That given, I consider C++ as an improvement to the code, but not the best possibility. My opinion is currently that a port to Rust would be a much better option, as Rust gives us memory safety, prevents us from doing nasty things with memory, including all the thread stuff. Given the fact that none of us is able to write Rust on an expert level by now, the question of doing the port within the project phase or after is answered automatically. Also, Rust is not stable yet. I would at least wait for version 1.0 of the Rust language before doing the port, possibly saving some time of Rust-to-Rust porting.

I still don't think a port is necessary and I really like the code we produce. I can see the advantages over staying in C, but for me personally, the disadvantages overweight by now. This may change in future, but for now and for the rest of the project phase, this is my opinion on the topic.

The discussion on github is not done yet, of course. I will carefully propose my opinion there, as this has become a very explosive topic by now. This article was just written to be a short overview over the topic and also to be a summary of my thoughts.

tags: #programming #c #rust #c++ #software