guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: On procedures within procedures


From: Mark H Weaver
Subject: Re: On procedures within procedures
Date: Fri, 05 Apr 2013 02:12:56 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Mike Gran <address@hidden> writes:
> I've been looking over one of the solutions to a Guile 100 problem
> (a basic version of the `ls' command) at the link below.  It is
> interesting stylistically because it works very hard at minimizing the
> scope of procedures.  It uses a lot of procedures within procedures,
> like, for example, within a `let*' block.
>
> https://gist.github.com/spk121/5301264

Apart from stylistic issues, I spotted a few errors in the code.

  (digits (lambda (n) (if (eq? n 0) 0 (1+ (ceiling (log10 n))))))

This has two problems.  First, the use of inexact arithmetic (via log10)
means that 'digits' is not guaranteed to compute the correct answer.
That's not good.  Also, for purposes of this formatting task, (digits 0)
should be 1, not 0.

Second, 'eq?' is not guaranteed to work on numbers.  '=' should be used
here, or 'zero?'.  'eqv?' could be safely used, but it has a different
meaning than '='.  'eqv?' tests "operational equivalence", whereas '='
tests "numerical equality".  Numerical equality is the right thing here.

There are other places where 'eq?' is used inappropriately:

   (bits-set?
    (lambda (bits . masks)
      (let ((mask (fold logior 0 masks)))
        (eq? mask (logand bits mask)))))

The code also uses 'eq?' to compare characters, e.g.:

  (define (string-starts-with? s c) (eq? c (string-ref s 0)))

  (if (eq? type #\l) ...)

'eq?' is not guaranteed to work on characters either.  To compare
characters, use 'char=?'.  'eqv?' could also work, but IMO it's cleaner
to use 'char=?' when you know that both arguments are characters.

     Mark



reply via email to

[Prev in Thread] Current Thread [Next in Thread]