notes.wrycode.com

1 Introduction   export meta

This page contains notes written in Org mode which are automatically converted to HTML and published when I update them.

The idea is that without changing my note-taking workflow, I can easily share notes that could be useful to others. With that in mind, pretty much nothing here is "finished".

Everything is on this one page with two exceptions: the reading/ directory, where I archive some things I read, and my Emacs configuration and notes.

2 Writing Checklists   export

Some guidelines for better writing.

The most important habit is obviously to write multiple drafts, dropping useless words with each one. Consequently, these are mostly tips to remove some of the ugly, easy-to-fix flaws in my writing.

See also: Software For Writers: Tools To Improve Your Writing and Writing Checklist - Gwern.net.

2.1 writing quality

  • add examples, especially if something isn't crystal clear
  • humanize the writing
  • remove or rewrite references that a high schooler wouldn't understand
  • remove unoriginal metaphors or examples
  • remove hedged phrases, weasel words
  • switch passive phrases to active (usually)
  • remove any foreign phrases, scientific words, or jargon that aren’t necessary
  • read out loud and check for flow
  • remove direct criticisms of other people
  • remove or acknowledge cliches
  • search for “ly” words and remove them (sometimes)
  • remove exclamation marks
  • remove commas that aren't necessary (e.g. before "too" at the end of a sentence)
  • strip needless words
  • check reading level
  • have other people read it and get their reaction

2.2 generic pre-publishing checklist

  • Title: descriptive, specific, short, unique
    • interesting? (no clickbait)
  • check for broken or redirected links and fix them
  • included sources and external references
  • make sure formatting is correct and looks good
  • link to related writing
  • summary for longer pieces
  • bold important parts. Use italics when appropriate.
  • spell check
  • grammar check

2.3 personal style

  • unless it's necessary for expressing a complex idea, remove sentences that really belong in an essay
  • remove unnecessary semicolons, commas, and parentheses
  • remove informal language
    • with the exception of sentences that are intrinsically personal because they involve myself. See the next section:

2.4 instructional writing

It's hard to stick to my personal writing style when writing instructions or generic computer science miscellany. It's useful to refer to the person doing the actions, but unclear who they are – us, me, or you? I've settled on "us" being the best choice (even in material that's not intended as an informal guided tutorial).

Switching between "we" and "I" is a natural way to create this kind of material despite its informality, and it allows me to easily disambiguate between concrete, established information and more tenuous anecdotal stuff.

I even use it in school. For instance, here's an excerpt from a formal Statistics project:

To simulate drawing a single sample in Excel, we can click Data>Analysis>Data Analysis>Sampling to generate a single sample of 10 out of our 500 candy bars. Unfortunately, I couldn't find a way to get this as a formula in Excel in order to automate finding the mean. Luckily, we can copy the whole column from Excel into a text editor. Here's an example program to generate the distribution of sample means:

  // the copy/pasted candy bar weights from Excel:
  distribution := []float64{19.985522684567343, ..., 21.081192987199796}

// (truncated code)

Expressing these types of sentences with only formal language would mean either

  1. rewriting the sentences in a way that changes the intended meaning and removes information, or
  2. awkwardly using anonymous pronouns, e.g. "one could copy the whole column from Excel…" (or, even worse, mentioning "the programmer" and referring to them with he/she/they as if they are someone other than the person reading the text)

3 Influences/Inspiration   export

Here are some websites that have inspired or influenced this website:

The actual code for this website is a modified version of org-notes-style.

4 Cross-compile a GTK3 app from Linux to Windows with native Windows look and feel   export

One of my research projects involves writing a Windows app for a department at my school. I only run Linux.

Here I've compiled the steps necessary to build and run a GUI GTK3 program on both Linux and Windows.This includes the frills most Windows users expect, like a graphical installer, an icon on the executable, and a program that looks like it was made for Windows.

You can view the results of the tutorial in this repository.

Create the demo C program from the GTK documentation and save it as main.c.

To compile the code on Linux, a simple

$ gcc -o main main.c `pkg-config --libs gtk+-3.0 --cflags gtk+-3.0`

will do the trick (you need pkg-config, GCC, and GTK3 installed). Test the executable to make sure it works:

$ ./main

4.1 Windows setup

To build for Windows, you need to use MinGW to compile the executable, and then you need to bundle the MinGW GTK dlls so they're available at runtime on Windows.

First install MinGW. If this step seems insurmountable, or if you're running Arch Linux or a similar distro, just skip ahead to the Buildah section.

On Fedora, for example, you can install everything you need with this command:

dnf install mingw64-gtk3 mingw32-binutils mingw32-nsiswrapper

4.1.1 Compiling for Windows

On a Linux system with MinGW installed, you can compile the same program with something like:

$ x86_64-w64-mingw32-gcc -o main main.c `mingw64-pkg-config --cflags gtk+-3.0 --libs gtk+-3.0`

You should now have an executable called main.exe. Obviously this won't work on Linux, but it also won't work on Windows until you make the GTK libraries available to it at runtime.

4.1.2 Bundle GTK libraries

Make a subdirectory called windows and copy the .exe into it. Now copy the MinGW libraries over to the same folder. Unfortunately, different Linux distributions have different locations (and sometimes even different names for the MinGW executables). On Fedora, they're found at /usr/x86_64-w64-mingw32/sys-root/mingw/*.

4.1.3 Test on Windows

If you copy the whole windows folder to a Windows computer or VM, the program should now run as expected. Magically enough, WINE is also able to run the program from Linux (although I don't recommend testing with WINE).

However, the program looks like bad because it uses GNOME's Adwaita theme (which looks bad on Windows), it uses GTK to render the client-side decorations (the top of the window with the exit button), there's no icon for the program in Windows' taskbar, and the program runs with a black command prompt window in the background. Furthermore, it's not ideal to distribute the program by zipping up this folder and sharing it.

4.1.4 Fix Icon

Download or create an icon, or use this example icon. From within the code you can set the icon for the program like this:

GdkPixbuf *icon;
icon = create_pixbuf("icon.ico");  
gtk_window_set_icon(GTK_WINDOW(window), icon);

The code for create_pixbuf is:

GdkPixbuf *create_pixbuf(const gchar * filename) {

   GdkPixbuf *pixbuf;
   GError *error = NULL;
   pixbuf = gdk_pixbuf_new_from_file(filename, &error);

   if (!pixbuf) {

      fprintf(stderr, "%s\n", error->message);
      g_error_free(error);
   }

   return pixbuf;
}

This will change the icon of the program while it's running. It shows up correctly in the Windows taskbar and window decorations, but it won't change the icon of the actual .exe. I still recommend including this code, because it works to set the icon on Linux desktop environments.

To change the icon of the executable file on Windows, we have to use MinGW's windres utility. Create a file called "icon.rc" with the contents:

id ICON "icon.ico"

and then run:

x86_64-w64-mingw32-windres icon.rc -O coff -o icon.res

Now we can add the icon.res resource file to the executable by slightly modifying our GCC call:

$ x86_64-w64-mingw32-gcc -o main main.c icon.res `mingw64-pkg-config --cflags gtk+-3.0 --libs gtk+-3.0`

Now the actual .exe file will have an icon associated with it on Windows.

4.1.5 Remove Command Prompt window

Just add the -mwindows flag to your compile command.

4.1.6 Fix Window Decorations

You can disable the GTK client-side decorations by adding the following line to the code:

putenv("GTK_CSD=0");

Now the program should use the normal Windows exit button and drag bar.

4.1.7 Switch to a Windows GTK theme

Adwaita looks bad on Windows. Search Gnome-Look for a different GTK3 theme to use with your app. You can choose a flatter, lighter theme or one specifically made to look like Windows. For this example, I chose the "Windows10" theme.

Download and extract the theme, then copy it to the share/themes/ directory in the windows/ directory we've been using.

Then create a file called settings.ini in a etc/gtk-3.0/ folder (also in the windows/ directory) with the following contents:

[Settings]
gtk-theme-name=Windows10

Now the program should look like native Windows software:

main_gtk_tutorial_screenshot.png

4.1.8 Generate an installer

Here's how to make an installer so your users don't have to manually unzip this windows/ folder which uses a script called nsiswrapper. Nsiswrapper generates an NSIS script and optionally compiles it using makensis.

cd into the windows/ directory, and run:

nsiswrapper --run main.exe ./*

This should generate a new file called installer.exe, which you can use to distribute the program. The installer is a standard GUI wizard that Windows users will be accustomed to. It allows users to optionally add a desktop shortcut, start menu entry, and taskbar shortcut.

Notably, it also includes an uninstaller.

4.2 Automation + Buildah

You may have noticed that I've been using Fedora to compile this program. I'm actually running Arch Linux, but MinGW packages aren't easily available for Arch, so I've been using a Linux container to take advantage of Fedora's package system.

I'm using Buildah instead of Docker. I wrote a script to automate the following tasks

  • set up a named fedora container
  • install the necessary packages using dnf
  • save the container so I don't have to download dependencies again
  • compile the GTK program using the steps I've outlined so far
  • generate the installer

Before you look at the script, I recommend reading the buildah introduction tutorial.

#!/bin/bash
setup () {
    # Create a fedora container
    container=$(buildah from fedora)

    # Install dependencies 
    buildah run $container dnf -y install mingw64-gtk3 mingw32-binutils mingw32-nsiswrapper 

     # Fix typo in mingw library
    buildah run $container bash -c "sed -i -e 's/-Wl,-luuid/-luuid/g' /usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/gdk-3.0.pc"

    # Cache image to avoid re-downloading dependencies every time
    buildah commit $container my-gtk-app

    # Clean up
    buildah rm $container
}

build () {
    # Create a new container from the base one we created
    container=$(buildah from localhost/my-gtk-app)

    # Folder to hold everything needed for the windows installer:
    output_folder=windows
    yes | rm -r $output_folder
    mkdir $output_folder

    # Directory of your package in the container
    folder=/root/app

    # Copy program into container
    buildah copy $container . $folder

    # Name for the executable file on Windows
    executable_name="Demo.exe"

    # make some folders we'll need
    buildah run $container bash -c "cd $folder && mkdir -p $output_folder/share/themes $output_folder/etc/gtk-3.0"

    # generate a RC file with the windres utility to embed an icon into the .exe later on
    buildah run $container bash -c "cd $folder && x86_64-w64-mingw32-windres icon.rc -O coff -o icon.res"

    # copy some project resources
    buildah run $container bash -c "cd $folder && cp -r Windows10 $output_folder/share/themes && \
    cp settings.ini $output_folder/etc/gtk-3.0/ &&\
    cp icon.ico $output_folder"

    # Compile program
    buildah run $container bash -c "cd $folder && x86_64-w64-mingw32-gcc -mwindows -o $executable_name main.c icon.res \`mingw64-pkg-config --cflags gtk+-3.0 --libs gtk+-3.0\`"

    # Copy executable into installation folder
    buildah run $container bash -c "cd $folder && cp $executable_name $output_folder"

    # Copy mingw dlls into installation folder
    # This part may need to be personalized
    buildah run $container bash -c "yes | cp -r /usr/x86_64-w64-mingw32/sys-root/mingw/{bin/*.dll,share} $folder/$output_folder/"

    # Generate an installer
    buildah run $container bash -ic "cd $folder/$output_folder && nsiswrapper --run $executable_name ./*"

    # Copy the output from the container
    cp -ru $(buildah unshare buildah mount $container)$folder/$output_folder .

    # Clean up
    buildah rm $container
}

# This just checks whether the container already exists on your drive
buildah inspect localhost/my-gtk-app &>/dev/null
return_value=$?

if [ $return_value -eq 1 ]
then
    echo "Initial container setup"
    setup
fi

# Build project
build

5 Sane multilingual Emacs keyboard experience   export

The default location of the Ctrl key is wrong for Emacs users.

Desktop users have several layers of modifier keys that should be organized by their use frequency. For the average user, Shift is probably the most common modifier, followed by Ctrl, Alt, and Super (the Windows key). This is about the same for Windows and Linux desktops. Linux users who use a tiling window manager may find the Super key higher up on the list.

Emacs requires constant use of the Ctrl and Alt (or Meta) keys, upending that balance. Ctrl clearly needs to be moved. A common suggestion is to switch CapsLock and left Ctrl1, which is still unsatisfactory. Ctrl is used so much that pressing CapsLock with your pinkie will still cause strain and eventually injury.

Instead, remap the right Alt to Ctrl.

For the X keyboard extension the option is called ctrl:ralt_rctrl.

This interferes with typing accented characters in other romance languages. I need to type Spanish without losing quick access to ', `, and ~ for programming. The only sane way to do this is with the altgr-intl layout, which uses right Alt as a level 3 modifier for the accented chars. The solution is to set the level 3 modifier to CapsLock, and overwrite right Alt back to Ctrl.

Set the following X Keyboard settings using whichever method you prefer:

layout: us(altgr-intl) (or layout: us and variant: algr-intl)

options: lv3:caps_switch (set this first) and ctrl:ralt_rctrl

6 Arch Linux install with Encrypted / and Suspend to Disk   export security Linux

6.1 Format Drive

  • cfdisk /dev/nvme0n1
    • choose GPT partition table
    • make a 100M partition for /boot/, toggle it bootable, and change its type to EFI System
    • make the remaining free space one Linux filesystem partition

6.2 Encrypt root partition

  • cryptsetup -v luksFormat /dev/nvme0n1p2
  • open the partition: cryptsetup open /dev/nvme0n1p2 crypt

6.3 Write and mount filesystems

  • mkfs.fat -F32 /dev/nvme0n1p1 (this will be /boot/)
  • mkfs.ext4 /dev/mapper/crypt
  • mount /dev/mapper/crypt /mnt/
  • mkdir /mnt/boot
  • mount /dev/nvme0n1p1 /mnt/boot

6.4 Install system

  • pacstrap /mnt base base-devel networkmanager xf86-input-libinput xf86-video-intel intel-ucode
  • genfstab -p /mnt >> /mnt/etc/fstab

6.5 Chroot in and configure system time, language, etc

  • arch-chroot /mnt/
  • echo "my_hostname" > /etc/hostname
  • ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime
  • systemctl enable systemd-timesyncd.service
  • uncomment language in /etc/locale.gen
    • locale-gen
    • locale > /etc/locale.conf

6.6 Set up Kernel and Bootloader

  • edit /etc/mkinitcpio.conf and put encrypt and resume before filesystems in the HOOKS array:
HOOKS=(base udev autodetect modconf block encrypt filesystems resume keyboard fsck)
  • generate ramdisk:
    • mkinitcpio -p linux

6.7 Set up Swap to enable suspend to disk

  • fallocate -l 1G /swapfile
  • chmod 600 /swapfile
  • mkswap /swapfile
  • swapon swapfile
  • and add the following to fstab:
  • /swapfile none swap defaults 0 0

6.8 Install Bootloader:

  • pacman -S grub efibootmgr
  • grub-install --target=i386-pc /dev/nvme0n1
  • edit /etc/default/grub, set timeout to 0 and add the following kernel parameters:
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet ec_sys.write_support=1 cryptdevice=/dev/nvme0n1p2:crypt psmouse.synaptics_intertouch=1 resume=/dev/mapper/crypt resume_offset=117215232.."
  • (the value for resume_offset can be found by running:
filefrag -v /swapfile | awk '{if($1=="0:"){print $4}}
  • grub-mkconfig -o /boot/grub/grub.cfg

6.9 User and root setup

  • set root passwd: passwd
  • useradd -m -g wheel -G audio video vboxusers -s /bin/bash <username>
  • optionally add other users
  • passwd <username>
  • visudo
  • systemctl enable NetworkManager.service
  • Now is a decent time to make sure you can boot into the system. Also try a systemctl hibernate. The system should require the encryption passphrase but correctly restore saved state.

6.10 Enable Automatic Login on Boot:

systemctl edit getty@tty1:

[Service]
ExecStart=
ExecStart=-/usr/bin/agetty --autologin <username> --noclear %I $TERM

6.11 Power Management

  • pacman -S tlp tcacpi-bat x86_energy_perf_policy
  • systemctl enable tlp.service
  • systemctl enable tlp-sleep.service
  • systemctl mask systemd-rfkill.service
  • systemctl mask systemd-rfkill.socket
  • edit /etc/default/tlp

6.12 Security

  • run firecfg as root
  • MAC address spoofing:
    • to turn it on by default, edit /etc/NetworkManager/NetworkManager.conf and add:
[connection]
wifi.cloned-mac-address=random

[connection]
ethernet.cloned-mac-address=random
  • Now every new connection (including new connections to the same network) will have a random MAC address

6.13 Audio

  • pacman -S pavucontrol alsa-utils
  • run alsamixer to balance channels

6.14 Miscellaneous configuration

  • edit /etc/pacman.conf
  • set up fast pacman mirrors:
    • pacman -S pacman-contrib
    • cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak
    • edit the .bak to uncomment nearby servers
    • rankmirrors -n 6 /etc/pacman.d/mirrorlist.bak > /etc/pacman.d/mirrorlist

7 Packing List   export

  • backpack, sleeping bag and tent
  • daypack
  • sleeping pad
  • crocks/sandals
  • hiking shoes, running shoes, street shoes
  • toilet paper
  • toothbrush and toothpaste
  • baby wipes
  • razor, shaving cream
  • stove, matches, fuel
  • eating utensils, camping skillet, bowl, insulated mug
  • water bottles
  • water filter, iodine
  • trash bags and ziploc bags
  • rope to tie up food
  • hammock, extra rope
  • tarp
  • hat, sunglasses
  • socks
  • underwear
  • thermals/sweatpants
  • short sleeve shirts
  • long sleeve shirt/sweater
  • rain jacket
  • shorts
  • fancy clothes
  • climbing harness, shoes, chalk, carabiner, rope
  • pocketknife, hunting knife
  • whetstone, honing steel or strop
  • flashlight, headlamp
  • emergency survival kit
  • emergency medical supplies
  • maps, cash, id
  • extra copies of government IDs, insurance, kin contact information
  • extra copy of travel itinerary in case of disappearance
  • tea
  • food
    • sardines, nuts
    • bagels and locks
    • freeze dried food
    • oats, rice, beans
    • apples and fruit
    • onions
    • seasoning, oil
  • burner cell phone
  • power bank
  • solar charger
  • laptop, case, charger

8 Publishing a website from Org-mode (old method)   export meta notes

These are notes from an older version of my site where I used go-org to generate pages from separate .org files.

8.1 editing webpages   important

There are some differences when writing a page in Org mode instead of Markdown:

  • To insert a link, type C-c C-l, which will prompt for the link and then the description. If you have already written the description, highlight it and type C-C C-l.
  • To insert a source code block, type <s and press Tab. Emacs will automatically insert a source code block. For inline code, surround the text with = instead of `.

8.2 go-org

Niklas Fasching's go-org is a complete Org mode parser which makes it easy to generate a website with a simple Go script. I've been running through a couple of files like drafts.org, posts.org, and journal.org and creating a new page for each top level heading.

d1 := org.New().Parse(f, "./") // new org.Document

for _, heading := range d1.Nodes { // for each heading in the file

        // pull full content of the heading as a new org.Document
        input := strings.NewReader(heading.String())
        d := org.New().Parse(input, "./")

8.2.1 properties

To add metadata to a post, just use org-set-property on the heading, which will add a new entry to the PROPERTIES drawer. For Boolean values I've just been adding a key with an empty value if it's true, otherwise my code assumes it's false. This way you can easily add keywords, summaries, and other meta tags. From the previous example, the properties would be stored at d.Outline.Children[0].Headline.Properties.

8.2.2 dates

You can store dates in the PROPERTIES drawer, of course, but if you want the title of a post to be a formatted date, just insert a timestamp (C-c .) and use something like this to reformat:

layoutUS  := "January 2, 2006"

        // set title
        switch t := d.Outline.Children[0].Headline.Title[0].(type) {
        case org.Timestamp: x.title = t.Time.Format(layoutUS) // format the date if the title is a timestamp
        default: x.title = t.String() // otherwise just use the heading as the title
        }

8.2.3 bugs/idiosyncrasies

A multiline list item followed by a heading needs to be indented extra, otherwise the heading will show up as part of the list:

- item 1
- item 2, a multiline item Lorem ipsum dolor sit amet, consectetur 
    adipiscing elit. Aenean quis semper orci. Aenean a est eu est
    dapibus. Nam felis libero, dapibus a maximus ut, condimentum .

 * Heading

9 Journal   export

Note: some of the posts older than October 2019 mention parts of the older website I hosted them on (plain wrycode.com, where I have a very simple homepage and resume) which don't exist anymore. With a few small exceptions everything from that website has been moved to this page.

9.1 October 18, 2019

9.1.1 Website Updates

edit: This post is out of date. I now simply use org-export from within Emacs and some custom CSS.

A couple of weeks ago I finally got around to something I've been wanting to do for a while: rebuilding this website. I previously was using a custom Common Lisp script that converted Markdown files to html posts. I found it limiting so I decided to try something different: my entire website is now written in Org mode files. I have one file for each category of posts (like notes or journal entries) and a separate heading for each post.

Benefits:

  • All posts of a certain type are in one file, so I can more easily refer to them and do things like renaming or reordering them
  • Org mode has builtin support for things like dates, custom properties (the PROPERTIES drawer is kind of like YAML front matter used in Hugo and Jekyll), tags, tables, and source code blocks
  • I already use Org mode (and Emacs) for planning and note-taking, so this integrates with my workflow. I can capture or refile notes, links and thoughts directly into my website pages.
  • Org mode is a more complete markup language than Markdown.

There are some drawbacks to this approach:

  • This is a lonely route.
  • Overuse of exotic Org features could make it difficult to export content in the future compared to Markdown

I took some notes on the Go code for this method.

In terms of organization and content on this website, I've made some minor changes:

  • I've added the notes section, where I want to keep ongoing, longer-form pages about certain topics (inspired by Gwern's long-term essays, among other things) and random notes and lists that someone other than myself could find useful.
  • The journal is no longer front-and-center, instead the homepage shows a list of blog-style posts. I don't have any "posts" yet, but I want a platform set up for if I have something interesting to write in the future. I also set up an archive for older posts.

9.1.2 URCA, Buildah

Work on my data vis project for TOPP has been progressing slowly as I battle with the tooling. I'm developing a GTK3 app using Go and the gotk3 library, and I want to cross-compile (from Arch Linux) to Windows. I finally managed to get a decent cross-compiling setup using Buildah, and learned a bit about Linux containers in the process.

My next battle, before I release the first version of the program, is to fix a bug in the Excel library I'm using.

9.2 September 10, 2019

The first few weeks of school have flown by. Here's what I've been working on:

9.2.1 URCA project

I'm almost finished with an initial prototype of the GUI for the data generator. Here's a screenshot of the UI and some example output.

olduvai-screenshot.png excel-screenshot.png

After ironing out some bugs and figuring out how to cross-compile for Windows (and hopefully Mac OS X), we'll have some decisions to make:

  • Should I focus on creating a general-purpose tool that researchers can use to generate graphs from arbitrary datasets with custom parameters, or a more focused, polished program with less user-facing options but a deeper focus on publishable, quality visualizations?
  • What are the most useful/needed functions to add?
  • How can I improve the usability of the program for other researchers? (My mentor has a good understanding of computers, but other researchers may benefit from using the program)

Looking further forward: - What conclusions can we draw from this project that relate back to the initial proposal? What is a good way to present it?

  • Does this bring to light any important niches that need to be filled by CS/Anthropology students? Is there a need to expand this project beyond its initial goals?

9.2.2 Reading

I finished Yuval Noah Harari's Homo Deus.

Depressive capitalist realism

Is it dangerous to engage seriously with radical right-wing thinkers?

Can negativity improve brainstorming?

A Sad Fact of Life: It's Actually Smart to Be Mean Online

Don't Use These Free-Speech Arguments Ever Again

Cop Diary

As usual, the links I post here aren't endorsements, but I really liked this paragraph from Social science and the radical politics of not knowing:

Recognizing our incapacity to know things shouldn't be distressing or disempowering; it's humbling, liberating, relaxing, and empowering. It reminds you that the little ball of fat in your skull is actually a pretty faulty device and it's not really your job to figure out everything going on in the world. Nobody can do that, but a lot of people think they can (and should); if you think you have this responsibility, not only will it drive you crazy but, as I said, on net you will not actually be contributing or helping anything. Again, don't get me wrong, I think everyone has a lot to contribute—but not in the form of objective explanations of what is happening in the world. We have this ridiculous, faux-democratic notion that everyone is entitled to their own reading of what is happening, but this is wrong. We are all equal, but if anything, I would say we are all equally disentitled to our own readings of what is happening—we are disentitled by objective reality, which is ultimately chaos, and which does not allow any of us the privilege of knowing exactly what is happening or what is causing what. I think we can find a radically more true, honest, and ultimately connective/solidaristic community in the shared realization that I don't know, you don't know, but we both know we have each other in this moment. Crucially, you can adopt this attitude in good conscience as well, because it's nobody's moral or political burden—not even social scientists'—to save the world or a country or a people by pretending to have knowledge nobody can have

The psychology of prohibiting outside thinkers

An interesting question is, because respectable intellectuals are often pretty smart and capable, why are they so fearful of outside intellectual projects, even if they are as evil as some fear? They are smart and capable intellectuals, so you'd think they would embrace some interesting challenge as an opportunity for productive contestation. Why don't they? Well, here's where the reality gets ugly. The reason respectable intellectuals so instinctively close ranks around the moral exclusion of NRx intellectuals is that currently working, respectable intellectuals privately know that the intellectual compromises they have made to secure their respectability and careers has rendered most of their life's work sadly and vulnerably low-quality.

High Tech Cowboys of the Deep Seas: The Race to Save the Cougar Ace

Are Politically Correct Students Better or Worse Students?

This: <p

> Wake up early.

> Show up.

> Learn how to think.

> Be genuine, but appear nice.

> Use envy for motivation instead of destruction.

> Do what you say you're going to do.

> Ensure balance in every area of your life.

> Confront repressed thoughts immediately.

> Surround yourself with people who are better than you (but remember

> the thing about envy).

> Work out every day.

> Be good at what you do.

> Make money doing what you love.

> Have good friends.

> Never settle.

9.3 August 20, 2019

It's been one month and 20 days since I last posted a journal entry. Here's what's happened:

9.3.1 Olduvai Gorge

I attended the 2019 TOPP Paleoanthropology Field School along with one other student from UNCG, one canadian student, two other American students, and three Tanzanian students. It was an incredible collection of unique experiences, and I can't do it justice here.

I'm just going to mention a few things that come to mind (to avoid being needlessly long-winded). Rest assured, I could talk for hours about every detail of the trip.

9.3.2 The Maasai

Maasai_Warrior.JPG
Figure 2: A Warrior relaxes on a hot afternoon in Olduvai Gorge

It would be impossible to talk about any trip to Tanzania without mentioning the Maasai. People from the massive tribe were ever-present, from when our Land Rover first pulled out of the Kilimanjaro airport to almost every hour spent in the field.

If I had to summarize my impression of the Maasai people, I'd say that they are crafty and resilient. Having not only found an ecological niche as pastoralists, they've managed to secure a cultural niche in this modernizing, globally connected world. While many indigenous groups around the world are essentially becoming extinct, the Maasai have learned to thrive. The combination of their distinctive culture and dress and their proximity to world-renowned national parks have given them the role of an accessable cultural novelty. Shrewd, natural businessmen (and women), they've capitalized on this. Since their mostly-desert habitat is unfit for agriculture, the Tanzanian government has only gently incentivized them to give up their lifestyle, and international scrutiny also protects them from reeducation camps and their ilk (looking at you, 19th-century United States). TOPP employs Maasai men as guards at the camp and as workers at some of the archeological sites; near our camp is a clique of women who offer handmade souvenirs and take care of their babies; and everywhere are Maasai who have assimilated to some degree and work as drivers, guards, or laborers.

But is everything good in this corner of the great continent of Africa? In a world obsessed with human rights and dignity, the Maasai represent an inconsistency for Liberals. Stereotypical issues include emorata, poor treatment of women and children, and a generally low quality of life by western standards. The Maasai don't see things this way, which can lead to some hard questions.

Anthropology is obsessed with cultural and moral relativism, so it felt at times like my minor left me unprepared to deal with the reality of Africa in a healthy way. At one dig, small groups of Maasai children would come by each day to watch us and to beg for food and water (they usually got some). At BKE2 we had some older children who brought their goats to graze in the valley and watch us. We got to know some of them by name and they sometimes helped sift sediment.

Maasai_children.png
Figure 3: Maasai children at BKE. The young boy on the right is a warrior.

One of our drivers knew bits of Maa and sometimes chatted with them; he learned that they won't go to school and don't want to. These are hungry children who will never learn to read and write but there's nothing we can do without violating their freedom of choice (a sacred value in the West).

The tiny anthropologist voice in my head reminds me "They are Maasai. For them, this is normal, and they certainly don't want to become like you." Is the anthropologist right?

flat_tire.jpg
Figure 4: A dismayed look after blowing a tire on the way back from an excursion

Our field doctor has limited resources out in the desert, but while she's not assisting field personnel, her and a staff member (Dr. Agness Gidna from the National Museum of Tanzania) occasionally help local Maasai people. I remember one interaction where a woman with cataracts requested medicine (a young man translated for her). Medicine, of course, doesn't exist for treating cataracts. The only treatment is surgery, so the woman would have needed to visit a hospital, which may have been out of her family's reach. After ~15 minutes of explaining and urging, she walked away with some Ibuprofen.

9.3.3 Science

Underpinning my experience was a recently renewed interest in Science along with a growing skepticism of and disillusionment with soft sciences and the humanities. Despite my misgivings about Anthropology in particular, I found the TOPP researchers (including Charles Egeland (my professor from UNCG) and Cynthia Fadem from Earlham College) to be rigorous and invested in scientific excellence.

shifting_sands_1.JPG
Figure 5: The 2016 marker for Shifting Sands, with the dune visible in the distance.

I do have one pet peeve: An oft-repeated justification for Paleoanthropology is that we need to "understand the past to better prepare for the future", or the even more ludicrous "we can learn from how our ancestors reacted to changes in climate to help with current climate change". I was taught this reasoning as fact in two of my Anthopology classes at UNCG, and heard it repeated again by Manuel Domínguez-Rodrigo while being interviewed for Tanzanian national TV. It's a highly questionable talking point that does more harm than good.

shifting_sands_2.jpg
Figure 6: A panorama of OT1, the site of an ongoing taphonomy survey. Shifting Sands is again visible on the right

9.3.4 URCA

In the coming weeks I'll be continuing work on my URCA project with Charles Egeland from UNCG. We now have a concrete plan and I hope to finish a demo application over the next month and a half. As usual, there are two hard things about designing the program.

9.4 June 10, 2019

Spring 2019 was my first semester as a junior, and my first semester in the Computer Science program at UNCG. I've accomplished some things, but I have a lot more to do. In nine days I'm getting on a plane to Tanzania.

I opened an issue to see if someone else wants to take over DWCHelper, since it's almost completed and will not end up being used by us for the URCA.

9.5 May 22, 2019

9.5.1 DWCHelper

I have been putting a lot of work into this program and it's almost completed. I'm excited to move on to the next part of the URCA project after my Tanzania trip. Since the program's "About" section may eventually change, I'm reposting it here:

DWCHelper is one component of my 2019 Undergraduate Research and Creativity Award project, which is a collaborative effort with the Anthropology department at UNCG.

The eventual goal of the project is to provide a tool for researchers at different sites in Olduvai Gorge, Tanzania to easily share, compare, and combine datasets and create useful, publishable data visualizations.

In June of 2019, I will be traveling to Tanzania to excavate and analyze animal bones, and I hope to gain a broader understanding of the context surrounding these 1.4 to 2 million-year-old specimens. My objective is to understand what types of questions researchers may need answered in their quest to understand this period of human evolution.

One challenge will be making the user prompts helpful for researchers who may be unfamiliar with command-line interfaces. For the URCA project itself, I have a feeling that this won't matter; we will probably "set up" the program once for each of the several Olduvai Gorge databases. Subsequent changes to the original data will automatically be integrated.

I've been starting to learn unit testing for the project, which apparently won't be taught in my degree. I also did a short course on web development (as much as I hate the modern web, HTML5, JS, and CSS knowledge will come in handy when I build the data vis part of the URCA project).

9.5.2 plr

I forked the Python program I mentioned in the previous entry and "cannibalized" it; I haven't implemented any of my planned features but a classmate on Github has been working at it. I may just see if she wants to take ownership over the project since I'll be in Africa without internet for a month!

I've had to put plr and betterssg on the back-burner while I work on DWCHelper, but I'd like to finish them both up soon. Perhaps it's good to have a few side-projects open, though.

9.5.3 Reading

I haven't really read anything good on the web, but I am getting into Legacy, by Greg Bear.

I also read several chapters of Code Complete 2, as recommended on the Coding Horror blog (the part I read seemed much less useful than I expected, but I might go digging around in later chapters another time)

9.6 April 23, 2019

Finals are almost upon us. Before I dig in and finish up this semester, I thought I'd put up what I've been reading.

Strongly identify with this article, although I don't actually agree with much of the premise. I think the author has captured the experience of many of my peers… along with my family, teachers, and coworkers. Worth a read. How Millennials Became The Burnout Generation

This one is also interesting. There are subtle implications and assertions (along with a sprinkle of strawman) that don't ring true to me. But the piece is written brilliantly. Don't waste your time with the comments. I have been thinking a lot about nature/nurture and "blank slate" ideas lately. What Explains the Resistance to Evolutionary Psychology?

This one is a JSTOR article; try to log in using credentials from your school. If you can't access it for some reason, get in touch with me: Acute Pain Infliction as Therapy

How Google's Jigsaw Is Trying to Detoxify the Internet

The computer as medium

Java Makes Programmers Want To Do Absolutely Anything Else With Their Time

Microsoft turned down facial-recognition sales on human rights concerns

Still working on this: Quantum computing for the very curious

VPN - a Very Precarious Narrative

Rust is not a good C replacement

9.7 April 09, 2019

I'll start the week off by linking to this post.

Now, for some positive stuff! I switched to the Go programming language for my URCA project, and it has been a huge relief. Go makes things effortless (things that would be huge, annoying problems in Common Lisp) so I can just focus on building the actual program. The language is so small that I "learned" it in an afternoon. The whole process was refreshing. I'm not building anything complex enough to really run into the limitations of the language, but I do have the general impression that I'll be mostly using Go as a drop-in replacement for script-type stuff.

I also noticed some link rot in my earlier log posts and I'm considering automating some sort of fix. This python program might be a good start. Maybe I can integrate the functionality into my static site generator. I did notice that the Internet Archive doesn't work properly for some links like The New York Times.

9.8 March 24, 2019

I got the URCA award I mentioned previously, so I will be focusing exclusively on this project in my free time now. Here's the repository I set up.

I'm still planning for the first stable release of betterssg in May.

I switched (almost) entirely to Sourcehut from Github.

My Ethics in the Computer Age class has been stimulating. Some recent highlights of discussion topics:

  • Should we give AI emotions, autonomy? Should AI have human rights?
  • Do we have rights to our own genetic code?
  • How does the US FICO credit score compare to China's new social ranking system?
  • What are human emotions? Is logic fundamentally different?
  • Does free will exist? Individuality?
  • Where do our morals and ethics come from? Where should they come from?

9.9 March 10, 2019

This week was Spring break. I spent a couple of days working on BetterSSG, implementing a build system with ASDF along with a bunch of major features. This website is now built using BetterSSG. I am happy with how quickly I've been able to add features. I've also been learning important toolset skills for use in my (hopefully) upcoming URCA project.

Common Lisp has a documentation problem. As one blogger put it, "why does Google hate Common Lisp?". The cryptic errors (like this) that CL programs give certainly don't help. That being said, I really like the functional approach to problem solving.

9.10 February 26, 2019

I started on a second iteration of my terrible static site generator. I'd consider it my first serious programming project (pretty much everything on Github right now is "recycle bin" material that I've uploaded to look active). I've only worked on it a little bit but so far there are about 50 lines of code that work to generate a basic website from different markdown files and a template html file.

I also updated the AUR package I maintain for the tiny irc client.

I have been getting into somewhat heated debates in my "Ethics in the Computer Age" class. All in good fun, of course, but worth mentioning here so I can smile when I read this someday.

9.11 February 17, 2019

Last week, one of my professors from last semester and I beat the deadline for a proposal for UNCG's Undergraduate Research and Creativity Award.

If we get the grant:

  • I'd get to work with one of the educators from one of my majors whom I highly respect
  • I'd get to potentially use my pet language Common Lisp
  • and I'd be working in my long-term area of interest (understanding human-computer interactions).

9.11.1 Skinner

Another idea that keeps messing with my mind is a summary of Beyond Freedom and Dignity by B.F. Skinner. I was shocked to find that a book from 1971 could mirror some of my own thoughts so well. Unfortunately it's apparently poorly written, and it's also from 1971 so it shows its age. While some of Skinner's conclusions specific observations about humans don't seem accurate to me, his core arguments seem consistent with the reality I've observed. Instead of Aristotle, as expected, most of my conversations with classmates end up stuck on Skinner.

Two comments from random users on goodreads help sum up the controversy I've observed among my peers:

Spencer Rich rated it one star, and wrote:

Easily ranks w/The Fountainhead as one of the worst poxes ever hoisted on humanity. Almost single handedly stole psychology from the hands of Jung, who had succeeded in giving creedence to the introvert and the play of fantasy in the inner life, Skinner reduces humanity to a succession of outward behaviors. And because when you're dealing with academia, you're looking at people who want things that are easily measured, Skinner and his ilk easily won out, leading to the Prozac-zombie state of the States and most of the Western world today. To be fair, perhaps Skinner has had a positive effect on education and inner-city renewal, but his dissolution of autonomous man, as he puts it, is vile. The other thing that bothers me about this book is how terribly it's written. Anyone with a good sense of English or logic could work out his methods without thinking. By placing his opinions between obvious facts, he makes his opinions appear as facts, i.e. "The sky is blue. Humans can be trained like guinea pigs. The grass is green." Or long paragraphs of substituting one set of phrases for his behaviorist terminology. Almost as horrible to read as Freud. But at least Freud was on the right track by mapping the subconscious. It wasn't until Jung and von Franz that psychology really came into its own. It's a vicious shame that it's been overrun by this Pavlovian charlatan.

Bschr1 rated it five stars, and wrote:

A refutation of the illusion that we have free will. Worse, to date noone that I have read has mustered any good counterarguments to Skinner. One of the most dangerous books in the English canon. You can't understand the political debate over the last 40 years about social programs unless you have mastered this text. You can't accept most people's simplistic religious beliefs once you have read this. Very scary stuff.

I'd like to see a 2019 version of the theory. It could be updated with current knowledge from genetics and psychology and written with a greater focus on value and cultural evolution.

9.12 February 06, 2019

I've been flooded with school. It's exciting, but exhausting.

My biggest frustration right now is the "Data Structures and Algorithms" class I'm taking – it's really just a Java 201 class. While I'm happy to be learning new data structures, it's frustrating to be stuck writing Java for problems that I could solve in minutes with Common Lisp. One "gentle" month of CL has spoiled me.

The problem with Java – and, if you believe its proponents, the most important feature – is its extensive structure. I'm reserving judgement on the language for now. After all, it's not like I'm maintaining thousands of lines of code in a production system with other software engineers. But there's no denying that the structure gets in the way of debugging. In Common Lisp, with the REPL (or even without it) I can instantly test a function without worrying about every detail of its location, permissions, and the rest of the program. In Java, you have to constantly modify and manipulate a driver class to test stuff. The textbook also reads annoyingly like an ad. I'm 12 chapters in, do they really think I need to be reminded every two pages of the benefits of Java and the Object-Oriented Paradigm??

I learned basic LaTex for "Foundations of Computer Science". It wasn't complicated – I probably should have known it already.

I've started using Zotero for storing research. The learning curve is tiny, and it offers features that my other "knowledge bases" don't have. My other pkbs being org-mode for Emacs and the Anki srs.

My "Ethics in the Computer Age" class is also great. It's stimulating, hard, and probably will be the subject of another log.

9.13 January 20, 2019

I'm still working on Common LISP: A Gentle Introduction to Symbolic Computation and getting through the beginning-of-semester boilerplate . One of my classes is "Technology and Ethics" (renamed from "Ethics in the Computer Age"), and it's exactly what I'm interested in. I'm looking forward to going in depth with some of those topics that I've mostly only wondered about.

Also, it's been a theme over the past year, but I'm feeling increasingly humbled by new knowledge coming at me from all directions.

9.14 January 12, 2019

This week I built a very rudimentary static site generator in Common Lisp. It's nothing special, but it was fun, and made me want to rewrite this website with my own generator and themes.

I'm also reading through the Rationality book/series on Lesswrong's home page. I've been a lurker for a long time on their IRC.

9.15 December 22, 2018

I'm continuing to work on Structure and Interpretation of Computer Programs, but I want to be able to apply the stuff I'm learning to real projects as soon as possible. I've decided to start learning Common Lisp after finishing the first chapter of SICP.

I thought I might as well post a quick guide to getting set up for the exercises in SICP (if you use Emacs).

After reading about some potential problems with the mit-scheme package, I decided to use Racket and its SICP package. Refer to the Racket documentation to get sicp installed in Racket.

Now, in any Racket file (use the .rkt file extension), you can use the SICP-compatable Scheme implementation by including #lang sicp at the top of the file.

This works fine in DrRacket, but after a few exercises I began to miss Emacs features. Luckily, there's racket-mode for Emacs! I also recommend installing smartparens and hideshow-org. Here are the settings I used in .emacs.

(add-to-list 'load-path "~/.lisp/hideshow-org")
(require 'hideshow-org)

;; make tab also do completion
(setq tab-always-indent 'complete)

;; make code fold from the end of the line, as normally expected, 
;; then return cursor to original position
 (defun toggle-fold ()
   (interactive)
   (save-excursion
     (end-of-line)
     (hs-toggle-hiding)))

(smartparens-global-mode t)
(add-hook 'prog-mode-hook #'hs-org/minor-mode)

(add-to-list 'auto-mode-alist '("\\.rkt\\'" . racket-mode))

Now I can use tab for completion, and for easy folding of the current code bracket (or, in this case, parentheses) in any code. Smartparens saves time by inserting a closing paren, bracket, brace or quote automatically, and the final line makes sure that the Racket REPL will be available whenever I open a .rkt file.

The only thing left is to learn the keymappings for racket-mode, which conveniently match the keyboard shortcuts for evaluating Elisp. To 'run' the racket file in the REPL, type C-c C-K, and to evaluate the symbol at point, type C-x C-o.

9.15.1 SICP exercises

Note: I'm not posting all of my solutions; many are strongly analogous to solutions found elsewhere on the web.

1.18

(define (* a b)
  (if (= b 0)
      0
      (*-iter a b)))

(define (*-iter a b)
  (cond ((= b 1) a)
    ((not (even? b)) (+ a (* a (- b 1))))
    (else (*-iter (double a) (half b)))))

(define (even? a)
  (= (/ a 2) 0))

(define (double a)
  (+ a a))
(define (half a)
  (/ a 2))

The answer to exercise 1.19 is technically only two lines of missing code from a program the book provides; I thought that the language of the question was obtuse enough to be almost infuriating. I had to refer to Tekkie's updated post on the problem for the best explanation.

1.29

(define (sum term a next b)
  (if (> a b)
      0
      (+ (term a)
         (sum term (next a) next b))))

(define (inc a)  (+ a 1))

(define (cube a)  (* a a a) )

(define (integral f a b n)
 (define h (/ (- b a) n)) 
  (define (y-of-k k)     (f (+ a (* h k))))

  (define (simpson-term k)
    (* (cond ((or (= 0 k) (= k n)) 1)
          ((even? k) 2)
          (else 4))
       (y-of-k k)))

    (* (/ h 3)

     (sum simpson-term 0 inc n)

     ))


(integral cube 0 1 1000)

1.30

(define (sum term a next b)
  (define (iter a result)
    (if  (= a b)
         (+ result (term a))
         (iter (next a) (+ result (term a)))))
  (iter a 0)
  )

(define (square a)
  (* a a))

(define (inc a)
  (+ a 1))

(sum square 0 inc 100)

9.16 December 16, 2018

I decided to start the legendary Structure and Interpretation of Computer Programs, after a brief foray into Emacs Lisp. This is one of those books that's challenging enough to make you feel like a toddler again. I love it.

My goal is to work though most of Chapter 1 by the end of winter break, and finish the book before I graduate.

I'm including some of the code answers I got below. The book can be found here, and I referred to Scheme wiki's SICP solutions for certain problems (like 1.11 and 1.12).

1.3

(define (test a b c)
  (+ (square
      (cond ((and (> a b) (> a c)) a)
                 ((and (> b a) (> b c)) b)
                      (else c)))

(square
      (cond ((exclusiveor (> a b) (> a c)) a)
                 ((exclusiveor (> b a) (> b c)) b)
                 (else c)))))

(define (exclusiveor a b)
  (and (not (and a b)) (not (and (not a) (not b)))))
(define (square a) (* a a))

(test 1 2 3)

1.8 combined with 1.7's good-enough? test

(define (cube-root x)
  (cube-iter x 1.0))

(define (square x) (* x x))

(define (cube-iter x guess)
  (if (good-enough? guess (improve guess x))
      guess
      (cube-iter x (improve guess x))))

(define (improve guess x)
  (/ (+ (* 2 guess) (/ x(square guess)))
     3))
(define (good-enough? guess newguess)
  (< (abs (- guess newguess)) (* .001 guess)))

(define (abs x)
  (if (< x 0)
      (- x)
      x))

(cube-root 8)

1.11:

; recursive (much easier)
;; (define (f n)
;;   (cond ((< n 3) n)
;;         (else (+
;;                (f (- n 1))
;;                (* 2 (f (- n 2)))
;;                (* 3 (f (- n 3)))))))

;;iterative, harder, doesn't help that the pattern isn't
;;predictable. should eval to 0, 1, 2, 4, 11, 25, 59, and 142.

(define (f n)
  (cond ((< n 3) n)
        (else 
  (f-iter 2 1 0 n))))

(define (f-iter a b c number)
  (cond ((= number 3) (+ a (* 2 b) (* 3 c)))
        (else (f-iter (+ a (* 2 b) (* 3 c) ) a b (- number 1)))
        ))

1.12

;; after mucking about with strings and realizing I have no idea how
;; this is done in MIT Scheme, I decided not to print a pretty
;; triangle. This code will compute the number in row r and "column" c
(define (computepascal r c)
  (cond ((or (= r c) (= c 1)) 1)
        (else (+ (computepascal (- r 1) (- c 1)) (computepascal (- r 1) c)))))

(computepascal 5 3) ;correct number is 6

1.15

(define (cube x) (* x x x))
(define (p x) (- (* 3 x) (* 4 (cube x))))
(define (sine angle)
   (if (not (> (abs angle) 0.1))
       angle
       (p (sine (/ angle 3.0)))))

; a gets the answer to 1.15a
(define (a p)
  (a-helper p 0))

  (define (a-helper p count)
  (cond
    ((not (> p 0.1)) count)
    (else (a-helper (/ p 3) (+ count 1)))))


(a 12.15)

1.16

;;fast-exp with iterative instead of recursive

(define (fast-exponent x n)
  (cond ((not (= (remainder n 2) 0)) (* x (fast-exponent x (- n 1))))
        (else (fast-exponent-helper x n))))

(define (fast-exponent-helper x n)
  (cond ((= n 2) (* x x))
        (else (fast-exponent (square x) (/ n 2)))))

(define (square x)
  (* x x))

I'll need to return to 1.13, which required some math skills relating to proofs that I haven't used in ages. Thankfully Bill the Lizard posted a walkthrough.

A few other exercises didn't require much besides understanding the question, or a "yes" or "no" answer, (e.g. 1.4). Some others were best left in the REPL (1.1), or I did them by hand (1.14).

10 URCA

10.1 GUI wireframe   export

10.1.1 Data Management Section

  • Import New Dataset
  • Remove Dataset
10.1.1.1 Currently Selected Data
  • Import as New
  • Export

10.1.2 Data Selection/Filtering

10.1.2.1 Select Datasets
  • [ ] BKE
  • [ ] DKE
  • [ ] OT1
  • [ ] etc.
10.1.2.2 Filter by Variable/Value
10.1.2.2.1 [remove]/[limit to] rows with
10.1.2.2.1.1 Variable [<e.g. "Animal Type">]
10.1.2.2.1.2 and values:
  • [ ] <ANY>
  • [ ] <ALL>
  • [ ] <BLANK>
  • [ ] <Variable not present at all for specimen>
  • [ ] "Mammal"
  • [ ] "Crocodile"
  • [ ] "Bovid"
  • [ ] etc.
10.1.2.3 Add New Filter

10.1.3 Data Grouping

  • Choose Row Variable(s) (grouping variables, e.g. "level", "dataset", or any variable you want the data grouped by)
  • Choose Column Variable(s) (better for dependent variables)

10.1.4 Generate Table

Added: January 17, 2020

Footnotes:

1
Partially because CapsLock is one of the most useless, yet largest keys on standard keyboards. Pointing this out is pleasing because of its contrarian tilt. It goes in and out of style to criticize the dated design of modern keyboards (e.g. Dvorak, etc.), although those who use them every day tend to silently accept the absurd status quo. The de facto Linux keyboard configuration program also makes it extremely easy to achieve this with the ctrl:nocaps option
2

Bell's Korongo East, a dig near Bell's Korongo, where Mary Leakey found teeth from an Australopithecus boisei in 1979.