Екстерно, со компромиси и неколку анегдоти

Два дена по масовниот студентски протест и еден ден по изјавата на министерот за образование, својот став го кажа и премиерот на Република Македонија. Видео веста од две минути и текстот може да ги најдете тука.

Еве кои работи ги приметив јас во неговата изјава.

1.

Прво, за тоа што не го кажа: за разлика од министерот вчера, не се обиде да ја наметне идејата дека СДСМ (или партија) стои позади протестот. Премиерот на луѓето кои протестираа им се обрати со студенти.

Да видиме како дојде до ова.

Прво, провладините медиуми го игнорираа протестот. Наспроти нив, малкуте слободни медиуми и голем број портали објавија фотографии, а на Time.mk до 16ч. дента веќе имаше кластер од 80-тина вести. Во очекување на стандардното етикетирање, Libertas.mk објавија одлично напишана пара-вест во која, меѓу другите, на слика го заокружија Kenny од South Park како „инфилтриран Американски агент.“

Кога по некое време излезе министерот со очекуваната реторика „не мислам дека се студенти тие што го организираат протестот“ само звучеше смешно и не допре до никого. Денеска премиерот не се ни обиде да го тврди истото.

Поентата ми е: некогаш за да манипулираш не е доволно да ги имаш купено повеќето медиуми. На пример кога има (релативно) масовни протести.

2.

Првата измена која премиерот ја споменува во неговата кратка изјава е оваа:

Така, тестирањето нема да важи за актуелните студенти,
туку за оние кои ќе се запишат на факултет од
следната акдемска година.

Резонирањето позади измената е дека до 2018-та година, кога ќе биде првото тестирање, институциите ќе имаат време да се подготват, технички и кадровски.

Јас би ја парафразирал изјавата:

Еј, студенти, вие што студирате сега – немате гајле. Вие терајте си, нема што да протестирате, вас екстерново не ве фаќа. Тоа што браќата и сестрите ќе бидат тестирани, ич да не му ја мислите.

Звучи како обид на сегашните студенти – како што сум јас и како тие кои ги видовме на улица – да им се одземе од иницијативата за протестирање.

3.

Понатаму во текстот, го пишува ова:

Нема да има санкации за професорите, и во случај
студентот да не го положи испитот, како што случај
со екстерното тестирање за основно и средно образование.

И ова:

Понатаму, според нашите информации, важна новина е што
на студентите кои нема да го положат испитот, нема да
им биде прекинато студирањето, туку ќе им биде дадена
можност да го полагаат колку што сакаат пати, но секој
нареден испит ќе го плаќаат поскапо.

Ќе ви ја раскажам приказната за Бобан.

Бобан беше студент кој безгрижно и среќно си ги поминуваше студентските денови не појавувајќи се на факултет. Колегите едвај да го познаваа. Сепак, на крајот на втората година, Бобан ги имаше исчистено сите предмети: со шестки, но сепак – имаше положено 20 испити на број.

Во текот на овие две години на Бобан му предаваа 15 професори (некои од нив држеа по два предмети). Секој од тие професори на Бобан му напиша шестка. Некои беа похрабри па му ставија седмица или осмица. Деталите зошто и како не ги знае никој.

Кога дојде денот Бобан да го полага екстерниот испит, Бобан – се разбира – падна. Без многу негодување, тој ја прифати одлуката и одново се запиша во втора. Денеска, десет години подоцна, Бобан сѐ уште студира, а татко му секоја година ги плаќа сѐ поскапите тестирања.

А, 15-те професори на Бобан, и тие продолжија како порано: сѐ уште предаваат и оценуваат, чесно, како што доликува на еден професор.

4.

Кога сме веќе кај измислени приказни, еве уште една:

Ѕидовите на читалната добро ја познаваат Алиса. Речиси секое попладне од учебната година, Алиса поминува по неколку часа наведната над клупата и го прави она што студентите (кога не се пијани) го прават: учи.

Алиса студира на приватен факултет. Разочарана од бирократијата која ја искуси во средно, Алиса беше решена никогаш веќе да не се запише во државна образовна институција. Нејзините стегнаа заби и собраа пари, ја поддржаа во намерата.

По првиот семестар, Алиса почна да си ја оспорува одлуката. Факултетот на кој се запиша беше прилично нов, а неговиот сопственик имаше историја која ги допираше сите области, освен академската. На факултетот предаваа шака професори и секој од нив предаваше 10 предмети. Критериумите за положување беа ужасно ниски: Алиса учеше 5% од тоа што нејзините колешки на Електро го учеа, но таа не беше свесна за тоа, а кога ѝ укажуваа на тоа, мислеше дека претеруваат.

Кога конечно ѝ го поделија тестот на Алиса, не ѝ остануваше многу освен да се препотува и да го предаде тестот едвај до пола решен.

Алиса веќе не е студент. Нејзините немаа пари да ѝ платат уште една година и уште едно – сега поскапо – тестирање.

Факултетот и неговиот сопственик уште се крпат некако, ги нема стигнато лошиот збор.

А Бобан? Океј му е него.

Http://new

If you try to open http://new in your browser you expect to get a connection error of some sort. But that’s not what happened to me. Instead the browser ended up serving me Apaches’ default “It works!” page.

http://new page

Naturally, I got curious.

First, I checked if the browser was modifying the request:

1
2
3
4
5
6
who# curl http://new

<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>

That wasn’t it. I checked the ip address:

1
2
3
4
5
6
7
who# ping new
PING new (127.0.53.53) 56(84) bytes of data.
^C64 bytes from 127.0.53.53: icmp_seq=1 ttl=64 time=0.054 ms

--- new ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.054/0.054/0.054/0.000 ms

Okay, so it’s the Apache server on my own computer. (I learned every 127.x.x.x address points to localhost.) But why does new resolve to localhost? It wasn’t the /etc/hosts file:

1
2
3
4
who# cat /etc/hosts

127.0.0.1 localhost
127.0.1.1 who

I checked to see if I have a running local DNS server:

1
2
3
who# ps aux | grep dns

nobody    3016  0.0  0.0  35200   836 ?        S    сеп04   0:43 /usr/sbin/dnsmasq --no-resolv --keep-in-foreground --no-hosts --bind-interfaces --pid-file=/var/run/NetworkManager/dnsmasq.pid --listen-address=127.0.1.1 --conf-file=/var/run/NetworkManager/dnsmasq.conf --cache-size=0 --proxy-dnssec --enable-dbus=org.freedesktop.NetworkManager.dnsmasq --conf-dir=/etc/NetworkManager/dnsmasq.d

Just to be sure, I checked for open connections on UDP 53:

1
2
3
4
5
6
7
8
who# netstat -ulnp

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name

udp        0      0 127.0.0.1:47146         0.0.0.0:*                           8744/skype
udp        0      0 127.0.1.1:53            0.0.0.0:*                           3016/dnsmasq
udp        0      0 0.0.0.0:68              0.0.0.0:*                           25372/dhclient

dnsmasq was indeed listening for UDP connections on port 53. At this point, I suspected some process was dynamically assigning himself the new hostname. My main suspect was Vagrant. A friend pointed out that it might be possible for another process to add a DNS records via dbus so we decided to investigate.

We tried using qdbus to try and communicate with dnsmasq but it didn’t go very well:

1
2
3
4
5
6
7
8
9
10
11
12
who# qdbus --system org.freedesktop.NetworkManager.dnsmasq /uk/org/thekelleys/dnsmasq

method QString org.freedesktop.DBus.Introspectable.Introspect()
signal void org.freedesktop.NetworkManager.dnsmasq.DhcpLeaseAdded(QString ipaddr, QString hwaddr, QString hostname)
signal void org.freedesktop.NetworkManager.dnsmasq.DhcpLeaseDeleted(QString ipaddr, QString hwaddr, QString hostname)
signal void org.freedesktop.NetworkManager.dnsmasq.DhcpLeaseUpdated(QString ipaddr, QString hwaddr, QString hostname)
method void org.freedesktop.NetworkManager.dnsmasq.ClearCache()
method QString org.freedesktop.NetworkManager.dnsmasq.GetVersion()
method void org.freedesktop.NetworkManager.dnsmasq.SetDomainServers(QStringList servers)
method void org.freedesktop.NetworkManager.dnsmasq.SetServers(QVariantList servers)

zsh: segmentation fault (core dumped)  qdbus --system org.freedesktop.NetworkManager.dnsmasq 

I wasn’t too eager to go into analysing why qdbus segfaulted, so I decided to approach it another way. I should’ve tried this sooner:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
who# dig new

; <<>> DiG 9.9.3-rpz2+rl.13214.22-P2-Ubuntu-1:9.9.3.dfsg.P2-4ubuntu1.1 <<>> new
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24344
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 5, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;new.             IN  A

;; ANSWER SECTION:
new.          3576    IN  A   127.0.53.53

;; AUTHORITY SECTION:
new.          4935    IN  NS  ns-tld1.charlestonroadregistry.com.
new.          4935    IN  NS  ns-tld2.charlestonroadregistry.com.
new.          4935    IN  NS  ns-tld3.charlestonroadregistry.com.
new.          4935    IN  NS  ns-tld4.charlestonroadregistry.com.
new.          4935    IN  NS  ns-tld5.charlestonroadregistry.com.

;; Query time: 12 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Thu Sep 18 14:32:25 CEST 2014
;; MSG SIZE  rcvd: 184

To my surprise, the domain appeared to exist globally. I followed charlestonroadregistry.com which redirected me to google.com/registry/.

From the contents of the page it was obvious what was the matter: Google was releasing top level domains soon and .new was one of them. Digging for ads or zip answered with the same 127.0.53.53 address.

I was curious if com or org also had their own IP address:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
who# dig com

; <<>> DiG 9.9.3-rpz2+rl.13214.22-P2-Ubuntu-1:9.9.3.dfsg.P2-4ubuntu1.1 <<>> com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7725
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;com.             IN  A

;; AUTHORITY SECTION:
com.          900 IN  SOA a.gtld-servers.net. nstld.verisign-grs.com. 1411051494 1800 900 604800 86400

;; Query time: 17 msec
;; SERVER: 127.0.1.1#53(127.0.1.1)
;; WHEN: Thu Sep 18 16:45:20 CEST 2014
;; MSG SIZE  rcvd: 105

There was a record, but only AUTHORITY SECTION: was present, ANSWER SECTION: was missing. I had no clue why they would differ. Then, another friend, who works as a sys-admin, pointed me to this ICANN announcement which reports:

The framework is designed to mitigate the impact of name collisions in the domain name system (DNS), which typically occur when fully qualified domain names conflict with similar domain names used in private networks. When this occurs, users can be taken to an unintended Web page or encounter an error message.

To address this issue, the framework calls for registry operators to use a technique called “controlled interruption” to alert system administrators that there may be an issue in their network. Specifically, an IPv4 address – 127.0.53.53 – will appear in system logs, enabling a quick diagnosis and remediation.

So Google’s domains, being within the 90-day “starting” period, were using 127.0.53.53 to warn system administrators for possible incoming domain name collisions with their local domain names. Which is why dig com doesn’t return an IP address, while new does.

Which solves the mystery.


This whole adventure, BTW, started because I wanted to open news.ycombinator.com; I wrote new in the address bar and hit Enter before Firefox had a chance to autocomplete the URL.

PureScript: Connecting It With JavaScript

Parent post: Thoughts on building a PureScript app

PureScript is a language that’s compiled to JavaScript. When I first thought about this, I kinda understood it, but not quite. Okay, the output is valid JavaScript, but how do the two languages relate? If I write something in PureScript, how do I use it in JavaScript?

And vice versa: all those JavaScript libraries, how can I import them in PureScript?

Here’s how I think about it: JavaScript is this messy language full of unsafe and bad and ugly and PureScript should be it’s… well, pure cousin. But I can’t use PureScript in isolation. At the end, it will take data from the real messy world, it will communicate with JavaScript, so I better learn how to separate the two worlds in a safe manner.

Calling PureScript functions

Lets create a simple module which will contain an add function:

1
2
3
4
module MyMath where

add :: Number -> Number -> Number
add a b = a + b

Saving this little script to MyMath.purs and compiling it with:

psc MyMath.purs --browser-namespace PureScript > index.js

will generate a file which we can import in our test index.html page:

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
<head>
  <script src="index.js"/>
</head>
<body>
</body>
</html>

Upon loading the script, we can access our function like this:

1
2
var res = PureScript.MyMath.add(3)(4);
console.log(res); // will print 7

A couple of notes here:

  • The --browser-namespace PureScript flag I used told the compiler to export all modules in an object called PureScript. If you leave this flag out, the name of this object will default to PS
  • The reason why I call MyMath.add(3)(4) in this rather strange way is because functions exported by PureScript always take exactly zero or one arguments. MyMath.add(3) in fact returns a new function which takes the second argument, which feels really strange if you’ve never seen it before. If you want to know more about why it is like that, you can check the Wiki article on currying

Co calling PureScript code is easy:

  1. Write your modules
  2. Compile them into an index.js script
  3. Import the script in the index.html page
  4. Call your functions

Calling JavaScript functions

The first resource you want to check out is the PureScript documentation on Foreign Function Interfaces.

The next thing you need to realize is this: at the end of the day, PureScript is just JavaScript that runs in some context. There are global variables around. You just can’t see them by default.

Let’s upgrade the example above. We’ll define a function in the global scope:

1
2
3
4
5
6
7
8
9
10
11
<!-- index.html -->
<head>
  <script type="text/javascript">

    happySadParity = function(number) {
      return number % 2 == 0 ? "Happy!" : "Sad. :(";
    }

  </script>
  <script src="index.js"/> <!-- our PureScript file -->
</head>

Now let’s reference it from our compiled PureScript code:

1
2
3
4
5
6
7
8
9
module MyMath where

foreign import happySadParity :: Number -> String

add :: Number -> Number -> Number
add a b = a + b

emotionalSum :: Number -> Number -> String
emotionalSum a b = happySadParity $ add a b

And finally, let’s call our new function:

1
2
var res = PureScript.MyMath.emotionalSum(3)(4);
console.log(res); // will print "Sad. :("

Let’s revise. In order to call a JavaScript function from PureScript, you need to:

  1. Have the function defined in the scope
  2. Import it with foreign import yourFunction :: InputType -> OutputType
  3. Use it like it’s a PureScript function

Hopefully, life makes sense now.

Important closing notes

There are other ways of compiling PureScript

Instead of running psc which combines all modules in a single file, you can use psc-make. The difference is: psc-make exports CommonJS modules in separate folders in a directory called output.

This is particularly interesting if you’re using PureScript functions from Node.js. If you copy the contents of output you should be able to do this:

1
2
var myMath = require('MyMath');
console.log(myMath.add(10, 20));

You can define JS functions inline

Instead of writing:

1
foreign import happySadParity :: Number -> String

which relies on having happySadParity in scope, you can just define the function on the fly:

1
2
3
4
foreign import happySadParity "\
\  function happySadParity(n) {\
\    return number % 2 == 0 ? 'Happy!' : 'Sad. :(';\
\  }" :: Number -> String

Is it safe?

No, it’s not. By binding code this way, you get none of the safety that PureScript offers.

Think about it. If you shove an exception in a PureScript function that doesn’t know how to handle it, well, your script will crash, no matter how typechecked the language is.

Likewise, if you call a JavaScript function and you’re not prepared for it to to return null or undefined — you’re screwed.

How do I make it safe?

I’ll cover that topic in another post which I’ll link here.

Thoughts on Building a PureScript App

For some time now I’ve been interested in learning functional programming more deeply. I’m already familiar with some concepts: pure vs. impure functions, what does it mean for some code to cause side-effects, what are higher-order functions etc. I try to refactor my imperative code in such a way that most of it remains pure, while I pull out the impurities.

However, I’ve never wrote anything substantial in a purely functional language. By substantial I mean more then a recursive factorial function. I started reading “Learn You a Haskell for Great Good!” one year ago but I didn’t get past the “Oh, cool!” stage.

Now I want to try something different. I’ve set myself a task: build an HTTP server on which I can play Dominoes.

The reason why I chose Dominoes is because I’m familiar with the domain; I already built the game in Node.js for Gambit.com so I have the API and model figured out. Now I want to try and rebuild a simplified version – in PureScript.

PureScript is a language that resembles Haskell a lot. The main difference is that it compiles to JavaScript, which makes it possible to also use it on the client. It has two-way bindings with JavaScript so you can: 1) call PureScript functions from JS and 2) call JS functions from PureScript.

As I’m fighting my way through, I’ll do a series of posts which describe how I feel and what I’ve learned.

Here’s the project on GitHub: https://github.com/whoeverest/dominoes-purescript

List of posts in the series:

The “Read” Bookmarklet

Every once in a while, I open a page that I want to read, and it looks like this:

wide-page.png

No max-width and small font-size, which makes it unreadable.

To fix this, I’ve created a really tiny bookmarklet which narrows the page and proportionally enlarges the font size, so it looks like this:

narrow-page.png

The code:

1
2
3
4
5
6
7
8
javascript:(function() {
  var b = document.getElementsByTagName('body')[0];
  b.style.width = '40em';
  b.style.background = 'white';
  b.style.fontSize = '1.2em';
  b.style.marginLeft = 'auto';
  b.style.marginRight = 'auto';
})()

If you want to try it out, just create a new Bookmark, then paste the code above in the URL field.

The Cumulative Fuckup of Impure Code

You know why keeping a purely functional codebase written in a mostly imperative language is hard?

If you have stack of five nested and impure functions and you refactor one of them so it becomes pure, now you have four impure functions and one pure function.

If you have a stack of five nested pure functions and you introduce a side effect in the inner-most function, now you have at least five impure functions.

My question is: how does one bubble the side effects up?

Fixing “Toggl” Symlink Problem on Linux

I started using Toggl recently and upon installing and symlinking it, I came to the following error:

1
2
3
4
:~/programs$ toggl 
terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_S_construct null not valid
Aborted (core dumped)

Running the program normally with ./TogglDesktop worked fine, but when using the symlink caused the error.

The problem was (as Damjan knew all along) that Toggl expected the path to itself as the first argument in argv []. This path was missing / wrong (don’t know really) when the binary was symlinked.

To fix, I created a Bash script:

1
2
3
#!/bin/sh

~/programs/TogglDesktop/TogglDesktop

made is executable:

1
chmod +x run.sh

and symlinked it instead of the binary:

1
sudo ln -s ~/programs/Toggl/run.sh /usr/local/bin/toggl

I hope it helps someone.

“-webkit-animation: Cubemove” in Chrome 29 Can Overheat Your CPU

Open this page and carefully monitor the temperature of your CPU.

http://whoeverest.github.io/spinner/

It is steadily going up? If it is, it’s time to update Chrome. Today the sensors on my CPU measured 97°C and it was all because I had this tab open in the background. Yep, just those two orange boxes rotating around each other.

I was running Chrome v29 under Ubuntu 13.10.

The problem was how webkit-animation: cubemove was being rendered in this older version of Chrome. Running apt-get update followed by apt-get upgrade solved the problem for me.

Now I’m running Chrome v33 and everything’s cool.

I recorded a video while I was debugging:

I’m running watch sensors in the top-right terminal. When I load the page, the temperature raises to +70°C. When I disable the CSS statement, it drops back to ~50°C.

Weird stuff.

Small Changes That Make Code More Debuggable

Name the return expression

If you change:

1
2
3
function add(a, b) {
    return a + b;
}

to:

1
2
3
4
function add(a, b) {
    var res = a + b;
    return res;
}

you can console.log(res) to see if it has the correct value. In the first case, you have to copy-paste the a + b expression. It’s more DRY if you don’t copy-paste.

Wrap the one-line body in brackets

This obviously matters only in a language with optional brackets around one-liners like:

1
2
if (something)
    do_something();

If you to see if the code enters the branch, by inserting console.log , you have to add the brackets afterwards. If you always put brackets, no matter the length of the body, you’ll always be able to debug. Plus, it works for situations where the body gets bigger later.

So instead write:

1
2
3
if (something) {
    do_something();
}

The Curious World of “Chances” in Games

If we were to sort games according to “how much does chance play a role in deciding the winner” we can place all games on a spectrum, with “Chess” being leftmost – not playing any role – and “Throwing Dice” where it’s up to the universe which side comes up.

Chess

In Chess, players take turns at moving one figure at a time (two while castling) on a 8x8 board consisting of 32 black and 32 white squares. Players decide which piece to move next and all the information needed to make this decision is laid out in front of them – there is no luck involved.

Playing Chess means running through a lot of possible states of the board, a couple of moves in advance, and playing the first move of that variation. Now it’s your opponent turn and the only way you can be “lucky” in Chess is by having your opponent “not see” a move, after which you gain some advantage.

Now let’s say you’re a perfect Chess player. You can calculate 50 moves in advance in a matter of seconds and play the best move. But when paired with a player of the same class – you will never win. The outcome of a perfectly played Chess game is draw.

Take a second and think about that. For all we humans know at the present moment, and for all computers can calculate, there is no way to “force” a win in Chess – only hope your opponent will make a mistake.

And hoping that your opponent will make a mistake is what most people call “luck” which is a concept of chance.

Texas Hold ‘Em

Hold ‘Em is the most popular version of the card game Poker. Players are dealt two cards each and the game begins. Throughout the game, players take turns in placing bets which generally correspond to what they think it’s the “strength” of their hand – a combination of the two cards sitting in their palm and the open cards on the table. When the hand-cards are opened, at the end of the game, the player who has the most improbable combination of cards wins.

Playing a round of Hold ‘Em means calculating the probability that the pair of cards you’re holding away from other players’ view, when combined with the open cards on the table, will make a combination that’s “stronger” than opponents’ combinations (while trying not to get too dizzy from the whisky and cigarettes).

If you watch Hold ‘Em on TV, you’ll notice each hand has a particular probability of winning assigned to it. Often, when two players are left on the table, one of them has “100%” written next to his hand. He’s surely a winner, but why do they continue playing? Why isn’t the game over? It’s obvious, of course, that the winning player lacks the information we have about the other guys’ hand, so according to his perspective – there’s still chance that he’ll lose.

So “chance” in card games is nothing more than we not knowing the other guys’ hand or we not knowing the card at the top of the pile. After the deck is shuffled, most card games become truly deterministic.

What does “chance” mean when cards are played open?

Throwing dice

The last example I want to discuss is “Throwing Dice.” Throwing dice is what most of us consider “really really random”. You take a number of dice, you shuffle them in your hand and throw them on a flat surface.

I made a variation of the game, it’s called “Placing Dice”. You take two dice, pick which side you want to point upward and you carefully place them on a flat surface.

Or I have another one: you take two dice, rotate them as you wish and drop them from a 0.5cm distance on a flat surface. Most of the time, they land as you wanted them to.

“Throwing Dice” is really just a more aggressive version “Placing Dice.” And what we call a “chance” in “Throwing Dice” is really just inability to precisely control our muscles, or the wind, or have in mind the slight bumpiness this flat surface has. Just as in Hold ‘Em, chance is just not knowing enough.

That’s what I find really interesting.