The color of music: why not discover python's ecosystem the right way?

It all begun, a nice sunny day of summer on #python-fr

Well, not that sunny, but a story always begin on a cheerful note. A numerous minority of beginners that comes on #python-fr (usually from PHP) often make a first project to discover python which belongs to the following categories:
  • recoding a network client/server without using twisted or tornado;
  • recoding an HTML parser without using an html parser (yes with regexps). 
When we usually tell them it is wrong, we are in the best case ignored, in some exceptional cases flamed for being castrating their creativity.

How do we tell them that reinventing the square wheel is not standing on the giants' shoulders?

Well, this is so disheartening that I asked myself, what would I do as a first project? And since I sux at deciphering music, I told myself: How hard is it to make a sonogram?

If you know a little music, you know that a note is associated with a frequency (the primary). Every instruments when you play a note have a primary vibration which is strong and a stationary vibration and additional stationary vibrations of k * primary  frequency but of lower amplitude called harmonics. So I want to see the music in a colourful way to be able to tell which notes are played by finding the lowest vibration with the biggest amplitude. No rocket science, occidental tempered modes are a gift from the Greek before they were broke. (We never paid them for this gift, but who cares they don't have IP lawyers).

How hard is it to make a spectrogram in python?

Let me google it for you:
spectrogram music python, choose : stackoverflow link,
I chose audiolab instead of waves because I was reading the author's article a few day agos on planet python.

So you are redirected on which gives you the bases for a first code and some explanations.

Fast Fourier Transform is an outdated (since this year after years of good services) way of transforming a time dependent serie in a frequency serie. But the Fourier transform is still a must.

The truth is you have to make a spectre of frequency, which is not a Fourier fransform, but closely related (I'll skip the theory of temperate distributions). As with a radar you convolve the signal with itself on a time window to have a power representation (autocorrelation). We have a nice trick with Fourier avoiding very costly and boring integrals of overlap over time. As I have not opened a book of signal processing for 20 years, I do strongly advise you if interested to double check what I am saying. I am pretty much a school failure so I must have made a mistake somewhere.

I did not liked the old code on macdev because I had more than 20 lines of codes to write. And I told myself, «it would be very amazing there is not a ready made class for spectrograms in python». And I reread carefully the Stackoverflow answer (googgling is fine, reading is a must). And I discovered that spectrograms are directly included in matplotlib

Plus my first result was crappy so I googled : improve resolution spectrogram python. And here I had the base to do a fine code. Because parameters were explained.

I did not even had to code or scratch my head to have a functioning code. Did I learnt something? Yes: always check your problem has not a solution before coding head first. And code less.

The fun in coding is about adding your salt

Well: spectrograms are fine but for decoding music reading raw frequencies sux. So here I came with my improvement that does not interest physicists: changing the numerical scales by readable notes.

Step 1: copy paste on internet an HTML table of note names vs frequency in a file.
Step 2: adding it to the graph.

Here is my code:

And here is the result:
Köln concert PartII of Keith Jareith from seconds 10 to 20.

It is a piano instrumental, you clearly see the harmonics, the notes (No I joke low frequency is a mess to read), and the tempo. My note scales are not the same than Keith's because I loaded a scale based on la=440Hz where it must be la=442Hz. You guess the arpeggio at offset = 1.8second.

Well, we python devs, are sometimes bashed because what we do is «too easy». Well, I find it pathetic someone who wets his pants pissing thousands of lines of code when you can have the same result with 20 lines.

AC/DC back in black from 5 to 10 seconds
Multi instrumental song makes it a pain to read the notes. You may guess however an E3 bass line with a tempo of 60bpm begining at offset = 6 seconds.

Why didn't I make a logarithmic scale? Because spectrograms are not compatible with log scales in matplotlib. That's the end of it.

So what is the conclusion?

If you begin in python, rather than re walking already more than known paths for which you'll invariably code a simple neat and wrong solution just explore what is the bleeding edge and do some fun stuffs, you'll discover we need new ideas and that you can help.

For instance in this case:
  • you could make a matplolib application where you can zoom part of the  whole song in another window;
  • you could try to code a colormap in matplotlib that can support logarithmic scale;
  • you could try to had some filtering to erase the harmonics;
  • you could had a bpm frequency detector and play with bpm to higher the resolution and show the beat in xticks to higher readability ;
  • you could play with the window function and the color scale to higher the resolution;
  • you could make a 3D graphs with frequency bins ...

There is always room for improvements as long as you target the right problems.

Well, computer industry is an amazing field to work in because there are always new problems to solve. Beginning in computer should not be about mimicking wrongly old boring problems (parsing HTML with regexps, network daemons, parallel computing) but about finding your place in the borders of an imaginary land. And remember if as I you begin in python: Always stand on the giants' shoulders, you'll see further than if you stay a dwarf in a crowd of giants.

Lost in cache optimization

Premature (and Micro) optimisation is the root of all evil

We all know this, don't we? And even though I know it, I do still fall in the trap.

Let me tell you my story: it all began with profiling a basic web log parser  I did fairly fast (core of the project was done in 2 days (demo here)). But before releasing it, bmsipelon wanted to check if the implementation was efficient enough so he made a benchmark of the algorithms. Thanks to him I corrected a bug in my library.

You may notice we've had a basic memoizer since the begining?

I was quite raging that his code was running faster than mine, so ... I decided to begin optimizations... And all hell broke loose.

Context : I was parsing a 191K lines apache log in 24 seconds with bmispelon implementation and in 30 seconds with my implementation. And I wanted to beat him badly.  That's called coopetition (competing in cooperation).


After running runsnake I had this gorgeous report :

Well, I also discovered map reduce is more costly and not that memory efficient compared to a simple loop Simple is better than complex.

Also, Hankyu is not the most efficient (it is beaten by default dict). The fractal look of __iadd__ and isintance is the cost of recursion. Remember: Flat is better than nested.

However, to change the shape of his results he needs to change a lot of code, I only need to change one argument. Cost vs advantages.

I thought that by getting rid of the fat (in httpagent parser, and date formating) I would win my 6 seconds.

As a result, I tried to improve the cache, by measuring its impact. Then I measured and here was the result for the cached date_formater:

    "date_format": {
        "len": 143142,
        "hit": {
            "hit": 49972, 
            "time": 0.08554697036743164
        "miss": {
            "hit": 143142, 
            "time": 4.912769079208374

It was a pleasure, and a drawback: my strategy seemed efficient in terms of performance, but explosive in terms of memory. So I decided to give a try to py3 functools.lru_cache and beaker.

functools.lru_cache and beaker were taking 30 seconds instead of 26 seconds! I thought to myself: these guys must over engineer. So I made my own crude fixed size LookupTable. As usual, Baptiste bested my circular buffer ring like implementation with its implementation. I had carefully looked at all big O notation for the complexity and tried to choose the containers according to my needs. So I was raging.

I also thought: Hey genius, date in logs are monotonically growing but sometimes constant, then why handle the burden of a dict that will blow up your memory, when storing a simple pair of values works? So I implemented, and «measured» with my tool the impact of a monotonic cache:

    "date_format": {
        "hit": {
            "hit": 49972, 
            "time": 0.0680077075958252
        "miss": {
            "hit": 143142, 
            "time": 4.508622646331787
Hurray! I won an award of the best idea of the century (probably existing in some old FORTRAN code) and rediscovered that caching strategies should take the shape of the data in consideration. Not only was my algorithm more efficient, but also sparser in terms of memory. So it was time to prepare some nice data to share my discovery.

So I decided to add more caching backends and test them all to look serious. I added repoze.lru_cache.

Here were my first data :

  • dict is a basic memoizer (the canonical example given everywhere),
  • repoze is repoze.lru_cache with maxsize=10000,
  • fixed is memoizer with Baptiste's custom fixed size lookup table  maxsize=10000
  • beaker is beaker.cache in memory and expire time = 600


Repoze.lru_cache is 27.5 seconds where functools lru_cache was 30 seconds, and faster than the crude fixed size lookup table?

So I looked the source code. Even though it was more complex it was thread safe and faster. I did not imagine a brain dead close to the metal implementation would be beaten by such a complex code (in terms of single lines of code and tests (they even recoded/optimized modulo!)).

At least, I still had the pride to think my monotonic messy but efficient cache  would be quite a news. But, repoze.lru_cache had seeded some doubt in my brain. So I decided to double check my results. On a tinge of wit I removed my monotonic cache in contradiction with my measurements. So I tested both repoze.lru_cache in replacement of my monotonic cache and the basic memoizer without any cache on the date formater ... just in case.

  • dict + nc is the dumb memoizer with no cache on date formating,
  • repoze wo mono is repoze.lru_cache caching also the date time formater

What happened? 

In my head, I had already anticipated that on the opposite of web caching, my function could be insufficiently costly to use a complex cache. So I made a «close to the metal one value cache». But I relied too much on my own measurements, and forgot to make the test that matters: real time analysis with the dumb time from bash on real data...

Yes, I won : my monotonic cache is indeed faster than repoze.lru_cache which is my archnemesis in this test, but caching this very fast function is dumb useless.

How could I have avoided all this loss of time?

By remembering that Premature optimization is the root of all evil. Let me show you the big picture
Had I begun optimization after a no cache version would I have discovered I was doing breadcrumbs optimization. 4 seconds faster than beaker is impressive (more than 15%).
Winning 4 seconds in regards to 80 seconds (5%) at the cost of :
  • development time;
  • non thread safe implementation;
  • my code is a battlefield;
  • no unit tests;
  • headaches;
  • close failure
is pathetic. I will probably finalize my API without my cache implementations.

Morals of the story


My measurement missed the overhead of the decorator's call time. A decorator adds a call to a function call, and there is no way to measure it, I over focused on improving cache but I lacked the point that no cache were needed. Never dumbly trust your measures. 

I also (re)learnt my lessons: measures can trigger artefacts, the real data world is often more complex and diverse than the one tested in a beaker. There are some one best way of caching however caching is still data dependant: there is no «one size fits all» caching. If you want to use a cache, it is a good practice to measure objectively that your caching strategy is the good one in situ. There are however some pretty safe strategies.

You should always test your new ideas against real data. Even if you carefully chose your algorithms you might have overlooked one bias (such as overlooking the pathological cases for key deletion in a dict). And what your unit tests may not reveal may appear in production which is the worst place to discover a design bug. Theory is great, so are experiments. They should not be seen as opposed, but rather as complementary.

Caching is like cryptography: you'd best use other's framework

Try to follow the general API, so you can change your backend. There is no such thing as an ultimate cache since caching is really data shape and context dependant.

Never lose sight of the big picture

Had I watched carefully my profiler would I have had noticed what I rediscovered: I was losing time with micro optimization.

Cache benchmarking results

In my test caches are never over filled, because I begin with empty cache and I allocate 10000 entries per cache as a default. yahi.speedshoot taking more than one file as an input, users might have a slight decrease in performance for big series of file with fixed size cache (cost of deleting keys in MutableMappings). However since caching is context dependant (do you parse files from a same sites, or different sites) thus these results may vary with the data you really parse. I cannot guess what is the best strategy, however any cache decorator should be made in a way that you can clean the caches. repoze.lru_cache misses this feature (and I have it \o/).
My monotonic cache is a good idea (ego boosting), but I was wrong on the use case. And as long as I have no case in which it works, it is a dumb idea.

Cache APIs are standard enough (cache provider handling the implementations for the real cache, providing cache invalidation and providing a cache decorator) that you should always make an adapter so that you can change your caching backend.

Beaker.cache is impressive in terms of functionality and could make my code thread safe and memory safe. Complexity is improved and it has a cost, but also some returns on investment.

Memoizer strategy is the fatest cache, and also the simpler to code. It is a good arrow to keep in your quiver in most circumstances, but remember your cache will grow without control.

Read before coding

I learnt a lot about caching with wikipedia, stackoverflow and pycon slides that were all over internet. Before coding, it is always a good idea to search internet, not for code but studies. Standing on the giant's shoulders is not lame, it is about focusing on the exciting new ideas that were not coded. Sometimes, it is fun to try to test the established wisdom by implementing your variant. You may win, you might lose, but you will have fun. Maybe I did not find any reference to a monotonic cache because it is lame, maybe I don't have the good keywords, maybe it is a good idea, I'll never know but  I took the chance. You'll never win if you never fight.

Algorithms are evolving, nothing grants that what you learnt is still up to date (even the iFFT algorithm is being renewed).

One pride

I did not ridiculed myself!

My teachers used to say if your results are astounding you should double check them since there is a 99% probability there is a mistake somewhere.

And they said: even if you fail, remember errors are fruitful since one never learns from its success but from its mistakes. Sharing your mistakes with the community is less rewarding but is as important as sharing your success.

This was my mistake: Premature optimization is the root of all evil.

PS here is my code for plotting:

Small tips to improve your packages on pypi (for beginners)

I am a big fan of plots. Not for their beauty, but for their dense informational properties. And since I capture download time series on pypi downloads on miscellaneous packages here are my preliminary findings (that needs validations, since my samples are not relevant in terms of size):

  1. After the first release you have 8 days to find your public;
  2. make packages with practical use;
  3. while new releases will reboost your exposure, if you have found your adoptants it will not make miracles (don't spam pypi, it is useless);
  4. README might be the most relevant criteria for early adoption; 
  5. put some actual code use in your README that is revelant.

Here are some funny stuffs I have no way (and not enough knowledge) to check and I dream to have an answer for: 
  1. the impact of the quality of the setup (have you filled in properly your setup, your trove classifiers);
  2. quality measure for documentation and impact on the downloads (I like pathlib's doc better than mine, because it sticks to the facts);
  3. snowball effect due to the reputation of the packager;
  4. is there an optimal templates for doc? (can we correlate a doc structure to a better adoption?)
  5. the impact of documentation presence (either pypi or rtd) on package adoption (this one seems obvious to me);
  6. the  impact of alpha/beta/stable tagging on adoption;
  7. the impact of a source code link in the README, and of a valid home page;
  8. which kind of home page increases adoption? 
  9. what is the optimal number of functionalities (number of class/methods) for a package (is sparse better than dense, simple better than complex) ? 
  10. which metrics are the most significant?

The purpose of the exercise is not to tell how smart I am, but to daydream of some feedbacks  from the QA in the packaging guide or in distribute (like an enhanced python check). I do lack skills to do all the aforementioned tests so I mainly send a message in a bottle expecting it to drift one day on the shore of the pypi/distribute team :) 

PS : I miss the make test from Perl and I can't figure a way to make my unittest mandatory prior to the installation of my package, and to have an automated feedback when pip install fails to improve my packaging. As a result if pypi would state the percentage of failed install over successful install I would be delighted.

Fixed window of ~1 week for finding your public

If we consider all the new packages I monitored (gof, archery, weirddict) you'll notice a charging law in the form of DLmax(1-e(-time/4d)) + adoption_rate*time.

ex :

Possible Explanation: 

RSS feeds will propagate, and your package will be visible for this period on various places and on sites such as

How to validate

For any new package : the ratio of download  after 4 days and 8 days should be the same. And the ratio after 16 days / 8 days should be far less than 4 days / 8 days. Most non adopted packages should have a flat download curve.


What if packages older than x years without adoptants were cleaned of pypi?

A package that meet its public will have an almost linear growth


Well on this one it is just observation :)

How to validate

For any download curve that don't follow the DLmax(1-e(-t/4d)) do the diff after 16 days for period without releases and then check the diff is constant +-10%.

A new release will give you a new chance in adoption

 A new release gives you a second chance but is is needless to spam pypi with new releases since your rate of adoption won't normally change.


Your new release will encourage migration anyway on one hand, but on the other hand if you have met your demand, then your «adoption market» is already saturated.


Do the linear diff of the curves 10 days before and after a release on a package and check that the growth ratio is the same.

Practicality beats purity

Given two packages : VectorDict (I recommend archery instead) for dict with addition and pypi-stat (used for these graphs) the practical package will have more chance of adoption than the more abstract one.


As you can see, VectorDict adoption is mostly due to pypi-stat adoption (200dl/4weeks).


Your fellow coder search pypi for actual solutions to their problems not for a tool in search for a solution. Coders better understand practical use than conceptual ones.


If you have a configuration with one «abstract package» and one or several «practical package» depending on it subtract the download curve of the practical package from the «abstract» one. I bet growing curve of abstract package is less that practical one. 

Put Some practical code in your README

The new curve for archery has a better growth. The difference is I put some use code. My intuition is putting actual code in the README helps


Parsing README and measuring downloads after 16 days for the 1st release in two groups : the one with code in it, and the ones without. There should be a bimodal distribution if I am right.

Having fun and making fun with game of life.

Summary of the previous episode

In the previous episode we made a simple game of life called GoF because I am dyslexic and Game Of Life became Game Of liFe. The purpose of the exercise was to demonstrate that an abstraction ought not to be complicated but ought to dissociate the intuitive way to use the code and its implementation. Now, our new mission, is even funnier: it is to show how a simple toy program can teach us serious things.

Introducing the game of life console 

I have made a small tutorial here :

My game of life implementation is deliberately faulty in its implementation, is a little bit of a troll, but it is has an amazing power to illustrate some key concepts of developing (I prefer factorizing):
  • it is an introduction to non linear algebra a field in which computer analysis is a must;
  • it is a massively parallel model hence a way of thinking problems in order to defeat concurrency problems;
  • it is a very simple way to begin manipulating python;
  • there are some smart tricks based on abstractions; 
  • it is an introduction to discrete cellular automata / multi agent simulations.

The troll in the code

I am not an Object Oriented developer. I am an old old developer coming from the old time, we use to say : «show me your code, and I shall be mystified, show me your data, and I know how your code really works». Since OOP and encapsulation has been massively adopted, data and code are mixed up in the same files. As a result, it has become impossible to tell code from data.

My code is old fashioned : data on one side (the matrix), and functions on the other side (evolve, bleach, dirty). But, is not.

If you type : = evolve
matrix.reset = bleach
matrix.random_fill = dirty


Then, now all the tutorial can be rewritten in a plain OOP fashion. So, the troll in my code is about stating that coding is not about using a paradigm, it is about making code that works, and that OOP and imperative programming can be equivalent.

Since I miss the separation of data and code, I do advocate separating data and behaviour in distinct files and that is why I love python dynamic typing but you could also use inheritance to achieve the same result. One illustration of this principle is archery that use traits (mixins) to give behaviours to inert objects (Mutable Mappings in this case).

I deliberately left a mistake in my code to illustrate my point: my Game Of Life's implementation cannot be used for a generic 2D cellular automaton networks because I left a method for counting living neighbors that is specific to Conway's game of life. I intend to use it make a point later if I have the time to develop on cellular automata, and on the proper separation of methods in an object.

Readying the path for some analysis

Imagine you want to make an histogram of the number of cells that are ALIVE after 0, 50, 100, 200 iterations. For the sake of fun, I use gof.weird_array.SparseArray. Hence you just have to count the number of items in the set to count the living cells this way:

import matplotlib.pyplot as plt
from gof.matrix import matrix 
from archery.bow import Daikyu
from archery.barrack import bowyer
from gof.gof import dirty, bleach, evolve
from gof.weird_array import SparseArray
from json import dump
result= Daikyu({})

for _try in range(100):
    ### {0}^{0} is more friendly thant the boring set()
    grid = matrix(20, 16, SparseArray({0}^{0}))
    dirty(grid, 10)
    result+= bowyer(Daikyu, {0: {len(grid.matrix._set): 1 }})
    evolve(grid, 50, 'unseeable')
    result+= bowyer(Daikyu, {50: {len(grid.matrix._set): 1 }})
    evolve(grid, 50, 'unseeable')
    result+= bowyer(Daikyu, {100: {len(grid.matrix._set): 1 }})
    evolve(grid, 100, 'unseeable')
    result+= bowyer(Daikyu, {200: {len(grid.matrix._set): 1 }}) 

fig = plt.figure()
for i, label in enumerate([0, 50, 100, 200]):    
    ax = fig.add_subplot( len(result), 1, i+1)
    if not i:
        ax.set_title("Number of living cells for 100 random configurations")
    p = None
    for k,v in sorted(result[label].iteritems()):
        x+= [k]
        y+= [v]
    ax.plot(x, y, label="%d iterations" % label)


And Tada o/

What is so special about these plots ?
  1. there is no nice distribution of the number of the accessible configurations after initial  time  (gaussian or any other distributions);
  2. the configurations that were pretty homogeneous in terms of 0/1 are now more spread (the entropy of each initial patterns decreases, but the result are less homogeneous in terms of 0/1 ratio than the initial patterns)  ;
  3. the number of configurations increases, and then decreases : we have a transition! 
At iteration 200, patterns should be converging to their  attraction basin. With a network of simple systems interacting with each other, you have a complex system. These rules being non linear, they cannot be addressed with linear tools (matrices, Fourier...). It is thus quite hard to predict their behaviors.

If you have the audacity to speak French ;) you can read this :

Now you have a lot of challenge to solve :
  • is there a domain in which the system is chaotic (given a distance of 1 for two distinct patterns, how does final distance evolve?);
  • Are there more chaotic rules than Conway's?
  • If we change the actual neighborhood for a random neighborhood how does the system change? 
  • how many stable attractors exists, what are they size? 
  • how many precursors exists for a basin, how these are distributed?
  • if we consider the grid as a vector of 1/0, then it is a number. Can we construct a chaotic enough cellular automata that would make a good cryptographic hashing function (hint : rule30) ?

What about GPU?

Another cellular automata that is fun is the lattice gas automaton. And it is suited for GPU : Data-Parallelism and GPUs for Lattice Gas Fluid Simulations Since the same causes produces the same effects, most of the cellular automata networks will be easily implemented on GPU.


And what about Finance? 

I have found G. Weisbuch works inspiring :  hits and flops dynamics by G. Weisbuch. Financial phenomenon are pretty much based on a lot of agent with their own rationalities, some global beliefs and a neighbourhood. It seems very tempting to use a cellular automata to model financial phenomenon (which seems non linear).

Plus cellular automata are pretty easy to code, easy to parallelize with CUDA. So maybe we can do fun things. At least I tried with a very ugly first code in python of a multi agent simulation with a fanciful utility :

And now?

Well, I hope you enjoyed, that's all.

PS Special thanks  to Alejandro Weinstein, Bmispelon for the corrections...

Correspondences : coding is poetry in disguise

Nature is a temple in which living pillars
Sometimes give voice to confused words;
Man passes there through forests of symbols
Which look at him with understanding eyes.

Like prolonged echoes mingling in the distance
In a deep and tenebrous unity,
Vast as the dark of night and as the light of day,
Perfumes, sounds, and colors correspond.

There are perfumes as cool as the flesh of children,
Sweet as oboes, green as meadows
— And others are corrupt, and rich, triumphant,

With power to expand into infinity,
Like amber and incense, musk, benzoin,
That sing the ecstasy of the soul and senses.

— William Aggeler, The Flowers of Evil (Fresno, CA: Academy Library Guild, 1954)

Coding is poetry

Nature is a temple in which living pillars
Sometimes give voice to confused words;
Man passes there through forests of symbols
Which look at him with understanding eyes.

When we code, we re-use concepts and codes from other developers, their symbols are indeed echoing in our own code, and sometimes, it gives voice to new words: the «paradigm» emerging from a new practice. The man passes through this forest of symbols bearing a sense, but the poem implies the man does not always hear them. It is given to some.

Like prolonged echoes mingling in the distance
In a deep and tenebrous unity,
Vast as the dark of night and as the light of day,
Perfumes, sounds, and colors correspond.

We rely on prolonged fainted echoes of old time, like Turing Machines, functional programing, document oriented database (NoSql) ... they seem noisy because of the collisions of the echoes, they also form a dark maelstrom where maths, geometry, electronics, business are mixing together. And, some can feel the consistency in this.

There are perfumes as cool as the flesh of children,
Sweet as oboes, green as meadows
— And others are corrupt, and rich, triumphant,
There are ideas that enlighten us by their striking simplicity, others that are rotten and smelling like anti-design patterns, and finally some that smells of genius mixed up with the smell of a full blow up.

With power to expand into infinity,
Like amber and incense, musk, benzoin,
That sing the ecstasy of the soul and senses.

The beauty of programming, lies in the fact, that coder like poets live in a dark world of frightening symbols, yet intoxicating words. By the sheer power of our imagination, we make sense out of this wor(l)ds*.

(*I do skip the infuriating part where we lack inspiration and feel like useless frauds.)
And this is the heart of our code, since code aims at being useful to human beings not computers.
Edit : that's must be bias coming from my past as a Perl user.
Here is a code in Perl, that compiles (and does nothing, but is human readable. 

Black Perl

BEFOREHAND: close door, each window & exit; wait until time.
    open spellbook, study, read (scan, select, tell us);
write it, print the hex while each watches,
    reverse its length, write again;
    kill spiders, pop them, chop, split, kill them.
        unlink arms, shift, wait & listen (listening, wait),
sort the flock (then, warn the "goats" & kill the "sheep");
    kill them, dump qualms, shift moralities,
    values aside, each one;
        die sheep! die to reverse the system
        you accept (reject, respect);
next step,
    kill the next sacrifice, each sacrifice,
    wait, redo ritual until "all the spirits are pleased";
    do it ("as they say").
do it(*everyone***must***participate***in***forbidden**s*e*x*).
return last victim; package body;
    exit crypt (time, times & "half a time") & close it,
    select (quickly) & warn your next victim;
AFTERWORDS: tell nobody.
    wait, wait until time;
    wait until next year, next decade;
        sleep, sleep, die yourself,
        die at last
# Larry Wall