Skip to main content

Ralsina.Me — Roberto Alsina's website

Posts about python (old posts, page 98)

Playing With Picolisp (Part 1)

I want to learn new lan­guages. But new as in "new to me", not new as in "cre­at­ed last week". So I de­cid­ed to play with the grandad­dy of all cool lan­guages, LISP. Cre­at­ed in 1958, it's even old­er than I, which is good be­cause it's ex­pe­ri­enced.

One "prob­lem" with LISP is that there are a mil­lion LISP­s. You can use Scheme or Com­mon Lisp, or Emac­s' Lisp, or a bazil­lion oth­er­s. I want­ed some­thing sim­ple so it was sup­posed to be Scheme... but a few days ago I ran in­to some­thing called Pi­col­isp and it sound­ed so cool.

Read more…

Playing with Nim

A few days ago I saw a men­tion in twit­ter about a lan­guage called Nim

And... why not. I am a bit stale in my pro­gram­ming lan­guage va­ri­ety. I used to be flu­ent in a dozen, now I do 80% python 10% go, some JS and al­most noth­ing else. Be­cause I learn by do­ing, I de­cid­ed to do some­thing. Be­cause I did not want a prob­lem I did not know how to solve to get in the way of the lan­guage, I de­cid­ed to reim­ple­ment the ex­am­ple for the python book I am writ­ing: a text lay­out en­gine that out­puts SVG, based on harf­buz­z, freetype2 and oth­er things.

This is a good learn­ing project for me, be­cause a lot of my cod­ing is glue­ing things to­geth­er, I hard­ly ev­er do things from scratch.

So, I de­cid­ed to start in some­what ran­dom or­der.


I read the Nim Tu­to­ri­al quick­ly. I end­ed re­fer­ring to it and to Nim by ex­am­ple a lot. While try­ing out a new lan­guage one is bound to for­get syn­tax. It hap­pen­s.

Wrote a few "hel­lo world" 5 line pro­grams to see that the ecosys­tem was in­stalled cor­rect­ly. Im­pres­sion: builds are fast-ish. They can get ac­tu­al­ly fast if you start us­ing tcc in­stead of gc­c.

SVG Output

I looked for li­braries that were the equiv­a­lent of svg­write, which I am us­ing on the python side. Sad­ly, such a thing does­n't seem to ex­ist for nim. So, I wrote my own. It's very rudi­men­ta­ry, and sure­ly the nim code is garbage for ex­pe­ri­enced nim coder­s, but I end­ed us­ing the xml­tree mod­ule of nim's stan­dard li­brary and ev­ery­thing!

import xmltree
import strtabs
import strformat

    Drawing* = tuple[fname: string, document: XmlNode]

proc NewDrawing*(fname: string, height:string="100", width:string="100"): Drawing =
    result = (
        fname: fname,
        document: <>svg()
    var attrs = newStringTable()
    attrs["baseProfile"] = "full"
    attrs["version"] = "1.1"
    attrs["xmlns"] = ""
    attrs["xmlns:ev"] = ""
    attrs["xmlns:xlink"] = ""
    attrs["height"] = height
    attrs["width"] = width
    result.document.attrs = attrs

proc Add*(d: Drawing, node: XmlNode): void =

proc Rect*(x: string, y: string, width: string, height: string, fill: string="blue"): XmlNode =
    result = <>rect(

proc Text*(text: string, x: string, y: string, font_size: string, font_family: string="Arial"): XmlNode =
    result = <>text(newText(text))
    var attrs = newStringTable()
    attrs["x"] = x
    attrs["y"] = y
    attrs["font-size"] = font_size
    attrs["font-family"] = font_family
    result.attrs = attrs

proc Save*(d:Drawing): void =
   writeFile(d.fname,xmlHeader & $(d.document))

when isMainModule:
    var d = NewDrawing("foo.svg", width=fmt"{width}cm", height=fmt"{height}cm")

While writ­ing this I ran in­to a few is­sues and saw a few nice things:

To build a svg{.nimrod} tag, you can use <>svg(attr=value){.nimrod} which is delightful syntax. But what happens if the attr is "xmlns:ev"{.nimrod}? That is not a valid identifier, so it doesn't work. So I worked around it by creating a StringTable{.nimrod} filling it and setting all attributes at once.

A good thing is the when{.nimrod} keyword. using it as when isMainModule{.nimrod} means that code is built and executed when svgwrite.nim{.nimrod} is built standalone, and not when used as a module.

An­oth­er good thing is the syn­tax sug­ar for what in python we would call "ob­jec­t's meth­od­s".

Because Add{.nimrod} takes a Drawing{.nimrod} as first argument, you can just call d.Add(){.nimrod} if d{.nimrod} is a Drawing{.nimrod}. It's simple, it's clear and it's useful and I like it.

One bad thing is that some­times im­port­ing a mod­ule will cause weird er­rors that are hard to guess. For ex­am­ple, this sim­pli­fied ver­sion fails to build:

import xmltree

    Drawing* = tuple[fname: string, document: XmlNode]

proc NewDrawing*(fname: string, height:string="100", width:string="100"): Drawing =
    result = (
        fname: fname,
        document: <>svg(width=width, height=height)

when isMainModule:
    var d = NewDrawing("foo.svg")
$ nim c  svg1.nim
Hint: used config file '/etc/nim.cfg' [Conf]
Hint: system [Processing]
Hint: svg1 [Processing]
Hint: xmltree [Processing]
Hint: macros [Processing]
Hint: strtabs [Processing]
Hint: hashes [Processing]
Hint: strutils [Processing]
Hint: parseutils [Processing]
Hint: math [Processing]
Hint: algorithm [Processing]
Hint: os [Processing]
Hint: times [Processing]
Hint: posix [Processing]
Hint: ospaths [Processing]
svg1.nim(9, 19) template/generic instantiation from here
lib/nim/core/macros.nim(556, 26) Error: undeclared identifier: 'newStringTable'

WAT? I am not using newStringTable anywhere! The solution is to add import strtabs{.nimrod} which defines it, but there is really no way to guess which imports will trigger this sort of issue. If it's possible that importing a random module will trigger some weird failure with something that is not part of the stdlib and I need to figure it out... it can hurt.

In any case: it worked! My first work­ing, use­ful nim code!

Doing a script with options / parameters

In my python ver­sion I was us­ing do­copt and this was smooth: there is a nim ver­sion of do­copt and us­ing it was as easy as:

  1. nimble install docopt
  2. import docopt{.nimrod} in the script

The us­age is re­mark­ably sim­i­lar to python:

import docopt
when isMainModule:
    let doc = """Usage:
    boxes <input> <output> [--page-size=<WxH>] [--separation=<sep>]
    boxes --version"""

    let arguments = docopt(doc, version="Boxes 0.13")
    var (w,h) = (30f, 50f)
    if arguments["--page-size"]:
        let sizes = ($arguments["--page-size"]).split("x")
        w = parse_float(sizes[0])
        h = parse_float(sizes[1])

    var separation = 0.05
    if arguments["--separation"]:
        separation = parse_float($arguments["--separation"])
    var input = $arguments["<input>"]
    var output = $arguments["<output>"]

Not much to say, other that the code for parsing --page-size is slightly less graceful than I would like because I can't figure out how to split the string and convert to float at once.

So, at that point I sort of have the skele­ton of the pro­gram done. The miss­ing pieces are call­ing harf­buzz and freetype2 to fig­ure out text sizes and so on.

Interfacing with C libs

One of the main sell­ing points of Nim is that it in­ter­faces with C and C++ in a straight­for­ward man­ner. So, since no­body had wrapped harf­buzz un­til now, I could try to do it my­self!

First I tried to get c2n­im work­ing, since it's the rec­om­mend­ed way to do it. Sad­ly, the ver­sion of nim that ships in Arch is not able to build c2n­im via nim­ble, and I end­ed hav­ing to man­u­al­ly build nim-git and c2n­im-git ... which took quite a while to get right.

And then c2n­im just failed.

So then I tried to do it man­u­al­ly. It start­ed well!

  • To link li­braries you just use prag­mas: {.link: "/us­r/lib/lib­harf­buz­z.­so".}{.n­im­rod}

  • To de­clare types which are equiv­a­lent to void *{.n­im­rod} just use dis­tinct point­er{.n­im­rod}

  • To de­­clare a func­­tion just do some gym­­nas­tic­s:

    proc cre­ate*(): Buf­fer {.­head­er: "harf­buz­z/h­b.h", im­portc: "h­b_buffer­_$1" .}{.n­im­rod}

  • Cre­ates a nim func­tion called cre­ate{.n­im­rod} (the * means it's "ex­port­ed")

  • It is a wrap­per around hb_buffer­_cre­ate{.n­im­rod} (see the syn­tax there? That is nice!)

  • Says it's de­­clared in C in "har­f­buz­z/h­b.h"

  • It re­turns a Buf­fer{.n­im­rod} which is de­clared thus:

    Buffer* = distinct pointer

Here is all I could do try­ing to wrap what I need­ed:

{.link: "/usr/lib/".}
{.pragma: ftimport, cdecl, importc, dynlib: "/usr/lib/".}

    Buffer* = distinct pointer
    Face* = distinct pointer
    Font* = distinct pointer

    FT_Library*   = distinct pointer
    FT_Face*   = distinct pointer
    FT_Error* = cint

proc create*(): Buffer {.header: "harfbuzz/hb.h", importc: "hb_buffer_$1" .}
proc add_utf8*(buffer: Buffer, text: cstring, textLength:int, item_offset:int, itemLength:int) {.importc: "hb_buffer_$1", nodecl.}
proc guess_segment_properties*( buffer: Buffer): void {.header: "harfbuzz/hb.h", importc: "hb_buffer_$1" .}
proc create_referenced(face: FT_Face): Font {.header: "harfbuzz/hb.h", importc: "hb_ft_font_$1" .}
proc shape(font: Font, buf: Buffer, features: pointer, num_features: int): void {.header: "harfbuzz/hb.h", importc: "hb_$1" .}

proc FT_Init_FreeType*(library: var FT_Library): FT_Error {.ft_import.}
proc FT_Done_FreeType*(library: FT_Library): FT_Error {.ft_import.}
proc FT_New_Face*(library: FT_Library, path: cstring, face_index: clong, face: var FT_Face): FT_Error {.ft_import.}
proc FT_Set_Char_Size(face: FT_Face, width: float, height: float, h_res: int, v_res: int): FT_Error {.ft_import.}

var buf: Buffer = create()
buf.add_utf8("Hello", -1, 0, -1)

var library: FT_Library
assert(0 == FT_Init_FreeType(library))
var face: FT_Face
assert(0 == FT_New_Face(library,"/usr/share/fonts/ttf-linux-libertine/LinLibertine_R.otf", 0, face))
assert(0 == face.FT_Set_Char_Size(1, 1, 64, 64))
var font = face.create_referenced()
font.shape(buf, nil, 0)

Sad­ly, this seg­faults and I have no idea how to de­bug it. It's prob­a­bly close to right? Maybe some nim coder can fig­ure it out and help me?

In any case, con­clu­sion time!


  • I like the lan­guage
  • I like the syn­tax
  • nim­ble, the pack­age man­ag­er is cool
  • Is there an equiv­a­lent of vir­tualen­vs? Is it nec­es­sary?
  • The C wrap­ping is, in­deed, easy. When it work­s.
  • The avail­abil­i­ty of 3rd par­ty code is of course not as large as with oth­er lan­guages
  • The com­pil­ing / build­ing is cool
  • There are some strange bugs, which is to be ex­pect­ed
  • Tool­ing is ok. VS­Code has a work­ing ex­ten­sion for it. I miss an opin­ion­at­ed for­mat­ter.
  • It pro­duces fast code.
  • It builds fast.

I will keep it in mind if I need to write fast code with lim­it­ed de­pen­den­cies on ex­ter­nal li­braries.

Código Charla PyDay "Como Hacer una API REST en Python, spec first"

El 4/4/2018 di una char­la en un Py­Day so­bre co­mo im­ple­men­tar una API REST a par­tir de una es­peci­fi­cación hecha en Swag­ger/Ope­nAPI us­an­do Con­nex­ion


Fo­to toma­da por Yami­la Cues­tas

Si bi­en no pude grabar la char­la (al­guien en la au­di­en­cia si lo hi­zo, pero no me dio el video! Pasame el video, per­sona de la au­di­en­ci­a!) y no hay slides, acá es­tá el códi­go que mostré, que es rel­a­ti­va­mente sen­cil­lo y fá­cil de seguir.

Códi­go de la char­la

Cualquier cosa pre­gun­ten.

PD: Sí, po­dría hac­er la char­la en un video nue­vo. Sí, me da mucha pereza.

My Git tutorial for people who don't know Git

As part of a book project aimed at al­most-be­gin­ning pro­gram­mers I have writ­ten what may as well pass as the first part of a Git tu­to­ri­al. It's to­tal­ly stan­dalone, so it may be in­ter­est­ing out­side the con­text of the book.

It's aimed at peo­ple who, of course, don't know Git and could use it as a lo­cal ver­sion con­trol sys­tem. In the next chap­ter (be­ing writ­ten) I cov­er things like re­motes and push/pul­l.

So, if you want to read it: Git tu­to­ri­al for peo­ple who don't know git (part I)

PS: If the di­a­grams are all black and white, reload the page. Yes, it's a JS is­sue. Yes, I know how to fix it.

I have written half a book

LIke men­tioned be­fore I am try­ing to write a book and ... well, I may be ac­tu­al­ly mak­ing pro­gress? At least the gen­er­at­ed PDF is about 170 pages long, which means I have writ­ten a bunch in this past month.

I have fin­ished the sec­ond of four planned part­s, which means I have done about half of it. Since I ex­pect the next two parts to be short­er, it's ac­tu­al­ly more than that.

The tar­get au­di­ence are peo­ple who have fin­ished the python tu­to­ri­al but are not ex­act­ly pro­gram­mers yet. They have the syn­tax more or less in their head­s, but how do you turn that in­to an ac­tu­al piece of code?

  • Part 1 is about "pro­­to­­typ­ing", the process of dump­ing an idea in­­­to rough code.

  • Part 2 is about pol­ish­ing that rough code in­­­to ... not so rough code. In­­­cludes a gen­­tle in­­tro­­duc­­tion to test­ing, for ex­am­­ple.

  • Part 3 (to be writ­ten) is about things that are not code:

    • Git / Git­lab

    • Is­­­sues

    • Pack­­­ag­ing

    • Set­t­ing up a we­b­site

    • CI

    • Lots more

  • Part 4 is still to be thought but ba­si­­cal­­ly it will cov­­er im­­ple­­men­t­ing a large fea­­ture from the ground up.

I much ap­pre­ci­ate com­ments about it.

PD: Si, va a haber una tra­duc­ciń al castel­lano. O mas bi­en al ar­genti­no. Una vez que lo ter­mine.

Contents © 2000-2024 Roberto Alsina