• Convert HTML files to PNG

For some stupid reason I ended up having to convert a whole lot of HTML files to images. Not wanting to waste space, the plan was to compress the files as much as possible without loosing too much quality.

So here’s how to do it:

Here’s what each line does:

• for f in *.html; do will loop through each .html file in the current directory
• wkhtmltoimage -f png $f$f.png will convert the .html files to .png (see the wkhtmltoimage project page)
• mogrify -trim $f.png will auto-crop the image and cut off the body padding, this saves a few bytes (see the mogrify documentation) • pngquant --speed 1$f.png --ext .png.o compresses the .png files (note that pngquant uses lossy compression; to compress losslessly, use pngcrush instead)
• mv $f.png.o$f.png replaces the original png with the optimised one
• Vim essentials

Here is a list of Vim scripts I picked up in the past few years that I find very useful. All of them can be found as submodules in my dotvim repo.

I am attaching my own rating to the scripts, but these aren’t really objective. They are merely an indication how much I ended up using the scripts. For example, vim-fugitive is so damn powerful it deserves a sixth star, but I just prefer to use git from the command line rather than from Vim.

Tim Pope’s scripts, in order of usefulness:

• pathogen is the single most useful plug-in for Vim! ★★★★★
• repeat for repeating plug-in maps ★★★★★
• sensible is a set of very useful defaults ★★★★★
• sleuth sets shiftwidth and expandtab in a smart way ★★★★★
• abolish for abbreviation, substitution & correction ★★★★☆
• commentary to comment stuff out ★★★★☆
• haml for haml, sass, and SCSS ★★★★☆
• liquid for liquid runtime files with jekyll enhancements ★★★☆☆
• markdown for markdown runtime files ★★★☆☆
• surround makes quoting/parenthesizing simpler ★★☆☆☆
• fugitive is “a git wrapper so awesome, it should be illegal” ★★☆☆☆
• speeddating makes date/time manipulation easier ★☆☆☆☆
• unimpaired are complementary pairs of mappings ★☆☆☆☆
• pyflakes (my fork) enables PyFlakes checking for Python files ★★★★★
• jedi enables jedi’s auto-completion for Python files ★★★★☆

Others that I’ve tried:

• coffee-script for those .coffee files ★★★★★
• golang is the official Go Vim script ★★★★★
• less is the Vim syntax file for LESS ★★★★★
• css3-syntax adds CSS3 syntax support to Vim’s built-in syntax/css.vim ★★★★☆
• markdown-folding allows folding markdown documents by section ★★★★☆
• colors-solarized is a “precision” colour scheme “for machines and people” ★★☆☆☆
• css-color is a nice concept, but I couldn’t get it to work ☆☆☆☆☆

Check out my dotvim repo or this screencast by Tim Pope for tips on how to put them all together.

• A Walter számok halmaza

Ajánlom minden olyan ismerősöm figyelmébe, aki azt hiszi, hogy a gyök kettő nem is igazi, az $i$ pedig egyáltalán nem létezik.

Szóval kezdett elegem lenni abból, hogy egyesek néhány sör után elkezdik támadni a számukra ismeretlen matematikai fogalmak sokaságát azzal az érvvel, hogy olyan nincs is. Igen, a gonosz matematikusok kitalálnak mindenféléket csak azért, hogy ezzel is bosszantsák a köznépet.

Hosszas gondolkodás után arra jutottam, hogy az emberek legnagyobb része úgy néz minden matematikai fogalomra, hogy azt próbálja beleerőltetni a számára ismeretes fogalmak rendszerébe, és ha nem megy, akkor az új fogalom minden bizonnyal lehetetlen.

Vegyük például a $\sqrt{2}$-t. Sok ember számára az irracionális számok egyszerűen nem léteznek ($\mathbb{I} = \varnothing$). A számok összessége tehát a racionális számok ($\mathbb{Q}$) halmazára korlátozódik. Ha egy ilyen személynek azt mondjuk:

Képzeld Feri1, $x^2=2$ .

Feri ezt így értelmezi:

Képzeld Feri, $x^2=2 \land x \in \mathbb{Q}$ .

És így válaszol:

De hát Jola2! $x \in \varnothing$ !

A racionális számokkal ($\mathbb{Q}$) már többen ki vannak békülve, az egész számokat ($\mathbb{Z}$) pedig mindenki komázza. Pedig ha ugyanezt megcsináljuk egy gyerekkel:

Szia Peti! Hallottad? $x = 1-2$ !

Peti fejében:

Szia Peti! Hallottad? $x = 1-2 \land x \in \mathbb{N}$ !

De Attila, hiszen $x \in \varnothing$ !

És aztán megkérdezzük Ferit,

Feri, mit szólsz Peti válaszához?

Ne bántsd már! Peti alig múlt kettő, majd ha nagyobb lesz, megérti.

Pedig Peti és Feri ugyanazt a hibát követik el: a kérdést úgy értelmezik, ahogy az az ismereteiknek megfelel. És sok egyetemet végzett ismerősöm is ugyanúgy belesétál ebbe.

Ezért szeretném kihangsúlyozni minden kedves olvasó számára, hogy amikor azt mondja valaki, hogy $x^2 = -1$, azt nem úgy érti, hogy $x^2 = -1 \land x \in \mathbb{R}$, mert hát $x = i$, és ezzel meg is ismertük a komplex számok halmazát:

Itt sem kell megállni, hogy “jól van, több már úgysincs”, mert én meg azt mondom:

Nyilvánvaló, hogy $x \notin \mathbb{C}$. Ez viszont nem jelenti azt, hogy $x \in \varnothing$, mert nem adtam meg semmilyen “fölső határt” $x$-re. Sőt, a fönti egyenlőségrendszernek számtalan megoldása van, csakhogy egyik sem komplex. (A kortárs matematikában a fönti képlet megoldását $j$-vel szokták jelölni.)

A számtalan megoldás közül csak egyet említenék meg:

$x =$

Ezzel definiáljuk az ún. Walter-féle számokat:

$\mathbb{W} = \{w \colon w = (a$ $+b) \land a, b \in \mathbb{C} \land$ $^2 = 1 \land$ $\notin \{i^n \colon n \in \mathbb{R} \land i^2 = -1\}\}$

A $\mathbb{W}$ halmazt a többi számhoz viszonyítva az alábbi Venn-diagrammal szemléltetem:

Melyben:

• $\mathbb{N}$ a természetes számok halmaza,
• $\mathbb{N}_0$ a természetes számok $0$-val kibővített halmaza
• $\mathbb{Z}$ az egész számok halmaza,
• $\mathbb{Q}$ a racionális számok halmaza,
• $\mathbb{I}$ az iracionális számok halmaza,
• $\mathbb{A}$ az algebrai számok halmaza,
• $\mathbb{R}$ a valós számok halmaza,
• $\mathbb{A}_R$ az algebrai és a valós számok halmazainak metszete,
• $\mathbb{C}$ a komplex számok halmaza,
• $\mathbb{W}$ a Walter számok halmaza.

A Walter számok halmazára érvényesek a következők:

• A $\mathbb{W}$ halmaz számossága $\aleph_2$ (lásd: kontinuumhipotézis).
• A $\mathbb{W}$ halmaz nem kapható meg Cayley–Dickson konstrukcióval (más szóval nem kvaternion).
• Ha a $(G; \oplus)$ csoport kommutatív (azaz Abel-csoport), és a $G$ halmaz egységeleme a , akkor (és csakis akkor) a $(G; \oplus)$ csoportot Walter-csoportnak nevezzük.
• Ebből következik, hogy $W = (G, \oplus, \otimes)$ test Walter-test akkor és csakis akkor, ha $(G; \oplus)$ Walter-csoport, továbbá
• a $\mathcal{W} = (G, \oplus, \otimes)$ gyűrű Walter-gyűrű akkor és csakis akkor, ha $(G, \oplus)$ Walter-csoport.

1Feri nevét megváltoztattuk a pofonok elkerülése érdekében.

2Az én nevemet is megváltoztattuk.

• Why back-end programming is hard

Or to put it in another way, why is font-end programming way easier.

I have a very simple theory about this matter. Because of the difference in what people consider being a product in each case, the process of writing and maintaining front-end code often becomes a lot different than writing a back-end.

The way a manager would look at a client app is something along these lines:

• developer writes code in a programming language
• computer translates this code into a usable app
• the app is tested directly by testers
• if it works fine, the app gets distributed
• people generate feedback
• manager turns feedback into tasks
• goto step 1

It is clear that the compiled, ready-to-use app is the product of the developer’s work and this is the only level where the programmer gets feedback on this work.

Very often nobody will care:

• which frameworks or utilities are used (as long as licences permit it)
• whether the code complies with standards of the programming language
• whether the files themselves are clean (sane line endings, no mixed tabs/spaces, trailing whitespace, newline at end of files, etc.)
• how data structures and other internals get implemented
• whether the code passes linters

…and in general, it is likely that (other than the programmer) nobody will even look at any code.

On the other hand, when a back-end developer is designing a service or and API, the product becomes the code itself, and not the service. Testers cannot install the service on their smart phones to test it, but it is still important to make sure it works well.

Even more important than for the client app: who cares if the app breaks for a few users, but if something goes wrong in the back-end, the whole project is doomed.

Requirements are now different:

• the code needs to be fully tested
• unit tests must cover all the logic
• integration tests have to make sure it all fits together
• add continuous integration so it doesn’t break during development
• regular code reviews are suddenly very important
• coding style now matters

And with that comes that now every framework, library, service or other dependency used by the back-end has to be a proven requirement, or it doesn’t get used. Managers don’t understand how the service works, in fact all they know are the requirements, but they have to be able to read the code and understand the entire test suite.

Commit messages now have to be well descriptive so non-devs can understand what each commit is about. Pull requests have to contain summaries so they don’t have to read the commit messages. Milestones have to be maintained and wiki pages must document every aspect of the code.

It must be noted that I am not agaienst rigorously maintaining code quality, but people should know that it is quite different to write quality code than code that will never even be read.

• To lint or not to lint

In general it is always a good idea to run static checkers through the code. It catches some obvious mistakes and helps maintain a readable code base — at least most of the time. But some checkers are quite aggressive, or some rules may be too outdated or simply don’t match the preferred coding style of the programmer.

Nevertheless, here are my two cents on linters and other static checkers:

A short snippet of in-line code is fine, but anything that resides in its own .js file deserves a lint. If you have to write JavaScript (*cough*coffee*cough*script*cough*), you have to lint it. To keep the bad parts out.

• Go: always run gofmt and go vet!
• Python: well, that’s a tricky one…

• pyflakes is a must, it will catch not just errors, but things like unused imports and locals, re-defined variables and such.
• pep8 should be run too, but you may want to disable some checks if you’re like me (I don’t quite agree with the visual/hanging indent rules and sometimes I don’t want to try and fit in <79 char lines)
• autopep8 can be useful sometimes, though it is best to not let things out of hand so much to need it in the first place
• flake8 is a handy combination of pyflakes and pep8
• pylint is useful but very strict; it will force you to split functions but won’t let you use too many function arguments; but at least it will rate your code on a 1-10 scale.

For less-strict checkers like gofmt and pyflakes, it is a good idea to install them as commit hooks. There are also vim plug-ins for most of these, so you see the problems right as you edit the file (or when saving). The advantage of of the static regex-based checkers is that they are fast enough to run on every change you make to the buffer.

Update

For Go there is also golint, which can be useful, for example it detects for x, _ := range and reports to drop the _; However, it mostly complains about missing comments :) And there’s also this.

• Coding style

It happened to me more than once that I wrote some code that looked more or less like this (simplified to avoid disclosure):

But after some code review it mutated into this beast:

Functionally, nothing has changed (or rather, I’m not talking about functional changes here). But how the coding style has changed is the result of a compromise among members of the review.

My preference is, of course, the first example (since I wrote it), because:

• it is shorter and simpler
• I understand it quite easily
• _by_author is redundant since the method is defined on the Author class.
• list_of_ is redundant as the plural of reviews implies a list (or more correctly, a collection, which can be any iterable)
• get_ doesn’t make much sense either, since we don’t have a setter, and it is obvious by looking at the method that it returns something

Arguments for the second example are usually:

• it is more explicit
• a new developer can look at the method’s name and see what it does
• a non-developer can look at it and have an idea of what might be going on

The accompanying argument is that code (and unit tests and functional tests) should be written in such a way that non-developers can understand it. I don’t agree with that point, to me it is OK that only developers understand code, but it certainly makes project management easier.

Unfortunately when it comes to a compromise, there isn’t much to do. The developer accepts the changes (after all, they’re just cosmetics), and carries on with the new code style. Since the code in question is Python, there isn’t a strict enough style guide that can help. While PEP8 has loads of instructions on how to format the code, it doesn’t say that much about semantics like naming things.

For that matter, I’d like to point out that Go has some guidelines for this. Effective Go lists the following naming conventions:

• getters should be named like Owner(), not GetOwner()
• methods that convert to a well-known type should be named like String(), not ToString()

I like to apply those to Python as well. With a simple naming convention, even with a terse syntax, code should be readable enough that a new developer can understand it. As for non-developers, there are plenty of statistical code analysing services and tools that analyse complexity, standard compliance, test coverage, etc.

Update

pylint suggests method names should be not longer than 30 characters (they should match [a-z_][a-z0-9_]{2,30}\$), so the second example still passes the lint check, although just barely.