source: project/gazette/src/issues/ @ 25547

Last change on this file since 25547 was 25547, checked in by Alaric Snell-Pym, 9 years ago

gazette: Split the omelette (insert pun about breaking eggs) between issues 20 and 21, at a suitable point near half-way, with a bit of link text.

File size: 22.7 KB
1((title . "Issue 20")
2 (authors "Alaric Snell-Pym")
3 (date . 1300960048))
5== 0. Introduction
7Welcome to the 20th issue of the Chicken Gazette. While the gazette
8was on hiatus the chicken community was definitely not. We are
9expecting a new release and lots of bugs have been addressed in the
12Thanks for the recipe go to Alaric. Thanks to the Chicken Team for
13compiling this issue.
17== 1. Hatching Farm
19The following new extensions were added:
21* [[egg:canvas-draw|canvas-draw]]: Bindings to the CanvasDraw graphics library ([[user:thomas-chust|Thomas Chust]])
22* [[egg:bindings|bindings]]: light-weight alternative to the matchable egg together with some enhancements ([[user:felix-winkelmann|Felix Winkelmann]])
23* [[egg:tuples|tuples]]: a tuple datatype implementation ([[user:felix-winkelmann|Felix Winkelmann]])
24* [[egg:svn-egg-author|svn-egg-author]]: makes it easier for people still using svn to tag/release eggs ([[user:peter-bex|Peter Bex]])
25* [[egg:memcached|memcached]]: memcached client interface ([[user:ivan-raikov|Ivan Raikov]])
26* [[egg:tree-rewrite|tree-rewrite]]: initial import of tree-rewrite, an adaptation of Oleg Kiselyov's term rewriting system PostL ([[user:ivan-raikov|Ivan Raikov]])
27* [[egg:srfi-71|srfi-71]] '''1.0''': import some of srfi-71 (evhan)
29The following new versions have been released:
31* [[egg:hen|hen]] '''0.5''': Create tag 0.5 (
32* [[egg:sequences|sequences]] '''0.3''': bugfixes; replicate ([[user:felix-winkelmann|Felix Winkelmann]])
33* [[egg:fastcgi|fastcgi]] '''1.1.1''': pointer->c-pointer fix; output strings can contain NULs (thanks to Peter Danenberg)
34* [[egg:contracts|contracts]] '''0.4''': some enhancements ([[user:felix-winkelmann|Felix Winkelmann]])
35* [[egg:sequences|sequences]] '''0.4''': performance tuning, some renaming ([[user:felix-winkelmann|Felix Winkelmann]])
36* [[egg:message-digest|message-digest]] '''2.3.5''': reverted def alloc of ctx & no str use in u8vector restyp creation. ([[user:kon-lovett|Kon Lovett]])
37* [[egg:md5|md5]] '''2.5.1''': Rel 2.5.1 w/ minor bug fix. ([[user:kon-lovett|Kon Lovett]])
38* [[egg:sha1|sha1]] '''2.3.1''': Fix correct context field clear (was not walking over memory since sufficient padding in struct, still it was wrong.) Rmvd ctx clear since unneeded. ([[user:kon-lovett|Kon Lovett]])
39* [[egg:spock|spock]] '''0.03''': renamed some API procedures; bugfix in driver (thanks to Supermario) ([[user:felix-winkelmann|Felix Winkelmann]])
40* [[egg:amb|amb]] '''2.1.4''': Wrong dep verno for condition-utils & check-errors in .meta. Missing import for srfi-1 member use in amb-extras [reported by Markus Klotzbuecher]. ([[user:kon-lovett|Kon Lovett]])
41* [[egg:mojo|mojo]] '''0.0.1''': first release ([[user:moritz-heidkamp|Moritz Heidkamp]])
42* [[egg:sdl|sdl]] '''0.5.3''': new release ([[user:christian-kellermann|Christian Kellermann]])
43* [[egg:tuples|tuples]] '''0.2''': tuples 0.2 ([[user:felix-winkelmann|Felix Winkelmann]])
44* [[egg:progress-indicators|progress-indicators]] '''0.3''': added missing licensing information to meta file (thanks to mario) ([[user:felix-winkelmann|Felix Winkelmann]])
45* [[egg:spiffy-request-vars|spiffy-request-vars]] '''0.13''': test fixes ([[user:mario-domenech-goulart|Mario Domenech Goulart]])
46* [[egg:html-tags|html-tags]] '''0.10''': added generate-sxml? parameter support ([[user:mario-domenech-goulart|Mario Domenech Goulart]])
47* [[egg:blas|blas]] '''3.0''': Chicken 4 cleanup ([[user:ivan-raikov|Ivan Raikov]])
48* [[egg:atlas-lapack|atlas-lapack]] '''2.0''': Chicken 4 cleanup ([[user:ivan-raikov|Ivan Raikov]])
49* [[egg:probdist|probdist]] '''1.7''': updated use of blas and atlas-lapack ([[user:ivan-raikov|Ivan Raikov]])
50* [[egg:hyde|hyde]] '''0.15''': simpler atom feed generation ([[user:moritz-heidkamp|Moritz Heidkamp]])
51* [[egg:signal-diagram|signal-diagram]] '''1.1''': added reduce combinator ([[user:ivan-raikov|Ivan Raikov]])
52* [[egg:awful-sql-de-lite|awful-sql-de-lite]] '''0.4''': See for the latest changes. ([[user:mario-domenech-goulart|Mario Domenech Goulart]])
53* [[egg:awful-postgresql|awful-postgresql]] '''0.4''': See for the latest changes. ([[user:mario-domenech-goulart|Mario Domenech Goulart]])
54* [[egg:awful-sqlite3|awful-sqlite3]] '''0.4''': See for the latest changes. ([[user:mario-domenech-goulart|Mario Domenech Goulart]])
55* [[egg:awful|awful]] '''0.31''': See for the latest awful changes. ([[user:mario-domenech-goulart|Mario Domenech Goulart]])
56* [[egg:spock|spock]] '''0.04''': removed explicit version number from setup script (reported to mario)
57* [[egg:spock|spock]] '''0.05''': compiled code runs somewhat on IE; slightly more verbose setup-script ([[user:felix-winkelmann|Felix Winkelmann]])
58* [[egg:memcached|memcached]] '''1.0''': first release ([[user:ivan-raikov|Ivan Raikov]])
59* [[egg:locale|locale]] '''0.6.11''': check-locale-component for 'name had bad value ('name itself rather than value variable). with-tzset was leaving TZ set when no original TZ value. Proc for envvar LANGUAGE (gnu) was using code that deref'ed nonexisting 'language locale component; part of code to substitute primary locale region for possible nonexisting 'country in LANGUAGE locale, which can be subset - just language. (This caused the Error: (string-parse-start+end) bad argument type - not a string: #f from string-upcase.) ([[user:kon-lovett|Kon Lovett]])
60* [[egg:locale|locale]] '''0.6.12''': Use 'current locale category for primary locale, rather than 'messages. locale-timezone has proc for offset & name. ([[user:kon-lovett|Kon Lovett]])
61* [[egg:matrix-utils|matrix-utils]] '''1.12''': updated use of blas ([[user:ivan-raikov|Ivan Raikov]])
62* [[egg:iexpr|iexpr]] '''1.2''': fixed unit tests ([[user:ivan-raikov|Ivan Raikov]])
63* [[egg:mpi|mpi]] '''1.8''': ported to Chicken 4 ([[user:ivan-raikov|Ivan Raikov]])
64* [[egg:bloom-filter|bloom-filter]] '''1.1.4''': Use of round -> ceiling (can't lose a bit). Added different way to calc M & K. Added variant signature for make-bloom-filter to take N & P. ([[user:kon-lovett|Kon Lovett]])
65* [[egg:ripemd|ripemd]] '''1.0.2''': Added ident to digest prim. ([[user:kon-lovett|Kon Lovett]])
66* [[egg:setup-helper|setup-helper]] '''1.3.1''': Fix for trashing the .o when static+shared module setup. "static module" added. ([[user:kon-lovett|Kon Lovett]])
67* [[egg:slime|slime]] '''1.1''': add swank:documentation-symbol (from Jean-Christophe Petkovich) and preliminary inspector implementation ([[user:christian-kellermann|Christian Kellermann]])
68* [[egg:format|format]] '''3.1.5''': first release ([[user:felix-winkelmann|Felix Winkelmann]])
69* [[egg:neuromorpho|neuromorpho]] '''1.12''': small fixes ([[user:ivan-raikov|Ivan Raikov]])
70* [[egg:yelp|yelp]] '''1.0.2''': add note to tests about Yelp API key (ddp)
71* [[egg:format-compiler-base|format-compiler-base]] '''17017.1''': Replaces "use" of "extras" unit with "import", as the current implementation modified the imported binding to "format" and thus overwrote the toplevel binding. ([[user:felix-winkelmann|Felix Winkelmann]])
72* [[egg:embedded-test|embedded-test]] '''17018.1''': fixed long open bug and tagged 17018.1 ([[user:felix-winkelmann|Felix Winkelmann]])
73* [[egg:ssax|ssax]] '''5.0.4''': added export for ssax:warn and tagged 5.0.4 ([[user:felix-winkelmann|Felix Winkelmann]])
74* [[egg:rpc|rpc]] '''1.1.2''': removed use of project procedure ([[user:felix-winkelmann|Felix Winkelmann]])
75* [[egg:flsim|flsim]] '''1.4''': fixes related to Octave code generation ([[user:ivan-raikov|Ivan Raikov]])
76* [[egg:opengl|opengl]] '''1.19''': opengl 1.19: properly link -lGLU (thanks to Moritz Heidkamp) ([[user:felix-winkelmann|Felix Winkelmann]])
77* [[egg:iset|iset]] '''1.8''': fix typo in optimization option ([[user:felix-winkelmann|Felix Winkelmann]])
78* [[egg:hen|hen]] '''0.6''': various fixes and additions (Joseph Gay)
80== 2. Chicken Talk
82Chicken 4.7 is about to be released.  The development team is
83performing some final tests to check if some critical bug shows up
84before the release. If you want to help testing the code which is
85going to be the next Chicken version, get the
86[[|latest development snapshot]]
87and give it a try.
89A Chicken-based commercial application has been added to the
90[[|Software]] wiki page.  According to
91the description, [[|AuScio]] ''is simple
92cross-platform metal price monitor combining the
93[[egg:qt-light|qt-light]], tcp and srfi-18 multi-threading eggs. The
94application is deployed as a native executable with Chicken's
97On the hobbyist side
99a scheme interpreter written in Chicken by
100[[|jacktrades]] has been found on the
103Evan Hanson reported a Chicken sighting in the
104[[|Computer Music Journal]]'s DVD.
106Thanks go also to John Cowan who brought the
107[[|Chicken Dance License]] as
108a possible new license to our attention :)
110Matt Welland announced a new version of chicken-iup
111[[|here]]. Also
112note that the download link has changed since the last Gazette.
114YC started a discussion about a
116RDBMS Interface]], where lots of people envisioned an easy to use glue
117to access RDBMS. The participants argued over the use of URL encoded
118queries vs. other more lispy forms. Thomas Chust developed
119[[|a prototype]] and is looking
120for feedback. Thanks!
122John Magolske shows us a nice trick to
124csi within Vim to evaluate visually selected text]]. He also ran into
125issues when installing chicken eggs in a nonstandard location w/o hard
126coding in these paths during compilation. Thanks to the helpful people
127on chicken-users
129he could solve his issue]].
131Matt Welland asks for a way to produce a notification sound in a cross
132platform way
134this mail]] but until now we don't have a good answer for this
135yet. Maybe you can help? Matt is also still waiting for an answer to a
136problem with
138under windows]].
140Felix announced the release of the hopefully latest development
141snapshot before the next major release. Please test
143as hard as you can.
145Chris Bolton asked about how to print colored messages to a terminal
146and learned about [[|the fmt egg]] and
147[[|ansi escape
150John J Foerch asked for a spiffy feature: remote-address should also
151take the X-Forwarded-For header into account when generating an
152address. Peter Bex kindly implemented it.
154Alex Shinn announced the
156draft]] which we all waited for. Thanks to the scheme-report group!
158Steve Graham asked about the possibility of writing android apps in
159chicken. Moritz Heidkamp
161to write a gazette recipe]] about it "in the near future".
163William Xu asked about a way to upgrade all installed eggs. Felix
164added a '-reinstall' option to chicken-install which you are
166to test]].
168Thanks to Alan Post, Mario Goulart has been able to fix the links to
169the [[|]] egg feeds.
171== 3. Omelette Recipes
173The dream of many Schemers is to write Scheme for a living. Due to the
174regrettable tendency of employers to frown upon good ideas, the best
175way to achieve this is to start your own company, so you can be your
176own boss, and frown upon the good ideas of others instead.
178However, running your own company comes at a price; and a big part of
179that price is the horror of "book keeping"; the requirement to track
180all flows of money and other, more abstract, forms of value in and out
181of your company.
183Some people will tell you book-keeping is simple. "Just keep all your
184receipts and bank statements and bills and invoices", they say. "Then
185send them to your accountant at the end of the year."
187"But what about value-added tax?", you ask (or "sales tax" in some
188countries). "And what about income tax paid at source for my employees
189(including myself)?". "And why do I need to pay an accountant so much
190to do a job that a computer can easily do in milliseconds?" And then
191the smug smile slowly drips from the face of the "Oh it's easy" crowd.
193Clearly, book-keeping is complicated. And yet also simple, in that it
194is determined by sets of rules.
196We know what to do, don't we? Let's get coding!
198The problem is that book-keeping involves several different kinds of
199inputs - bills (that people send you), invoices (that you send
200people), transfers of money (bills and invoices being paid), loans (to
201and from the company), employees being paid, interest payments from
202the bank, dividend payments, and so on; while it also involves several
203different outputs - tax reports for the various taxes involved (in the
204UK, I had to deal with VAT every three months, income tax and national
205insurance when paying myself and my wife as employees every month, an
206annual filing fee, and annual corporation tax and dividend payments),
207statutory filing of certain financial summaries (generally annually),
208and internal reporting: How much was I spending? How much did each
209client owe? How much should be in the bank by when? Plus, it's nice to
210be able to generate nice invoices to send to folks who owe you
211money. That's a form of specialised report, too, just reporting on a
212single invoice.
214Each of the output reports depend in complex ways on different
215information from the inputs. The VAT reports mainly have to add up how
216much VAT I've paid when being billed by others, and how much VAT I've
217charged when invoicing - meaning that VAT needs to be tracked on all
218bills and invoices so it can be extracted. They also want to know
219totals of actual money in and out of the company in the period (even
220stuff where VAT isn't an issue), presumably to check up on
221me. Meanwhile, end of year reports tend to need to know how much I've
222invoiced for various different kinds of work, and what I've spent on
223what kinds of things: buying equipment that will last me for several
224years is handled differently to expenses like travel, or buying stuff
225that I eventually resell to clients (so in our invoices, we need to
226keep track of money charged for services separately to money charged
227for things).
229Some reports care about virtual money moving hands. As soon as I
230invoice somebody, then the company now has a virtual asset - some
231money owed to it. That's worth as much as cash in the bank from some
232perspectives (generally, I have to pay tax on it as soon as it's
233invoiced, even if I've not been paid). And yet some care only about
234actual cash changing hands (working out my bank balance, for instance).
236Sometimes our clients invite us to incur expenses in doing work for
237them (such as extra travel) and then invoice them on for those
238expenses, so they pay us back - in which case, expenses need to be
239able to be tied to invoices, as well. Sometimes we decide to cancel an
240invoice, which can't be done by just pretending it never existed, for
241audit-trail reasons; we need to issue a "negative" invoice called a
242credit note.
244Just to complicate matters more, the actual movement of money isn't
245atomic. If I invoice somebody on date A, they might post me a cheque
246which arrives on date B, which I pay into the bank on date C, which
247actually clears into the account (and thereby appears on my bank
248statement, when I get it) on date D. So at date A the company now has
249a "we are owed" pretend-money asset, which goes through various stages
250until it finally turns into money in the bank on date D.
252I handled my book-keeping with some hacky scripts written in Chicken
253Scheme. What I'm going to document here is partly what I've done, and
254partly what I should have done - it was a very iterative process,
255refining the best way to handle stuff, and there's lots of
256improvements I've wanted to make but not had time to. So I'm going to
257describe the ideal case, not the hacky half-way house I actually have
258right now!
260The approach I took was to have a file called a "ledger" that I enter
261all my invoices and so on into. This is parsed to build up a bunch of
262data structures in memory, from which the various reports can easily
263be obtained. Firstly, for each kind of input object (invoices, bills,
264etc) there's a list of them, or more often a hashmap to make them easy
265to find by some identifier (I can give my invoices unique symbolic
266names, for instance). That contains the raw data as parsed from the
267ledger file. But then we also create summary structures, which are
268used by the more general reports to generate their output without
269having to special-case each and every different input object type, and
270to enable sharing of common functionality between reports.
272The main summary structure is the double-entry transaction list, which
273models the entire financial activity of the company as transfers
274between accounts.
276Imagine I invoice Widget Corp for setting up and installing a router:
278  INVOICE INV005: Issued 2011-04-25
279  Router setup and installation: GBP 800
280  1 router from my stock: GBP 350
281  1 train ticket for me to go to their site: GBP 35 (no VAT due)
282  Subtotal: GBP 1,185
283  VAT on the above: GBP 230
284  Total due: GBP 1,415
286As part of the work, I lose a router (worth GBP 350) from my stock,
287and have to spend GBP 35 on a train fare.
289This might expand into the following transactions:
291 * 2011-03-02: "Expense for Widget Corp (INV005)"
292   * +35 "Travel to site"
293   * cash -35
295 * 2011-04-25 "Invoice Widget Corp (INV005)"
296   * -800 (Router set up and installation)
297   * stock.balances -350 (1 of LX300 router, serial number 0343248)
298   * clients.widgetcorp.expenses -35 (Travel 2011-03-02)
299   * taxes.vat -230
300   * clients.widgetcorp.balance +1415
302And, eventually, they might pay me, which hits my bank account some
303time later:
305 * 2011-05-07 "Payment from Widget Corp (INV005)"
306   * clients.widgetcorp.balance -1415
307   * bank.balance +1415
309And then one day I'll pay my VAT bill, which will look something like:
311 * 2011-06-01 "VAT payment for period from 2011-03-01 to 2011-06-01"
312   * taxes.vat 230
313   * bank.balance -230
315Note a few tricky things. Each transaction's "splits", as the lines
316within them are known, have to sum to zero for everything to balance
317correctly, which tells us that nothing has gone missing. So when we
318start being owed GBP 1,415 by Widget Corp, we need to account for
319where that asset has come from. Special accounts with names such as
320"" (for value generated by me working) and
321"clients.widgetcorp.expenses" (for previously-paid expenses that, as
322of this invoice, I can charge the client for) pop into
323existence. "taxes.vat" looks as if VAT is a form of income for me, as
324money comes "from" it in the transaction - which is sort of true; I'm
325charging Widget Corp for some VAT alongside for the actual work
326done. Figuring out what signs to put on all the items in the invoice
327is mind-bending and painful, but if you just concentrate on making it
328all add up to zero in the end and starting from things that are
329obvious (is money going into or out of the bank account, or the "owed
330to me by this customer" account?), you can figure it out.
332From the above, we can start to flesh out some data structures:
335(define-record txn
336               date customer code description splits)
338(define-record txn-split
339               account amount notes)
342(define *txns* (make-hash-table))
343(define (register-txn! txn)
344  (if (hash-table-exists? *txns* (txn-date txn))
345      (begin
346        (set! (hash-table-ref *txns* (txn-date txn))
347              (cons txn
348                    (hash-table-ref *txns* (txn-date txn)))))
349      (begin
350        (set! (hash-table-ref *txns* (txn-date txn))
351              (list txn)))))
354What is an "account"? There's a few kinds, and what kind of account it
355is matters in reporting. Accounts might be assets within the company -
356such as "clients.widgetcorp.balance" or "bank.balance" or
357"stock.balance". Or they may be places where money (be it real or
358virtual) is created from or destroyed by (from the perspective of the
359company), such as "" and "". The important
360difference is that balance-type accounts have a balance that is
361increased when money is sent to them and decreased when it's taken
362out, and that balance is part of the value of the company, while the
363income/expense type accounts don't. In my terminology, these are
364"balance" accounts and "delta" accounts. Each account also begins to a
365group, used to aggregate them in reports: there's income accounts,
366bank accounts, client accounts, and so on. And accounts may be tied to
367a third party - I've given an example of a client above, but also, the
368organisations that send me bills have balances (the money I owe
369them). In general, every third party (be they ones that bill me, or
370ones that I invoice, or both - I've interacted with other freelancers,
371sometimes working for them, sometimes vice versa) has a set of
372accounts attached to them for their balance, expenses I can claim from
373them, and so on. That implies another set of record types:
376(define-record third-party
377               name address balance-account expenses-account)
379(define-record account
380               name type group third-party)
383(define *third-parties* (make-hash-table))
384(define *accounts* (make-hash-table))
386(define (find-account acct-name)
387  (hash-table-ref *accounts* acct-name))
389(define (register-account! acct)
390  (set! (hash-table-ref *accounts* (account-name acct)) acct))
393An account's {{third-party}} slot may be {{#f}} if it's not part of a
394third party.
396Accounts are the organisational structure that turns a sea of financial
397events into something we can start to make sense of. In the next thrilling
398installment, we will look at actually entering transactions, and turning them into
399a data structure from which useful reports can be produced...
401== 4. About the Chicken Gazette
403The Gazette is produced occasionally by a volunteer from the Chicken
404community. The latest issue can be found at
405[[]] or you can follow it in your feed
406reader at [[]]. If you'd like to
407write an issue, [[|consult the wiki]]
408for the schedule and instructions!
Note: See TracBrowser for help on using the repository browser.