]> git.donarmstrong.com Git - lilypond.git/blob - TODO
release: 1.1.26
[lilypond.git] / TODO
1 Features you cannot find in the doco as working, should be mentioned
2 here.
3
4 This is an assorted collection of stuff that will be done, might be
5 done, or is an idea that I want to think about
6
7 Most of the items are marked in the code as well, with full explanation. 
8 grep for TODO and ugh/ugr/urg
9
10 *In a piece such as the Zipoli piece in mutopia/... there is a stray
11 `8' over every bar line when processed by LilyPond 1.1.25.
12
13 TODO before 1.2
14
15         * junk Text_def, use G_text_item in stead.
16
17         * junk Script_def
18
19         * fix partial measures in meaningful way.
20
21         * fix AFM for BlueSky AFM files.
22
23         * working notehead style.
24
25         * add scripts to bars eg.  |^"bla" 
26
27         * relative mode for mi2mu
28
29         * uniformise recent feta contributions.
30         - use SCM and Molecules for {accordeon stuff, }
31         - bigger and fatter 4/4 C
32
33         * make a SMOB of Atom and Molecule
34
35         * use kerning for dynamics.
36
37         * sort out directory stuff.
38         - --prefix option?
39         - -I option per filetype?
40         - kpathsea?
41
42 **************
43 I also found a few bugs:
44
45 * The examples in input/test/bar-scripts.ly and score-bar-scripts.ly
46   don't work. The problem seems to be that you can't define a 
47   a score identifier and then use it in the \score block.
48
49
50         - make separate MF chars for endings of ledger lines, and calc rest of lines.
51
52         * support_l_arr_ empty in staff-margin's G_staff_side_item
53
54
55 ************
56
57 How can I specify a chord whose duration is longer than a whole note?
58
59  \type ChordNames { \chord{ A1*2-min } }
60
61 gives me a parse error.  And \times doesn't work either.  I can't use
62 a spacer note.  So it seems to be impossible to have long chords of
63 general length.  Of course, in the example above I can use \breve.
64 But what if I want a chord that lasts for 3 whole notes?  Or what
65 about 2.5 whole notes?  Is there a mechanism for getting this kind of
66 length?  
67
68
69 Why does my second extender request get junked in the following:
70
71 \score{
72 < \notes \relative c''{ 
73      a4()b()c()d c()d()b()a }
74    \type Lyrics \lyrics {
75      foo1 __  bar2. __ _4 }
76 > }
77
78 It seems that \cr and \decr don't work any more.  
79
80 \score{
81   \notes{
82     a \cr b \rc c }
83   \paper{linewidth=-1.;}
84 }
85
86 Gives me 
87
88 qq.ly:3:9: warning: can't find (de)crescendo to end:
89     a \cr
90           b \rc c }
91
92
93
94 Use of semicolons is still rather confusing.  They are obligatory
95 after some types of assignments and illegal after others.  
96
97   \property foo=bar               illegal
98   foo = 3 at top level            illegal
99   foo = 3 inside \paper           obligatory               
100   foo = \notes{ ...} top level    illegal
101   foo = \translator{ } in \paper  obligatory
102
103 As far as I can tell, the sole accomplishment of this syntactic
104 irregularity is to keep the user as confused as possible.  
105
106
107 I was trying to get interstaff beams to work and did this:
108
109 \score{
110 \type GrandStaff <
111 \type Staff=one \notes\relative c'{
112   \stemup
113   [c8 c \translator Staff=two \stemup c c]
114   \translator Staff=one
115   \stemdown 
116   [ b8 \translator Staff=two a8]
117   \translator Staff=one 
118   c4 
119   }
120 \type Staff=two \notes{ \clef bass; s1 }
121 >
122 \paper{
123                 \translator{
124                         \GrandStaffContext
125                         minVerticalAlign = 3.0*\staffheight;
126                         maxVerticalAlign = 3.0*\staffheight;
127                 }
128   linewidth = -1.;
129 }
130 }
131
132 The beams are at the right angle, but they aren't in the right place.
133
134
135
136 *******************
137
138
139         * fractional chord durs.
140
141         * hang Item on Spanner
142
143         * remove Interval dim_ from Dimension_cache and rename the struct.
144
145         * do --safe for PS output?
146
147         * convert-mudela --output
148
149         * Staff_margin (with a partial measure.)
150
151         * fix "I've been drinking too much"
152
153         * fix pletvisibility properties:
154           - bracket on/off/no-bracket-when-beam
155           - num on/off/no-num-when-beam
156
157         * fix: standchen.
158
159         * junk backlinks?
160
161         * junk text{sharp,flat,etc}
162
163         * fix convert-mudela manpage
164
165         * decimal point in \paper {}
166
167         *{  \voiceone <a'4.*2/3  d''4.*2/3 fis''4.*2/3>  [g''8 fis'' e''] d''4 |}
168          and=20
169          { \voicetwo  d'4 d'2.*2/3 } spacing
170
171         * tied notes for MIDI
172
173         * sharp /flat on trills (in MIDI ??)
174
175         * scm-ify \property values.
176
177         * move class Lookup {} into scm
178
179 BUGS:
180
181         * collisions/voices \voiceone \voicetwo are broken; see 
182           input/praeludium-fuga-E.ly
183           mutopia/J.S.Bach/wtk1-fugue2.ly
184
185         * fix: text on rests: rediculous dims
186
187         * ly2dvi
188           - bottomnote for ly2dvi
189           - deps for ly2dvi
190
191         * fix midi output:
192            - default duration?  duration must be not entered
193              explicitely on first note.
194
195         * turn slope-damping on/off
196
197         * c4 \! \> c4
198
199         * tremolo stuff
200
201         * gallina barlines.
202
203         * fix height of / collisions with lyrics (chords), 
204            see input/test/vertical-text.ly; input/test/repeat.ly
205
206         * latex bla.tex broken (titles / \lilyfooter stuff?)
207
208         * check/set minimum slur/tie length
209
210         * msgfmt -o check?
211
212         * \breathmark TeX macro 
213
214         * catch GUILE errors?
215
216         * add new glyphs to font.ly
217
218         * formatting of input stuff. 
219
220         * \notes{ a \< b \cr } vs \notes{ a \< b \! }
221
222         * if possible, it might be nice for a warning to appear if someone does
223         \translator with no name and without assigning it to an
224         identifier.  
225
226         * space after bars?
227
228         * 'hinterfleisch' before bar (e.g. wtk1-fugue2)?
229
230         * \type Voice \times 2/3 { [c8 c16 c16 c16 c16] }
231
232         * fix singleStaffBracket
233
234         * repeat bars: need distance after ":|" and before "|:"
235
236         Summary of minor spelling irregularities:
237         -  capitalization/use of underscores in property names
238
239         * fix SkipBars  -> skipBars
240
241         * \shape 1st dim skipped? 
242
243         * fix marks/barnumbers/marginal notes
244
245         * broken scripts:
246         lbheel = \script { "bheel" 0 0 -1  0 0 }
247         rbheel = \script { "bheel" 0 0 1 0 0 }
248         lbtoe = \script { "btoe" 0 0 -1 0 0 }
249         rbtoe = \script { "btoe" 0 0 1 0 0 }
250         lfheel = \script { "fheel" 0 0 -1  0 0 }
251         rfheel = \script { "fheel" 0 0 1 0 0 }
252         lftoe = \script { "ftoe" 0 0 -1 0 0 }
253         rftoe = \script { "ftoe" 0 0 1 0 0 }
254         
255         and also
256         
257         portato= \script { "portato" 0 -1 0 1 0 }
258
259 STUFF
260         * check out legal/(c) matters for scores.
261
262         * check out GCC signatures?
263
264         * Align_element::padding  ?
265
266         * uniformise property names...
267           - ydirection <-> yDirection
268           - rather allow '_' in identifiers first (i.e. junk ^ and _),
269             and do y_direction?
270           - typo checks on property names?
271
272         * use streambufs and iostream
273         to provide IO handling for TeX stream, mudela stream, data-file.
274
275         * seriously buffer TeX output (do profile of writing .5 mb TeX file.)
276
277         * strip EXEs before installing
278
279         * zip target for binary windows dist (JBR)
280
281         * junking \skip req in lyrics
282
283         * Language:
284         - \type -> \context ?
285         - \translator -> ?
286         - fix \partial 
287         - \bla {} vs \bla ; 
288         - mix engraver hacking with music ?
289         - \once\property  KEY = VAL
290         - \addtranslator, \removetranslator
291         - junk ^ and _ for scripts
292         - junk _ for lyrics.
293         - abstract grammar.
294
295         * percussion note heads
296
297         * mi2mu empty staffs.
298
299         * horizontal centering of dynamics 
300
301         * \font\fontA=feta20.afm (.afm?)
302
303         * gzip RH manpage
304
305         * stable make/config stuff
306
307         * $DEPENDENCIES_OUTPUT support
308
309         * Xdvi zooming ?! Try to understand GS garbage collection.
310                 gs: Error: /undefined in draw_beam
311                 gs: Operand stack:
312
313         * fix vertical alignment and stafflines
314
315         * GrandStaff needs more work -- I want a single word
316         `harpsichord' to the left of the grandstaff, not one on each
317         stave.  (Organ staff -- with separate pedal -- but common
318         properties may be something to think about.  Of course for
319         organ you want to be able to give stop indications on the way
320         through, so the \property Voice.Instrument would be a stop,
321         and \property GrandStaff.instrument would be PipeOrgan...)
322
323         * revise the Score_priority_align_engraver concept.  It sucks. 
324
325         * make new VoiceOne, VoiceTwo, VoiceThree contexts with
326 ydirection and hshift preset
327
328         * *.yo: fix pod manpage layout legacy
329
330         * text-items clash with stems/beams
331
332         * --include, -I option for ly2dvi (pass on to lily)
333
334         * fix placement of beam-less abbrev
335
336         * \meter 3/4;
337         <{\voiceone cis4. cis8 cis4 | cis4 cis cis | r1 }
338          {\voicetwo cis,4 r r | r2. | r1 }> |
339         }
340
341         * try to use template<Type> iso MACRO(Type)
342
343         - NEWS: ... Musical_pitch (analogous to Duration and Rhythmic_req)
344           think about, analogous to pitch: 
345            * { a4 a16 } c <-- duration of c?
346            * < a4 b8 > c <-- duration of c?
347
348         * \tempo 4. = 90;
349
350         * fix audio-items (don't use (input) requests, but copy data)
351
352         * make sure all ex's have a mudela-version
353
354         * do rest-collisions for Multi_measure_rests as well.
355
356         * split error/warning in error/warning/non_fatal_error
357
358         * add a Duration_convert member to Duration_iter to set parameters.
359         Junk global duration settings. 
360
361         * minimum length second part broken tie
362  
363         * en-,discouraged linebreaking: 
364           - handle DISALLOW < penalty > FORCE
365           - discourage breaking of slurs
366
367         * fix variable define/lookup parser global<->paper
368
369         * fix title/instrument placements; see input/test/title.ly
370
371         * <\voiceone c4. \voicetwo c4>
372
373         * add full cello suites to web site (kom op, Maarten!)
374
375         * Rethink Time_description
376           * \cadenza , \meter, \grouping should all be \properties
377
378         * rename
379           - measure -> bar
380           - abbrev -> tremolo
381           - abbreviation-beam -> (measured/unmeasured) tremolo
382           - partial -> anacrouse
383
384         * shared lib
385
386         * robustify Beam (in case of no stems, 32nd notes)
387
388         * decentralised spring factory
389
390         * move paper vars into engraver properties
391
392         * check for groff / troff/ nroff et
393
394         * more intelligent file searching
395
396         * make LilyPond RPM fully relocatable
397
398         * disable spaces in TeX stuff
399         
400         * handle ^C for tmp/file creation.
401
402         * dots & rest collisions.
403
404         * documentation
405         - introduction?
406         - info?
407         - LaTeX?
408         - more manpages?
409
410         * versioning for Feta
411
412         * the warning about the negative slur/tie length appears twice
413         which is irritating.
414
415         * The `3' in the meter key is a one or two pixels too thin (at 600dpi)
416         in the middle:
417
418         * the bracket is ugly (wings are too parabolic, should be more circular)
419
420         * better hshift (dots, distance, head dependent)
421
422         * clefs (AG): The "8" should appear closer to the actual clef,
423           touching it.
424
425         * put errorlevel in Input class
426
427         * junk nesting slurs
428
429         * integrate midi-elts from mi2mu and lily?
430
431
432 3RD PARTY BUGS:
433 ****************
434 /*
435 ICE
436 */
437 signature S {
438   int foo ();
439 };
440
441 signature V {
442   S * s();
443 };
444
445
446 V*v();
447 f ()
448 {
449   return v( )->foo ();
450 }
451
452 /*
453
454   egcs-1.1
455
456 foo.cc: In function `int f()':
457 foo.cc:6: label `b' used but not defined
458 */
459 void
460 f ()
461 {
462   bool b;
463   if (b && && b)
464          ;      
465 }
466 ***************
467
468         * make GCC warn about ctor that leaves member vars  uninitialised.
469
470         * GNU diff 2.7: diff -rN does not see a new directory with empty file
471
472         * glibc 2.0:
473
474           f = fopen ("/dev/null", "r")
475           assert (feof (f))
476
477 3RD PARTY PROJECTS:
478
479         * GNU patch 
480           - 'double-fix' mode: ignore identical fix, rather than suggest 
481             to revert patch direction when (more or less? exactly) the same 
482             thing is fixed
483
484 PROJECTS
485
486         * Scripts:
487         - fix position of bar number
488         - stack scripts in chords:
489           % fingering:        footing:
490             < a-4 c-2 g-1 >   < c-\ltoe e-\lheel >
491         - script-spacing
492         - slur parts as a script
493         - stack parameterised scripts for fingering and footing:
494
495         * convert-mudela:
496         - automatically add  a \version if not present.
497         - better parsing
498         - make smarter
499         - convert-mudela -e empty.ly
500
501         * emacs mudela-mode
502         -  should handle block comments too.
503         -  handle lexer modes (\header, \melodic, \lyric) etc.
504         -  indentation
505         -  notenames?
506         -  fontlock: \melodic \melodic
507
508         * use properties for:
509         - plet?
510         - Staff_sym size
511         - default tempo.
512         - font size
513         - bartypes (get rid of derived Span_bar_engravers)
514         - cadenza mode? 
515
516         * page handling:
517         - PS output
518         - optimal pagebreaking.
519
520         * Unicode support? -> man 7 unicode
521         - 16 bit Strings
522         - -u switch
523         - detect of 16/8 bit files
524         - examples to go with it.
525
526         * Spring_spacer:
527         - write a faster Spring_spacer (without matrices if possible)
528         - relate energybound to linelen unitspace fontsize etc.
529         - used fixed point fp?
530
531         * \header
532         - output header info to MIDI too.
533
534         * a musical dictionary. See Documentation/vocabulary-*, other
535         languages:
536         - explanations
537         - italian
538         - german
539         - dutch
540         - swedish
541          .. ?
542
543         * chords
544         - guitar chords (fret diagrams)
545         - other chord name styles (american(?) style)
546         - basso continuo
547         - MIDI output?
548
549         * Debug logs:
550         - derive lily_stream, Dstream, texstream from ostream?
551         - indentable stream as baseclass for TeX stream, lily stream, Dstream.
552         - use dstream feature in mi2mu
553         - integrate IO checking into stream class
554
555         * input converters
556         - NIFF?
557         - ABC? 
558         - SMDL?
559
560         * add to MIDI output:
561         - tempo change
562         - ornaments (and trills?)
563         - repeat/volta
564         - slurs
565         - accents
566         - dynamics
567         - account for rhythmic position in measure
568         - etc.
569
570         * grace notes
571         - make separate class for Grace_*_engravers 
572         (which is at Voice_gravs level)
573         - make encapsulated spacing problems.
574
575         * accidentals per Voice_group
576
577         * Output class, handles : (smallish)
578         - help text /(c) notice?
579         - version line
580         - warning /errors/progress
581         - abort on error/warning; exit status
582         - quiet/ignore-version options
583         - logfile output
584
585         * elaborate Staff_side baseclass:
586         - scripts
587         - text
588         - slur start/end
589
590         * PS 
591         - speed up PS code.
592         - PS lines to .eps files
593         - write custom prolog
594
595         * Output an output format independent (ofi) typeset file; and 
596           make ofi2 TeX, MusiXTex, Display PostScript, PostScript,
597           Ascii... interpreters. (difficult)
598
599         - NIFF ?
600         - Common Music Notation
601         - PostScript output (esp. Beams, Slurs, etc)
602         - Move all Score_elems, into libmutype.a
603         - SGML
604
605         * Documentation
606         - Doc (C) stuff of sheet music
607         - a better format?  SGML?  TeX?  Info?
608         - a better tutorial
609
610         * more spanners (smallish)
611         - Glissando
612         - trill
613
614         * Rewrite Stem, Beam and Rhythmic_grouping (hairy)
615         - [c8. c32 c32]
616         - doc on Rhythmic_grouping
617         - general shaving on Beam and Stem
618         - use plet grouping
619         - separate visual from rhythmic info even more
620         - beams over bars
621
622         * lines:
623         - Ledger lines, should be separate item: Ledger_lines, Ledger_lines
624         - set different line sizes / thicknesses
625         - beam stem showthrough, inter beam sizes (french vs german style)
626
627         * Collisions
628         - left/right note balls should be handled by Collision:
629         < \multi 2; { \stem 1; <b c> } { <f as b> } >
630
631         * Keys:
632         - merge key{item} & localkey{item}?
633         - spacing, national styles?
634
635         * Support for TAB
636         - redo Notehead to allow digits as heads
637         - add a \tablature {} lexer mode for easy entering
638
639         * should adjust stemlength for flag number.
640
641         * breaking:
642         - caching breakpoints
643         - saving them
644         - specify number of lines
645
646 INPUTLANGUAGE
647
648         * c4 4 4 4 for c4 c4 c4 c4?
649
650         * neatly (and readably) expressing concurrent
651         voices
652
653         * <c f a>4 ?
654
655         * Viola mode?
656
657                 @c c g e g 
658         for
659                 c g es g, 
660
661                 @A c g e g
662         for
663                 cis gis e gis
664
665         * relative mode for pitch entering
666
667         * configure pitch_byte
668
669         * rest name configurable
670
671 SMALLISH PROJECTS
672
673         * limit memory usage; the full coriolan takes up too much resources.
674
675         * fix confusing naming in Engraver vs Engraver_group_engraver (context)
676
677         * progress when creating MIDI elts.
678
679         * A range for context errors (eg. mark both { and }. )
680
681         * lyric in staff  (sharpsharp in staff, text below)
682
683         * half sharps/flats
684
685         * write Dynamic_line (to group dynamics horizontally)
686
687         * use Real for all y positions.
688         - use translate_axis( .. ,Y_AXIS)  iso separate variables.
689
690         * half-sharps, half-flats
691
692         * adaptive accidental spacing.
693
694         * handle EOF graciously in error messages.
695
696         * declare notenametab?
697
698         * midi esp.: use I32 iso int where 32 bits are needed (or assumed...)
699
700         * stafftypes: voice names/ instrument names.
701
702         * lily \tempo
703
704         * C meter iso 4/4, idem for alla breve, etc.
705
706         * textspanner: center position
707
708         *   % toe to bheel   four to five
709             %   ^_u            4_5  
710             %     -                           
711             %  --|x--         --|x--
712             %  --|---         --|---
713             %  --|---         --|---
714           (where "to" is a tiny bow)
715
716         * auxilliary file for caching info.
717
718         * Text_crescendo
719
720         * clean solution for staffsize in items.
721
722         * revise calcideal
723
724 IDEAS
725
726         * Output data structures of Mudela in XML/SGML.
727
728         * create libmudela, or liblily_frontend
729
730         * move MIDI stuff (including Quantization) to a ANSI C libmidi library.
731
732         * Spacing_request for manually adjusting spacing
733
734         * caching breakpoints
735
736         * used fixedpoint arithmetic for min. energy.
737
738         * move towards incremental algorithms.
739
740         * far fetched language ideas
741         - design meta-language like TeX and Metafont
742         - programming/macros input
743
744         * versioning stuff (cvt mudela, mudela, etc.)
745
746         * Klavarskribo?
747
748         * dynamic loading of engravers? 
749
750 SMOBS:
751
752 ****************************************
753 Han-Wen Nienhuys <hanwen@cs.uu.nl> writes:
754
755 > mcmanus@IDT.NET writes:
756 > > > I want different C++ objects (with scheme embedded) to be linked by
757 > > > C++ pointers.  I want to access these other objects from the Scheme
758 > > > code, and I want access to these pointers from C++.
759 > > 
760 > > You can do this with a  combination of smob's and primitive functions,
761 > > though it may not be  be exactly what you wanted.   You would have one
762 > > smob  for each class in  your application, and then  you would write a
763 > > primitive function that would return the objects  that are linked to a
764 > > base object.
765
766 > And the smob and the C++ class are interlinked?  Like
767
768 >       class Foo_class {
769 >               Foo_smob *smob_ptr_;
770 >       }
771
772 >       struct Foo_smob {
773 >               Foo_class *class_ptr_
774 >       }
775
776 Usually you can get away without having this interlinked structure.
777 One piece of information you need when exporting objects to scheme is
778 the smob tag for your class.  You might store this value (a long) into
779 a class static variable, or a file static variable.  I'll use a class
780 static variable in this example.
781
782 I typically use code that works like this (untested code ahead):
783
784 class Foo_class {
785     static long *Foo_smob_tag;
786     SCM obj; // representation as a scheme object, description comes later
787 }
788
789 // call this once on startup
790 void init_Foo_class {
791     static scm_smobfuns type_rec;
792
793     type_rec.mark = foo_mark;
794     type_rec.free = foo_free;
795     type_rec.print = foo_display;
796     type_rec.equalp = 0;
797     Foo_class::Foo_smob_tag = new int(scm_new_smob(type_rec));
798 }
799
800 When you want to export an object to scheme, you put a pointer to the
801 object itself in the cdr of the cell, and the tag in the car of the
802 cell.  The code looks like this:
803
804 // Is this a Foo?
805 static int
806 foo_p(SCM obj)
807 {
808     return(SCM_NIMP(obj) && SCM_CAR(obj) == Foo_class::Foo_smob_tag);
809 }
810
811 // given a Scheme representation, return, a C++ representation
812 static Foo_class *
813 foo_unbox(SCM obj)
814 {
815     return((Foo_class*)SCM_CDR(obj));
816 }
817
818 // the SCM representation of the object is stored inside itself
819 // this will become useful when destructor gets called
820 static SCM
821 foo_box(Foo_class *foo)
822 {
823     SCM_DEFER_INTS;
824     SCM_NEWCELL(foo->obj);
825     SCM_SETCAR(foo->obj, Foo_class::Foo_smob_tag);
826     SCM_SETCDR(foo->obj, (SCM)foo);
827     SCM_ALLOW_INTS;
828     return foo->obj;
829 }
830
831 > C++ determines life time, so what is the strategy?
832
833 What happens now when the destructor gets called?  Lets set the cdr to
834 NULL, and then check for that in all of the primitive functions that
835 use your smob.  We'll call this notion 'live'; a scheme object is
836 'live' if the C++ representation still exists, it's dead if the C++
837 object is gone.  You can still have references to dead objects in
838 scheme code; it's just an error to use them.  This idea is stolen from
839 Emacs's handling of buffers ('buffer-live-p' and friends).
840
841 Add another function, foo_live_p:
842
843 static int
844 foo_live_p(SCM obj)
845 {
846     return(foo_p(obj) && SCM_CDR(obj) != NULL);
847 }
848
849 In you destructor, you need to do:
850
851 ~Foo_class()
852 {
853     SCM_CDR(this->obj, NULL);
854 }
855
856 When writing new primitives, now just check foo_live_p().
857
858 I hope the above helps,
859
860 -russ
861
862
863 --
864 "Even if you are on the right track, you'll get run over 
865 if you just sit there."  
866              --Will Rogers (1879-1935)
867
868 ***************************
869
870 > I am still muddling along with integrating GUILE in LilyPond, and I
871 > have a question.  I want to replace an existing C++ implementation of
872 > identifier tables by GUILE's code.  I've managed to replace
873
874 >       Hash_table<String,Identifier*>
875
876 > by
877
878 >       Hash_table<SCM, Identifier*>
879
880 > and use interning and GUILE symbols for doing the identifier lookup.
881 > But I'd like to use GUILE's hash tables as well, and that's were my
882 > question comes in: is there an interface that allows me to iterate
883 > through the entries of a GUILE hash table?
884
885 I use the following, which should definitely be provided somewhere
886 in guile, but isn't, AFAIK:
887
888 (define (hash-table-for-each fn ht)
889   (do ((i 0 (+ 1 i)))
890       ((= i (vector-length ht)))
891     (do ((alist (vector-ref ht i) (cdr alist)))
892         ((null? alist) #t)
893       (fn (car (car alist)) (cdr (car alist))))))
894
895 (define (hash-table-map fn ht)
896   (do ((i 0 (+ 1 i))
897        (ret-ls '()))
898       ((= i (vector-length ht)) (reverse ret-ls))
899     (do ((alist (vector-ref ht i) (cdr alist)))
900         ((null? alist) #t)
901       (set! ret-ls (cons (fn (car (car alist)) (cdr (car alist))) ret-ls)))))
902
903 If you want a C version, you can run the above code through hobbit, or
904 tranlate it to C by hand.
905
906 -russ
907
908
909 --
910 "Whenever you find yourself on the side of the majority, it is time to
911 pause and reflect."
912              -- Mark Twain
913 ***********************