“Hello World” in Zig

  • Creating
➜  zig-playground git:(master) ✗ cat src/main.zig
const std = @import("std");

pub fn main() !void {
    var stdout_file = try std.io.getStdOut();
    try stdout_file.write("Hello from Zigland!\n");
  • Running
➜  zig-playground git:(master) ✗ zig build run
Hello from Zigland!
  • Looking at builds:
➜  zig-playground git:(master) ✗ l zig-cache/o
drwxr-xr-x - agam 20 May 18:34 1FaU34FwI7Ct04pmfOlMacuOykIOisQtTn1t1Q3lrQOZcsEF0qxJW3vLauzHjpwm
drwxr-xr-x - agam 20 May 18:36 fyjPplfax8VTFYlidzFwMj_gV5Dw_T9T4PVTNBaOPnxDE5dq2XRo28L0b-87xi0l
drwxr-xr-x - agam 20 May 18:36 r-sdQS7ThLQpXn2OhOye0gD2RSuygbP_R6dWnLJZKjgjdWqQxTSCKB3dHKbWucMG
drwxr-xr-x - agam 21 May 23:21 XxkweE8uWyMc9LocxqJMMKAwTGgBzcn4q3bEKH1tL8Kx-F5Gk3kopgQqLbVLXVbh
  • Debug build size:
➜  zig-playground git:(master) ✗ l zig-cache/o/r-sdQS7ThLQpXn2OhOye0gD2RSuygbP_R6dWnLJZKjgjdWqQxTSCKB3dHKbWucMG/zig-playground
.rwxr-xr-x 406k agam 20 May 18:36 zig-cache/o/r-sdQS7ThLQpXn2OhOye0gD2RSuygbP_R6dWnLJZKjgjdWqQxTSCKB3dHKbWucMG/zig-playground
  • “Release build” size:

zig build -Drelease-small=true

➜  zig-playground git:(master) ✗ l zig-cache/o/XxkweE8uWyMc9LocxqJMMKAwTGgBzcn4q3bEKH1tL8Kx-F5Gk3kopgQqLbVLXVbh/zig-playground
.rwxr-xr-x 53k agam 21 May 23:21 zig-cache/o/XxkweE8uWyMc9LocxqJMMKAwTGgBzcn4q3bEKH1tL8Kx-F5Gk3kopgQqLbVLXVbh/zig-playground

So, 406k for the debug build, 53k for the release build, very similar to Nim here, and comparing very favorably indeed to Rust or Go (!)

Monthly Curations: April 2019

Starting new C++ projects

I wanted to have a playground to try out new idioms and concepts (hah!) in C++, and it became an excuse to figure out what the right way (in my opinion) would be, given the enormous range of choices each step of the way.

I settled on two requirements: a good build system and a good standard library augmentation.

There are numerous build systems these days, but (blame familiarity here, I guess) I went with Bazel.

Similarly, familiarity led me to pick Abseil over (say) Boost or Folly.

To show how straightforward it can be these days to “just start making” something in C++, I made a small dummy program that has a single cc_binary rule and uses some basic string library functions.

(The real story is how amazing it is to have open-sourced versions of these, this setup would have been unthinkable just a couple of years ago!!)

Take a look here.

Old Lisp programs

I found an old chess program that Mark Watson (somehow I can’t find the original link anymore, my Gist mirroring it is here). I was wondering what it would take to get it to run again, and I was shocked to find out that when I copy-pasted it in, loaded the file, it … it just worked !!

This is not supposed to happen, really. Code from 28 years ago isn’t supposed to just run. I don’t need to talk about how even Python code from 10 years ago would require some work to run.

Also notable is the lack of required scaffolding in terms of makefiles, build tools or anything of the sort. Yes, you could imagine breaking the code up, but it’s just 585 lines. Drop it in and load the code, and you’re good to go. No extensions, shims, nothing.

As proof, here is a short transcript of me playing terribly with it.


Common Lisp nits/tips/libraries: Iteration


Every once in a while, I see a mention of how Common Lisp really does support “non-functional” styles, and then cl:loop is trotted in, with attendant examples that make your eyes glaze over.

As you might expect, this isn’t the only way to do it; there’s a “Lispier” way, if you will (none of this is new, the original manual/memo dates from 1989!).


CL-USER> (ql:quickload "iterate")
To load "iterate":
Load 1 ASDF system:
Install 1 Quicklisp release:
; Loading "iterate"
[package iterate]...........................

(while I’m here, a plug for sly instead of slime; you know you’re successfully connected when you see the [sly] Connected. Take this REPL, brother, and may it serve you well. message 😀)

Simple uses

For a really simple example, iter is not too different from loop, but still:

Basic for loop

CL-USER> (loop for i from 1 to 10 collect i)
(1 2 3 4 5 6 7 8 9 10)
CL-USER> (iter:iter
(for i from 1 to 10)
(collect i))
(1 2 3 4 5 6 7 8 9 10)

Collecting tuples

CL-USER> (loop
for x in '(a b c d)
for y in '(d e f g)
collect (list x y))
((A D) (B E) (C F) (D G))
CL-USER> (iter:iter
(for x in '(a b c d))
(for y in '(d e f g))
(collect (list x y)))
((A D) (B E) (C F) (D G))

Intermediate example

Here is an example (from the CL cookbook) of looping, with an auxiliary variable on which we have a terminating condition, with a combination of “doing something” and collecting something else, at the same time:

CL-USER> (loop for x from 1
for y = (* x 10)
while (< y 100) do (print (* x 5)) collect y) 5 10 15 20 25 30 35 40 45 (10 20 30 40 50 60 70 80 90)
CL-USER> (iter:iter
(for x upfrom 1)
(for y = (* x 10))
(while (< y 100)) (print (* x 5)) (collect y)) 5 10 15 20 25 30 35 40 45 (10 20 30 40 50 60 70 80 90)

Another example, though a bit contrived (there’s a one-liner to do this without using either of these two, but …)

CL-USER> (let ((s "alpha45"))
(loop for i from 0 below (length s)
for ch = (char s i)
when (find ch "0123456789" :test #'eql)
return ch) )
CL-USER> (let ((s "alpha45"))
(for ch in-string s)
(finding ch such-that
(find ch "0123456789" :test #'eql))))

Misc cool stuff

Making modifications

I find it easier to “splice in” new changes to iter. This is another contrived example, but sort of shows what I mean:

CL-USER> (iter:iter
(for i from 1 to 10)
(collect i into nums)
(finally (return nums)))
(1 2 3 4 5 6 7 8 9 10)
CL-USER> (iter:iter
(for i from 1 to 10)
(collect i into nums)
(collect (* i i) into nums)
(finally (return nums)))
(1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 9 81 10 100)

Natural iteration for different types

The (for ... in ...) gathering clause applies quite naturally to a great many types of structures.

CL-USER> (iter:iter
(for x in '(1 5 6))
(when (oddp x)
(collect x)))
(1 5)
CL-USER> (iter:iter
(for x in-vector #(1 5 6))
(when (oddp x)
(collect x)))
(1 5)
CL-USER> (iter:iter
(for (k v) in-hashtable (alexandria:alist-hash-table '((foo bar) (baz quux))))
(collect v))
((BAR) (QUUX))

Accessing previous values

CL-USER> (iter:iter
(for x from 1 to 10)
(for p-x previous x initially 0)
(collect (+ x p-x)))
(1 3 5 7 9 11 13 15 17 19)

Collecting all vs. unique values

CL-USER> (iter:iter
(for x in '(7 1 4 3 2 1 7 1 0))
(collect x))
(7 1 4 3 2 1 7 1 0)
CL-USER> (iter:iter
(for x in '(7 1 4 3 2 1 7 1 0))
(adjoining x))
(7 1 4 3 2 0)


You can splice in a reduction step (counting, summing, maximizing, minimizing, etc.) in ad-hoc way.

This extremely contrived example is essentially equivalent to (reduce #'* '(1 2 3 4 5 6 7 8 9 10)), but hopefully you get the point:

CL-USER> (iter:iter
(for x from 1 to 10)
(reducing x by #'* ))
3628800 (22 bits, #x375F00)


YMMV, but iter seems to have (for me) a more uniform syntax, a few extra features, better comparability of clauses, and I personally prefer it to loop. If you’ve never used either, I’d recommend just sticking with the former.

Setting up ZSH on a Mac

I’ve been using the excellent Fish shell for the last few (three? four?) years, but every once in a while I need bash-compatibility, and Zsh seemed like perhaps a sweet spot between the two.

If you’re in a similar spot, this is a two-minute (almost) guide to getting up and running with Zsh on OS X.

Step 1: What does brew have?

~> brew search zsh
==> Searching local taps...
zsh ✔                                zsh-autosuggestions                  zsh-git-prompt                       zsh-lovers                           zsh-syntax-highlighting
fizsh                                zsh-completions                      zsh-history-substring-search         zsh-navigation-tools                 zshdb

Step 2: Just install the main product

So brew has a lot of packages, but I just need zsh for now.

Step 3: Use it!

I used to have this two step process of first adding it to /etc/shells and then calling chsh -s on it, but there’s a better way to do it:

sudo dscl . -create /Users/$USER UserShell /usr/local/bin/zsh

Step 4: Configuration options

Here you can either create .zshrc files manual, or through the startup menu, or … use Oh-my-zsh/Prezto.

I went with the last one, but here’s what the “first time menu” looks like:

Please pick one of the following options:

(1)  Configure settings for history, i.e. command lines remembered
 and saved by the shell.  (Recommended.)

(2)  Configure the new completion system.  (Recommended.)

(3)  Configure how keys behave when editing command lines.  (Recommended.)

(4)  Pick some of the more common shell options.  These are simple "on"
 or "off" switches controlling the shell's features.

(0)  Exit, creating a blank ~/.zshrc file.

(a)  Abort all settings and start from scratch.  Note this will overwrite
 any settings from zsh-newuser-install already in the startup file.
 It will not alter any of your other settings, however.

(q)  Quit and do nothing else.  The function will be run again next time.
--- Type one of the keys in parentheses ---

Step 5: Prezto

Pretty straightforward to install, and you can keep tweaking later, if that’s what you want.

git clone –recursive https://github.com/sorin-ionescu/prezto.git “$ZDOTDIR:-$HOME/.zprezto”

And then

for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
  ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"

That’s it, open a new terminal and enjoy your new shell!

Nit-picking languages

It’s that (too frequent) time again … when I anxiously (and full of fickleness) wonder what language to increase familiarity with.

The last year, I learnt quite a bit of common lisp, or atleast enough to write a lot of exploratory code in, working with libraries, timing, profiling, improving, and so on.

I had a rude shock when I learnt from one of my Scheme heroes that he really just prefers Haskell now. WTF? But seriously, he makes good points, chief among which is the lack of confidence in refactoring existing lisp code.

But both have the same “lack of libraries” barrier (sure, you’d say, why don’t you build your own — but that’s not the point).

So I’ve been moving around among these, toying with some web-development style languages (and always recoiling from JS), when I suddenly realized that I have absolutely zero experience with any of the .Net languages.

So, (just thinking out loud here) why not learn me some F#, and kill two birds with one stone?