viernes, 12 de febrero de 2016

Test spies with Lua metatables

Dabbling with Lua metatables, I tried to write a minimal testing library that does not impose you any funny 'describe(...)' or 'it(....)' nesting, and one can just organise the tests as he pleases.


I called it spacesuit.lua as it wraps your functions and gives you minimal support to write tests (assertions and spies) in the wild. If you need your tests to be TAP compliant, runnable from any platform, and a well known solution, I can recommend busted, but for me, I tried to keep it minimal so I can put it in my bag and run the files I need from my console, using some silly bash/zsh script using globbing. no need for luarocks, native compilation of lfs or anything.

Apart from providing some sugar for assert_equal (which I'll probably delete in favour of plain assert(foo==42)), it provides:

  • assert_raise(fun): runs the function and asserts an error is thrown during its execution.
  • spy(fun): returns a proxy function (it's a table with __call in its metatble) that logs all the calls (both actual parmeters and results). The usage is quite simple:
  • s = spy(function(x) return x+1 end)
    -- inspect the log
    s.called_with(42) -- true
    s.called_with(42).and_returns_with(43) -- true
    s.called_with(43) -- error
    s.called_with(42).and_returns_with(44) -- error
    --number of times called
    s.called() -- true
    s.called(1) -- error
    s.called(2) -- true
  • make_spy(Module, 'fun_name'): hijacks Module.fun_name so that you can track executions of functions inside modules. It provides a clean() method that releases the hijacking.
  • stub(Module, 'fun_name', fun): hijacks Module.fun_name and substitutes it for 'fun'.
The whole ungolfed code is (without tests) about 100 lines of lua, which is very impresive for a non-batteries included language.


The how is what is interesting. When you make a spy out of a function, spacesuit creates a func table which responds to called_with. called_with  returns a table with and_returns_with key which will do the matching. It's quite a nice usage of lexical scope juggling.

For the hijacking part, I wanted to wrap everything into another table which would have the 'clean' method, and use __call to call the spy table (that would cascade to its __call entry in its metatable, but lua doesn't let you chain __call's. So you have to write the outer one as a function that calls the inner one (and then the __call is run).

jueves, 11 de febrero de 2016

With this trick, Helm-dash gets find-as-you-type for free, developers hate it...

It's been a long time since I had this feature in mind. Where helm-dash would open documentation pages as you typed. 

It is clearly possible to run actions while pressing keys (helm-swoop does it). But when I looked at its code, I saw the author had rewritten and rebound most of the keys to add the 'hooks'. I clearly didn't want to do that.  

So I kept looking for cleaner solutions (helm-dash didn't have to do complex things, just trigger the action at every keypress), and wrote my finding in this issue. hooking to helm-idle, or hooking to 'helm-after-update-hook seemed the sanest options, but none was compelling enough.

Then I learned that you can set a 'persistent-action', that will run when you press c-z and won't quit helm. Ok, that's something. Not exactly what I ment but I can live with it.

FastForward a year , and while I was using helm-dash, I spotted the hints in the modeline.

So after c-h m, I discovered that c-c c-f does exactly what I want, that is running the persistent-action on every keypress.

So yeah, standing on the shoulders of giants, in this case I got my feature without needing to code a single line.

Issue closed!

miércoles, 27 de enero de 2016

Let's talk about multiplicative factors

It seems 2016 came with some buzz on a couple of recurrent topics: 'Unicorns do/do-not exist', 'github rules/sucks' and 'the 10x programmer'.

I'm not sure about the first statement, and I'm by no means qualified to talk about it. But on the 2nd one, because I'm always looking for reasons and ways to improve, and because I like the "worse is better" (tacking this into account) debate. So here are some of them:
It's funny how in the 2nd link, there's this point:

Let’s not adopt this new technology.
Can we achieve the same thing with a technology that the team is already using and familiar with? “The best tool for the job” is a very dangerous phrase.

Which matches a lot with a line I have in my self-description-doc.

martes, 26 de enero de 2016

Pointy org-bullets

As it seems everyone in my internet neighborhood is publishing their org-bullet configs, that's how my bullets in org look like now.

 It's quite intuitive: the more pointed, the more important. And there are no differences in the line height.

Here's a screenshot:

(eval-after-load 'org-bullets
  '(setq org-bullets-bullet-list '("✺" "✹" "✸" "✷" "✶" "✭" "✦" "■" "▲" "●" )))

lunes, 18 de enero de 2016

Difference lists recap

In CTM, around page 145, the authors talk about a list implementation called Difference Lists. At the abstract level, a dlist is just a list. an ordered list, that has constant time for pushing elements on the front, and a way to iterate over its elements, one by one. It's made of Conses, and the last cdr points to nil.

The difference with normal lists is that it provides -- thanks to the way how Oz (and prolog) can unify unbound variables -- a way to append 2 lists in constant time. The same principle, when applied can lead to very efficient implementations of operations like flatten or reverse, and this leads to efficient ways to code other datastructures like Queues.

I could try to explain how they work, and how you can achieve this performance speedups, but It's definately better if I just link to a few links, and then you skim them and realize how smart and mind bending it is to start thinking declaratively. :)

According to Clocksin: "probably one of the most ingeinous programming techniques ever invented yet neglected by mainstream computer science".

domingo, 17 de enero de 2016

Bootstrapped metacompiler using Perl5 and lua

I wrote a Shchorre's metaII implementation myself using perl regexes.

The whole code that is run is just a recursive regexp match against a string (/$bootstrap/ =~ /$program/), which makes it even more mindfucked than usual. It's a simple way to create recursive descent parser just using regexes and perl extended patterns.  The string that tries to match is a representation in meta-II of the very same syntax the string is written on.  Yes.  :-)

I'm taking advantage of the Perl5 extended pattern '(?{})' that runs perl code whenever the regex reaches that point.  The idea is pretty similar to how metaII outputs work themselves even syntax-wise, so I thought it was a nice way to implement it as it's using the same idea that is going to use metaII after being bootstrapped (sorry if this post is difficult to read, but I can't find easy ways to write about without it in clear non-chained-and-recursive-and-self-referent-way). 

To be able to run recursive regexes, we need what MJD calls a proxy parser which is just a delayed 'thunk' that will be evaled just at runtime. We can achieve it in the regex world with (??{}).

If you're not familiar with metacompilers, my advise is to google a bit about them, and find out about them. It's an amazing piece of technology.  Basically you can get a compiler build itself in very few lines of code, and then augment it step by step by modifying the rules it consumes, and creating a slightly more evolved copy of itself, that you can use as a stepping stone to create more advanced compilers.

I added a makefile that shows the process of compiling a compiler using itself and a description of itself.

Here's the repo where there  are more insights in the readme file. Also, check my other posts on metacompilers.

viernes, 15 de enero de 2016

MemoYzing: memoize using Y Combinator

Lately I've had to speed up an openresty-lua application.  As most of the code is just applications of transformations to data, and it's mainly functional, I thought that memoizing would be the easiest way to go.

After generating a flamegraph for the code, I spotted a couple of functions that could be memoized. Problem solved.

While looking for a nice way to write the memoize function, I remembered the shortest memoizing code ever in lua. Also I googled a bit and found kikito's memoize library. So far so good. But they both share a problem. What about recursive functions? They will get catched only on the top level, because the self referencing calls , after memoizing are not self referencing anymore, and they point to the old function.

Perl memoize module overwrites the symbol table to alias the functions. In ruby 2.0 you can memoize a recursive function using Module#prepend. With the Y combinator

Here's this article from Matt Might about how YCombinator makes it possible to turn a recursive function into a memoized recursive function caching the intermediate results, using the indirect self-reference that it provides.

EDIT: I just published the button and then thought "what if I wanna convert a doubly  recursive function (fib) into a iterative one (tail call) by using accumulators? I can obviously memoize according to the two args, but it gets pretty useless, as the results can be hardly reused. I found this series of articles "from recursion to iteration" that provide some tricks. Haven't fully understood it, but I'm on it.