This is the mail archive of the guile@cygnus.com mailing list for the guile project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
jglascoe@jay.giss.nasa.gov writes: > On Fri, 30 Oct 1998, Maciej Stachowiak wrote: > > > (define (hash->keys mytab) > > (let ((real-tab (cdr mytab)) > > (entry->key cadr) > > (end (vector-length real-tab))) > > (let loop-over-tab ((index 0) > > (accum ())) > > (if (= index end) > > accum > > (loop-over-tab (+ index 1) > > (let loop-over-bucket ((l (vector-ref real-tab index)) > > (accum accum)) > > (if (null? l) > > accum > > (loop-over-bucket (cdr l) > > (cons (car l) accum))))))))) > > hrmm. functional, pretty, and sleek. But I bet this guy is faster: > > > (define (hash->keys mytab) > > (let ((real-tab (cdr mytab)) > > (entry->key cadr) > > (end (vector-length real-tab))) > > (do ((index 0 (+ 1 index)) > > (accum () (do ((l (vector-ref real-tab index) (cdr l)) > > (accum accum (cons (car l) accum))) > > ((null? l)) > > accum))) > > ((= index end)) > > accum))) > > functional, pretty, sleek, and fast. I see no difference why performance would differ. A tail call is as fast as iteration in most decent Schemes. I am too lazy to do timing tests right now though :-) In my typical code-writing style I'd probably write the first version in fact, even though it is longer textually; I find named let makes iteration a lot clearer (at least to me). I this case in particular, it makes more sense to me to have the initializer, the test, the base case and the update for each loop appear in that order, rather than the order {(initilizers and updates), test, base case} as they do with the do loop version. > > > ... rewriting working simple-minded code to functional but efficient > > code is not hard even by hand, and smart compilers do exist. > > I guess it takes practice ;) > Definitely. Again, it is true that Scheme makes it easy to write code that is bound to be inefficient without a lot of support from the implementation. However, it lets you write such code very quickly, and in a relatively tiny amount of code, and then rewrite it to be more efficient, either by hand or through automated tools by being easily parseable and transformable. Incidentally, you mentioned order of magnitude improvements of length of Perl/Python source code vs. C, I think Scheme often gives improvements on the same scale. I've observed such drastic reductions personally many times when translating C code to Scheme or corresponding expansions going the other way. It can be longer than perl code in some cases, but that is because Scheme has a tradition of using meaningful identifiers and uniform surface syntax, whereas perl is highly irregular and prone to using very short identifiers and many non-alphanumeric characters for key parts of the semantics. I'd bet python and scheme code to do the same task would be about the same length in lines if comparable libraries were available. Indeed, the Scheme code would probably be shorter for some tasks if you used the right abstractions, since Scheme has better support for building "embedded languages" - i.e. domain-specific sublanguages integrated into the language itself. Finally, I have to reply in reference to an old comment that Scheme is in fact a VHLL and is widely recognized as such. It does have some functionality outside the scope of the typical VHLL, and many versions lack the domain-specific libraries to be a _useful_ VHLL for many tasks, but I'd still definitively categorize it as a VHLL. - Maciej