Building yet another single-file backend as a service. As always, we focus on simplicity, but nevertheless we try to implement as many features as we can without making it too complex.| zserge.com
My journey into retrocomputing, 8-bit home computers, Apple I and of course MOS 6502 assembly.| zserge.com
Random thoughts about plain text music notation, tablatures, amateur musicians and pocket zines. Vaguely related to programming, too.| zserge.com
Recently with friends we talked about an early web site I’ve programmed, probably the very first web service I’ve ever done. It was a simple dictionary. Back then, we had Nokia phones without real web browsers, just something called the WAP protocol and WML markup. Since I struggled with foreign languages as a student (I still do!), I decided to create a mobile site in WAP/WML to help me translate words, show definitions, thesaurus entries, pronunciations, and more.| zserge's blog
This is part 6 from series “Tiny Great Languages”. Final code is on Github. Part 1: Assembly. Part 2: BASIC. Part 3: Forth/MOUSE. Part 4: Lisp. Part 5: APL/K. Part 6: PL/0. Let’s talk about Pascal. It’s the language I first learned many years ago, and it becomes the final one we cover in this series. Well, not the full version of Pascal, but a tiny educational subset defined by the legendary Niklaus Wirth.| zserge's blog
This is part 5 from series “Tiny Great Languages”. Final code is on Github. Part 1: Assembly. Part 2: BASIC. Part 3: Forth/MOUSE. Part 4: Lisp. Part 5: APL/K. This would be a controversial language, but it fits perfectly into the 50-lines-of-less code category. Let’s talk about APL family, and specifically – K. Created by Arthur Whitney the language is known for its terse and cryptic syntax. But it fixes one “issue” with APL – K uses ASCII symbols.| zserge's blog
This is part 4 from series “Tiny Great Languages”. Final code is on Github. Part 1: Assembly. Part 2: BASIC. Part 3: Forth/MOUSE. Part 4: Lisp. Part 5: APL/K. Done with the concatenative language MOUSE, we can now turn our attention to another small and elegant language from way back: Lisp. Lisp is famous for its minimalist syntax (similar to Forth, the parser is almost nonexistent) and its clear, logical evaluation rules.| zserge's blog
This is part 2 from series “Tiny Great Languages”. Final code is on Github. Part 1: Assembly. Part 2: BASIC. Part 3: Forth/MOUSE. Part 4: Lisp. Part 5: APL/K. Meet BASIC, the king of home computing in the late 1970s. Originally designed to promote computer literacy in schools, BASIC inspired a whole generation of professional software engineers. BASIC typically combined a simple text editor with a command shell and interpreter.| zserge's blog
Summing up years of building interpreters and compilers for various programming languages. The first chapter is about assembly language. We will try to implement a tiny two-pass assembler for CPython VM.| zserge.com
Neural network and deep learning introduction for those who skipped the math class but wants to follow the trend| zserge.com
Exploring the world of Markov chains, learning how they predict text patterns and make a basic implementation that talks nonsense like Homer Simpson.| zserge.com
Exploring how to use 2D graphics in various desktop operating systems, the old-school way. In this part we learn how to create an empty window under Linux, macOS and Windows.| zserge.com
Build your own tiny Git from scratch to learn the internals of Git version control system.| zserge.com
Exploring various transpilers from C to "better C" and how they can help replacing C in existing project.| zserge.com
An exploration around RPN, concatenative languages, esoteric weirdness and threading techniques, while trying to learn Rust once again.| zserge.com
Zig programming language is new, but it's getting a well deserved attention. Can it be a good fit for small-and-simple programming tasks?| zserge.com
Many of us use one-time passwords (OTP) regularly to log into different services. Most probably rely on Google Authenticator and similar tools. But what about building one by ourselves?| zserge.com
The Small Web Renaissance, Finger, Gopher and Gemini. How they work and what makes them different from the modern Big Web.| zserge.com
A tiny ray tracer, only useful for people who never written one themselves, but would like to. It lacks features, but provides a foundation to build your own, featureful ray tracer upon.| zserge.com
You probably shouldn’t read this article. If you want to start learning a programming language - write a BF interpreter in it. For many years this has been a common suggestion to the newcomers into programming. And we all know how the typical solution would look like: s[999],*r=s,*d,c;main(a,b){char*v=1[d=b];for(;c=*v++%93;)for(b=c%7?a&&(c&17?c&1? (*r-=c-44):(r+=c-61):c&2?putchar(*r):(*r=getchar()),0):v;b&&c|a**r;v=d)main(!c,& b-1);d=v;} Well, or something a bit more readable in ~100 lines ...| zserge's blog
An unusual benchmark for programming languages, designed to replace C. Unlike many other benchmarks, this one measures developer productivity and performance.| zserge.com
A brief introduction into 1-bit buzzer music, perhaps the most limiting and challenging genre of electronic computer music.| zserge.com
Learning how CSS-in-JS works by building one from scratch and squeezing it into a barely noticeable size.| zserge.com
Yes, modern web development is complex. Frameworks change each other, cognitive load increases, hype-driven development introduces new risks that lead to “the Big Rewrite”, which at the end rarely goes well. But does it have to be this way? Looking back, we may notice that the websites written in plain HTML+CSS still open and work perfectly. Boring technologies survive. Similarly, web services built with a dull tech stack are surprisingly robust.| zserge's blog
Audio I/O is a complex topic, which scares away many inspired musicians who are into programming (or programmers who are into music). Let’s try making it look less complex and see how audio works on each modern desktop platform. Our show case today will be a simple beeper. Remeber that annoying thing inside your PC boxes producing the irritating buzzing sound? It’s long time gone, but I suggest to sumon its soul and make a library that plays beeps across all the platforms.| zserge's blog
Making music with low-level C code, from a simple saw wave to playing melodies| zserge.com
Making a tiny oldschool music composer inspired by RTTTL and Nokia Composer| zserge.com
We are all familiar with a traditional office suite - a word processor, a spreadsheet, a presentation program, maybe a diagramming or note-taking app. We have seen it all in Microsoft Office and Google Docs. Those are really powerful and large. But what would be the most minimal amount of code required to build an office suite? platform Obviously, our office suite won’t be a desktop GUI app - those require plenty of code and efforts to build one.| zserge's blog
How would one write a code editor in JavaScript? A long time ago one would take a regular textarea to handle user input and would create another div that would do syntax highlighting etc. However, this approach quickly becomes unusable when someone opens it on mobile. That’s why CodeMirror has been rewritten to use contenteditable and many other editors followed this approach. contenteditable Contenteditable, as the name suggests, allows users to edit the contents of the element using the b...| zserge's blog
A playful experiment in making the most minimal bitmap font.| zserge.com
The previous post about JVM turned out to be well-received, so I would like to uncover another fun topic related to JVM - Java agents. Although not everyone gets a chance to write custom Java agents in his career, they are still a wonderful field to explore and open an endless way to customize JVM behavior. Java agents are special in the way that JVM allows them to do much more than a regular Java app is allowed to: they can instrument or profile code, hot-swap classes, patch methods, etc.| zserge's blog
Whether we like it or not, but Java is one of the most widely used programming languages. However, since most of the applications in Java are either too boring or too complex - not every Java developer has enough curiosity to look under the hood and see how JVM works. In this post I will try to write a toy (and incomplete) JVM to show the core principles behind it and hopefully sparkle some interest in you to learn it further.| zserge's blog
KVM is a virtualization technology that comes with the Linux kernel. In other words, it allows you to run multiple virtual machines (VMs) on a single Linux VM host. VMs in this case are known as guests. If you ever used QEMU or VirtualBox on Linux - you know what KVM is capable of. But how does it work under the hood? ioctl KVM provides an API via a special device node - /dev/kvm.| zserge's blog
This post is meant to be a counterpart to the previous KVM post, but about containers instead. The idea is to show how exactly containers work by running a busybox Docker image in our own small container runner. Unlike a VM, container is very vague term. Normally, we call containers a self-contained bundle of code and its dependencies, that can be shipped together and run in an isolated environment inside some host operating system.| zserge's blog
Tmux has liberated me from tiling window mangers. Not that I didn’t like those, but I occasionally have to work with macOS or default GNOME setups. And over the years I realised that I only need a terminal multiplexor to do terminal tiling for me, the rest of the windows are just fine to be full-screen in separate workspaces. So, I ended up doing 80% of my work in terminals with tmux.| zserge's blog
While self-isolating orchestras and amateur musicians are playing ‘Ode to Joy’ from their open windows, I would like to give it a try with my ode to J. If you read the Hacker News or other programming resources, you probably have read the following passage: “One summer weekend in 1989, Arthur Whitney visited Ken Iverson at Kiln Farm and produced—on one page and in one afternoon—an interpreter fragment on the AT&T 3B1 computer.| zserge's blog
(The story of github.com/zserge/headline). About seven years ago Google decided to shut down Google Reader, a world known and beloved RSS reader, and I think no other service has been so genuinely lamented since then. I remember the warm feeling when I opened Reader on a tiny HTC Wildfire that fit well in my palm and read stories from dozens of blogs of interesting and unusual people I was subscribed to.| zserge's blog
In this article we will try to understand how chess engines work by porting the sunfish chess engine to Go. Sunfish is notable for its simplicity and small size, while still being capable of playing decent chess. Go is also known as a simple and highly readable language, so I hope the two of them could make a great couple. To build a chess engine one has to decide on three important topics:| zserge's blog
I use Vim as a plain text editor for everything. Apart from coding, I write blog posts in vim, create quick notes and draft design documents. Surprisingly, I haven’t customized it a lot and am very lean about the plugins. While keeping my setup austerely simple, I rarely lack any of the functionality. However, recently I wondered if I can achieve a “distraction free” experience with Vim, like when you see a full screen text, nicely centered, and nothing else:| zserge's blog
Metrics are data points representing your system behaviour over time. People instrument their long-running apps with metrics to see if there are or were any problems and if the system behaves as expected. There are various metric types, but most common ones are counters, gauges and histograms. Metric types Counter is simply an increasing number. You may use counters to track the number of served requests, number of errors, and so on.| zserge's blog
Over the years of using Linux as my primary and only OS I had to embrace some unavoidable facts. First, things tend to change and complex things tend to break. Second, reinventing the wheel almost never pays off. And finally, it’s not that hard to make a new habit and sometimes it’s better than adjusting your workstation to your “intuitive” understanding that may change very soon. So years ago I decided to only use the most common software and only the very minimal personalized config...| zserge's blog
Cross-platform GUI has always been a painful part of software development. Today the biggest horror for an old-school C developer is to look at the list of Electron apps on their website. Simple, often trivial utilities, each taking over a hundred of megabytes of disk space and consuming hundreds of RAM once launched. I’m not going to start a rant here, people of HackerNews have said enough on this topic. Electron wins because it is easy to use and everyone knows how to write HTML/CSS (unli...| zserge's blog
The for loop is one of the most powerful constructions in the C language. It consists of three different parts. The first one is initialization, performed exactly once at the beginning of the loop. The second one is the conditional part, called every time before the loop body. The last one is the increment part, executed on every iteration right after the loop body. Such a loop combines both, linear code and branching in a very customizable manner, which we will explore below.| zserge's blog
Tcl intepreter in six hundred lines of code, customizable, extendable, covered with tests| zserge.com
Previously on Anvil: version 0.1 was the first one to use incremental rendering approach instead of virtual tree diff’ing. Version 0.2 added support for XML layouts and binding data to existing views. Version 0.3 was about two-way data bindings - most views got simplified lambas for handling user input and many related bugs have been fixed. Today’s version 0.4 takes care of support libraries. I personally rarely use support libraries (at work we don’t target regular consumer devices so ...| zserge's blog
If you only have a few UI elements, a small data class and your controllers have only a few actions to perform - you may consider using no architecture at all. Just make a global “controller” object and/or a global data object. By “global” I mean you may use dependency injection, or propagate the instance from the root activity to its child views, or make it a singleton. Simply bind data to your views and call controller methods from your event listeners.| zserge's blog
When people first hear about Anvil they don’t trust it because at first glance Anvil seems to be just a replacement for XML layouts. It’s not. It’s a library to build predictable reactive views. There are many known disadvantages of XMLs (poor code reuse, no type-safety, no variables, very limited styling support etc etc). Yet the developers are so much used to XMLs that they started liking them! Let’s see how one can use Anvil in all its power and still have XMLs in their projects.| zserge's blog
A common question I hear about Anvil is how to style views. Let’s recall how it’s been traditionally done in Android. Here’s an example from the Android Developers website: <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:textColor="#00FF00" android:typeface="monospace" android:text="@string/hello" /> If you have a lot of views like this - most likely you would like to move repetitive code into a single place and just keep a reference to them in ...| zserge's blog
Android is probably the second most popular development platform after the web. Web development practices tend to change every month if not every week. As soon as a tool or a library becomes mature and stable - they call it deprecated and seek for a new replacement. Now let’s see how Android development tools and paradigms have evolved over the past few years and how it compares to the web.| zserge's blog
New Anvil 0.3.0 has been released. The major focus for this release has been on user input widgets and two-way data bindings. Issues There have been two types of issues in this two-way data binding milestone: bloated inconvenient event listeners and recursion. Listeners The first one is easy. Java 8 and Kotlin are the primary languages for Anvil, so when people bind an event listener to a view - they use either a lambda or a method reference.| zserge's blog
Libraries are only good when it’s easy to share them. Android has done this wrong for a very long time. Node.js has npm and a new library can be published in a couple of minutes, usage is as simple as adding library name to package.json. Go has no package manager at all and publishing a library is as simple as “git push” and using is as simple as “import github.com/user/library”.| zserge's blog
Those of you who regularly check my blog may remember that I was going to redesign Anvil from scratch. Unfortunately, it was an unavoidable step. We had performance issues and it turned out that blindly copying modern web metaphors to Android doesn’t work well. I am sorry, I had to change a lot of Anvil APIs since then. Those of you who have their apps written with Anvil 0.0.12 most likely would prefer to stick with the older version.| zserge's blog
Dear users, those who were early followers of Anvil. I’m now heavily working on the next version of Anvil, but it’s likely to make you rewrite your code, and I’m deeply sorry about that. Below I will describe why the changes are necessary and I hope you will find that your code would not be modified a lot and embrace the benefist it brings. how anvil works now Currently we have Renderables which have a view() method returning a virtual layout.| zserge's blog
Benchmarking Go in the cloud Go now seems to be a natural choice for writing your next microservice or web app. It’s mature and fast. But where would you host your app? In this post I will compare some popular PaaS (platform-as-a-service) and how the same primitive Go web app performs on each of them. Go I’m using the latest Go compiler and the latest version of Gin framework with zero-allocation router.| zserge's blog
Lua is one of my favourite languages. It’s tiny, it’s fast, it has simple grammar and is very easy to learn. I also often write shell scripts - from simple one-liners, to bigger ones containing business logic and binding together smaller app components. In fact, this blog is powered by a few shell scripts to generate list of posts, rss xml etc. I had an experience in the past when Bash script became hard to maintain.| zserge's blog
Whenever I prepare my APK for the release - I used to do the following steps: Copy keystore to the project directory Copy gradle.properties into the project directory with keystore name, alias and password defined Copy some code from some blog that would load the properties and set up the signing Finally, do gradle build But why not to move the boilderplate out of build.gradle? Helper signing script I wrote a tiny helper script that can be included into the projects:| zserge's blog
Palette is an open source lightweight color picker for the most famous color schemes, like Material Design, Flat UI, iOS, Windows Phone etc. Despite being color blind, I like apps and websites with the right selection of colors. And sometimes when starting a new project it’s easier to pick a color palette from the existing ones. Or, if you want to meet the guidelines for the certain platform - you’d better use the colors they offer.| zserge's blog
Anvil: version 0.0.7 released! If you missed the news - Anvil is a tiny reactive UI library for Android. It’s based on the concept of the virtual layout (much like React.js) and brings declarative layouts with data bindings, componentization, styles, animations etc in pure Java. It also supports Kotlin, which is a great language and I hope it will replace Java on Android some day. Version 0.0.6 was suprisingly stable, but life goes on, and here’s version 0.| zserge's blog
Once upon a time I was making a pretty large app for Android. When everything was almost finished I wondered how shall I remove all my logs before publishing the app? Looks like many other developers are interested in the same question as well. Surprisingly, the recommented way out is to strip off the Log class from the production builds using ProGuard. Maybe Proguard is nice, but to me it’s really weird why instead of having a nice out-of-box API for logging I need to modify my byte code w...| zserge's blog
Gradle is too slow, Ant is too basic. Buck is fast and super-configurable and I’d like to tell you how I use it for Android development. I own a pretty old thinkpad laptop so I don’t expect the builds to be too fast. Ant used to spend 10..40 seconds for each build on my laptop depending on how large the project is. Gradle takes about a minute in average and that’s too long for me - I just lose focus when I just sit and wait for the build results.| zserge's blog
Anvil: big progress for a small library I have just released Anvil 0.0.2. So many changes have been made and now I am absolutely confident that Anvil has its strong points even though I’m the only active user of it. What is Anvil? This section is for those who missed the early steps of Anvil. Anvil is a tiny reactive UI library for Android. What does this mean? It means that you can declare your UI in Java, bind your data to the views, bind event listeners to the views and leave it running.| zserge's blog
Kotlin is a very nice language for JVM. I wrote about it in the past. Anvil is a very nice UI library for Android. How do these two play together? The first attempt My favourite example to demonstrate Anvil syntax is a simple click counter. It demonstrates the use of layouts, views, data binding and event binding. In Java it looks like this: public ViewNode view() { return v(LinearLayout.class, orientation(LinearLayout.VERTICAL), v(TextView.| zserge's blog
Reading my previous blog post some people asking why I’m so strongly against XMLs if they are really good? I think I shall clarify that I’m not against XMLs per se, I’m against the way many developers organize their apps. Let’s look at a simple example - a button and a textview showing how many times the button was pressed. Here’s a typical implementation in Java+XML: <LinearLayout ....> <TextView android:id="@+id/text" .| zserge's blog
TL;DR: I offer declarative strongly typed layouts with data bindings in pure Java. Android UI development is broken. It normally ends up with lots of boilerplate code and poor architecture. Here are some (very subjective) issues: There is no MVC (or M-V-Whatever). XMLs always contain lots of copy-pasted code, very poor code reuse. XMLs are very fragile, so you can type “TextVeiw” and it will not warn you during the compilation but will throw an InflateException in runtime.| zserge's blog
As you may have noticed, the site has changed its look. That’s because I made a small rewrite and it resulted in a new static site generator. It’s my another NIH product, this time it’s written in Go. stash away I used stash before. It was written in UNIX Shell and was really perfect for my needs. Then it became slower and slower. The reason is that it could not track the timestamps of the web pages so it regenerated every page every time.| zserge's blog
Most large software projects include automated testing and the reasons are obvious. But what about smaller, even toy projects? There should be some extremely lightweight unit-testing frameworks/libraries that would easily fit even the smallest project needs. Unit testing should be easy to start. Otherwise people won’t bother with writing tests at all (unless they are forced to). People don’t like learning complex frameworks to run just a dozen of tests.| zserge's blog
So, you switched to Gradle and just finished you new shiny Android library (or java library). And of course you want to share it with the community. Here’s a quick guide for those who never published their libraries before. What is maven central? In java world libraries are usually stored in a big repository called Maven Central. You may think of it as of the NPM repository for Node.js or as of PyPI for Python.| zserge's blog
Somehow refactoring turned info rewriting from scratch… So, meet the new shiny mucks app written in AWK language (instead of UNIX Shell). I played with quotes in tmux “send-keys” command, and it turned out that different shells treat quotes in the “read” command very differently, and I found no easy way to overcome it. That’s how AWK came to the rescue. A more mature, yet much simpler language made my code cleaner and shorter.| zserge's blog
I can’t imagine my daily work in terminal without multiplexers. I used to use GNU Screen a couple of years ago, then I switched to Tmux. There has been a lot of talks about screen vs tmux, and then vs byubu. I still use both, and I still like both. What I was really missing is session management. Since my laptop’s uptime is normally more than a month - I just created windows manually and started programs manually and then just attached/detached until the next reboot.| zserge's blog
Lambda support for Android Note: big thanks to orfjackal (Esko Luontola), the author of Retrolambda, for making it possible. I just used his tool to produce Android apk. So, you’re jealous about new JDK8 upcoming to most Java developers except for you, Android coders? Then I have good news - there is a way to use lambdas in Android right now (warning: it’s still a hack)! But I already have local classes!| zserge's blog
This website has been powered by poole for a long time. I don’t think I have any real reasons to migrate from poole. Do you know there are static site generators written in UNIX Shell? I think it’s a good choice for old-school programmers, who feel uncomfortable with Ruby, Python and even Node.js. All that shell madness started with werc, a nice tool used by suckless and cat-v. Then sw appeared.| zserge's blog
Let’s talk about compiler backends. C should be a portable language, and there is no need to rewrite the whole compiler if you want to port it to the new CPU architecture. Backend is a part of the compiler that generates low-level byte code. Compiler itself just calls backend functions. Good backend design makes the compiler highly portable. I wanted CUCU to be a portable compiler (actually, a cross-compiler). So, I decided to move backend code generator to a separate module.| zserge's blog
So far, we have defined language grammar and have written a lexer. In this part we will write a parser for our language. Before we start, we need some helper functions: int peek(char *s) { return (strcmp(tok, s) == 0); } int accept(char *s) { if (peek(s)) { readtok(); return 1; } return 0; } int expect(char *s) { if (accept(s) == 0) { error("Error: expected '%s'\n", s); } } peek() returns non-zero value if the next token is equal to the given string.| zserge's blog
Let talk about the compilers. Have you ever thought of writing your own one? I will try to show you how simple it is. The first part will be pretty much theoretical, so keep patience. what we’re going to achieve? CUCU is a toy compiler for a toy language. I want it to be as close to ANSI C as possible, so that every valid CUCU program could be compiled with a C compiler without any errors.| zserge's blog
Explore the intriguing history of Eliza, a pioneering chatbot, and learn how to implement a basic version in Go, unraveling the roots of conversational AI.| zserge.com
In a post-apocalyptic future with no internet or stackoverflow, let's try to build a programming environment from scratch.| zserge.com