Bluish Coder

Programming Languages, Martials Arts and Computers. The Weblog of Chris Double.


2008-10-11

Revisiting the Linear recursion combinator in Factor four years on

The Joy programming language has a linrec combinator for performing linear recursion. Some time ago I took a stab at implementing linrec in Factor. Slava also posted his version that was originally a part of Factor.

As can be seen from Slava's version, juggling the stack when four quotations are involved can be problematic. I thought I'd revisit linrec using Factor's locals library and see how it compares. This is my attempt at an implementation using locals:

:: linrec 
 ( if-quot:    ( -- ? ) 
   then-quot:  ( -- ) 
   else1-quot: ( -- ) 
   else2-quot: ( -- ) 
   -- )
  if-quot call [ 
    then-quot call 
  ] [ 
    else1-quot call 
    if-quot then-quot else1-quot else2-quot linrec
    else2-quot call
  ] if ; inline recursive

This is pretty readable compared to the solutions in the prior posts. Because linrec is a combinator it needs to be declared 'inline'. It recursively calls itself so needs to be declared 'inline recursive' to enable calls of linrec to be compiled. More details about this can be found in the Factor documentation. Usage of the linrec word looks like:

5 [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec .
 => 120

[ 5 [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec ] infer.
 => ( -- object )

{ 1 2 3 } [ dup rest empty? ] [ first ] [ rest ] [ ] linrec
  => 3

[ { 1 2 3 } [ dup rest empty? ] [ first ] [ rest ] [ ] linrec ] infer.
  => ( -- object )

[ 1000 [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec drop ] time
 => 22ms

: fac ( n -- n ) dup 1 = [ dup 1- fac * ] unless ;
[ 1000 fac drop ] time
 => 19ms

It's nice that the 'fac' word and the linrec definition seem to compile down to the same code:

[ [ dup 1 = ] [ ] [ dup 1- ] [ * ] linrec ] optimized.
  => [
      \ ( gensym ) [
          dup 1 dupd eq?
          [ drop t ]
          [ dup 1 swap tag eq? [ 1 bignum= ] [ drop f ] if ] if
          [ ] [ dup 1 - ( gensym ) * ] if
      ] label
  ]

\ fac optimized.
  => [
      dup 1 dupd eq?
      [ drop t ]
      [ dup 1 swap tag eq? [ 1 bignum= ] [ drop f ] if ] if
      [ ] [ dup 1 - fac * ] if
  ]

One confusing aspect of this linrec definition is having to declare the stack effects of the quotations passed to linrec. Depending on the linear recursion task the stack effects may be different. Compare factorial vs finding the last element of a sequence:

{ [ dup 1 = ] 
  [ ] 
  [ dup 1- ] 
  [ * ] 
} [ infer. ] each
  => ( object -- object object )
     ( -- )
     ( object -- object object )
     ( object object -- object)

{ 
   [ dup rest empty? ] 
   [ first ] 
   [ rest ] 
   [ ] 
} [ infer. ] each
  => ( object -- object object )
     ( object -- object )
     ( object -- object )
 ( -- )

Both usages of linrec still infer and compile so I guess the fact that the stack effects balance out allows this. I'm not sure whether it's just a side effect of implementation or intended.

Working on this example I can say that, for me, Factor programming has become easier compared to four years ago.

Tags: factor 

2008-10-11

The Left Fold Enumerator for i/o

There have been some interesting papers and talks about approaches to handling i/o using left folds recently.

First was the galois tech talk about a safe and efficient i/o interface in Haskell using left fold enumerators. PDF slides are here. The example web server, Hyena, is available on github.

Oleg Kiselyov then gave a talk at DEFUN about using left folds for web servers. The slides and source for the talk are available at Oleg's site in the Haskell Iteratee I/O section.

We explain input processing with left-fold enumerator, using as an example HTTP request processing in Haskell. The approach is general and applies to processing data from various collections, from in-memory data structures to databases, files, sockets, etc.

Our approach differs in: permitting incremental processing; i/o interleaving comes by default; we shall see an example of i/o multiplexing with no need for threads and related locking and synchronization.

Unlike lazy IO, our approach is correct. There is not even hint of UnsafePerformIO. Unlike Handle-based IO, accessing a disposed resource like a closed handle is just impossible in our approach. Our approach has some other nice properties, permitting composing streams and stream processors.

One can use the same processor to handle several streams one after another. Or use two processors to process parts of the same source. One can combine processors vertically, which is very useful when one stream is embedded (chunk-encoded, escaped, UTF8-encoded) into another. Enumerators and iteratees, which generalize fold, have nice algebraic properties. But we won't talk about them.

Interesting weekend reading!

Tags: haskell 

2008-09-27

New Zealand Open Source Awards

The New Zealand Open Source Awards were held in Wellington on Wednesday night. Congratulations to Robert O'Callahan who was nominated as a finalist for the 'Open Source Contributor' category, and won the award on the night!

Also winning an award was Radio New Zealand for 'Open Source use in Government'. Radio New Zealand are doing some great work distributing their content in Ogg Vorbis format as an alternative to MP3. For example, see their 'ninetonoon' page.

Another reason to love Radio New Zealand they are experimenting with the new <audio> functionality currently in the Firefox 3.1 nightly builds. Richard Hulse blogs about the Oggulate script he is writing that converts the links to Vorbis files on the page to buttons that play the Vorbis audio file using the audio element. So if you're looking for some content to give Firefox 3.1 a workout, give Radio NZ's Vorbis support a try.

Tags: mozilla 

2008-09-11

JavaScript Space Invaders Emulator

Ajaxian recently posted about a fun JavaScript implementation of PacMan. After spending way too much time on it I wondered how well an emulation of the old arcade game hardware would go in JavaScript.

I've written a few 8080 arcade game emulations before in different languages so I had a go at implementing it in JavaScript. You can try the work in progress at my JavaScript 8080 Emulation page. It runs surprisingly well on modern JavaScript engines.

The page first loads with the arcade game Space Invaders loaded. You can run a set number of instructions, or step through one at a time. It displays the disassembled output. Pressing 'Animate' will run the game in a timer and it can be played. It is a general 8080 arcade game emulator, for the games that use similar hardware to Space Invaders. The buttons at the top load the code for Space Invaders, Lunar Rescue or Balloon Bomber.

If you have a bleeding edge version of Firefox 3.1 with Ogg Vorbis <audio> support, pressing the 'Enable Audio' button will enable sound. The sound support uses <audio> to play the samples when requested by the emulator. This turns out to make a good test case for my audio support and it may need the fixes from bug 449159 and 454364 to work.

If you're interested in the other emulators I've done:

The implementation does not get traced with the TraceMonkey tracing JIT yet. I'll look into the reasons why and as TraceMonkey and my implementation improves it'll get faster I'm sure. Even so, it runs very close to full speed.

This implementation uses Canvas, audio for sound and should work on browsers with a fast JS engine and these technologies.

For the emulator loop I run a set number of instructions during a timer that is run via 'setInterval' to prevent the 'script is running too long' message. One thought that Robert O'Callahan suggested was to run the emulator in a worker thread and have communication for input/output via messages to the browser. I'll play with this idea and see how it goes - it'll give me a chance to try out Firefox 3.1 worker threads implementation.

The emulator can be run (without the GUI) from a JavaScript shell for testing purposes. I used the shell to test the implementation by running my Factor version and logging all the state of the emulated CPU, doing the same with the JavaScript version, and making sure the output was the same.

Although it's not quite perfect, it's currently playable, and shows that the types of games that are written as Java or Flash applets can be done in standard HTML and JavaScript in the latest browsers.

Tags: javascript 

2008-07-31

Theora Video Backend for Firefox Landed

It was announced at the Firefix Plus summit today that Firefox will include native Theora and Vorbis support for the HTML 5 media elements. So <video> and <audio> will support those codecs built into Firefox itself. Chris Blizzard posted about this earlier.

The backend has been committed to the main Mozilla source code and is enabled by default. You can download nightly builds and test it out. An example of a live site that uses <video> is the Wikimedia video archive.

This original commit is a work in progress. There are unimplemented bits, bugs, etc that need to be sorted out. But it's a start towards using a common codec across all platforms and will improve as we get towards the 3.1 release.

In other news, getting out of Whistler, where the summit is being held, is somewhat of an issue at the moment...

Tags: mozilla 


This site is accessable over tor as hidden service 6vp5u25g4izec5c37wv52skvecikld6kysvsivnl6sdg6q7wy25lixad.onion, or Freenet using key:
USK@1ORdIvjL2H1bZblJcP8hu2LjjKtVB-rVzp8mLty~5N4,8hL85otZBbq0geDsSKkBK4sKESL2SrNVecFZz9NxGVQ,AQACAAE/bluishcoder/-61/


Tags

Archives
Links