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]

Re: Scheme is too complicated



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