Re: conciseness is power



Greg Bacon wrote:
As an exercise, I wrote code to find anagrams in a one-word-per-line
dictionary. See http://blogs.pragprog.com/cgi-bin/pragdave.cgi/
Practices/Kata/KataSix.rdoc.  Within the equivalence classes, I sorted
the words in ascending order and sorted classes in descending order of
size. See the code below:

  (defun anagram-list (hash)
    (let ((anagrams '()))
      (maphash (lambda (normal words)
                  (when (>= (length words) 2)
                    (push words anagrams)))
        hash)
      anagrams))

  (defun find-anagrams (path)
    (let ((anagrams (make-hash-table :test #'equal)))
      (with-open-file (s path)
        (loop for word = (read-line s nil)
          while word do
            (push word (gethash (normal-form word) anagrams))))
      (anagram-list anagrams)))

  (defun chars-of (word)
    (loop for i from 0 below (length word) collect (char word i)))

  (defun normal-form (word)
    (let* ((chars (chars-of (string-downcase word)))
           (normal-order (sort chars #'char-lessp)))
      (coerce normal-order 'string)))

(defun normal-form (word) (sort word #'char-lessp))

Just for one. I did not look that hard at other code.


(defun longest-first (a b) (let ((lena (length a)) (lenb (length b))) (cond ((> lena lenb) t) ((< lena lenb) nil) (t (loop for aa in a for bb in b do (when (string-lessp bb aa) (return nil)) t)))))

  (let ((anagrams (find-anagrams #P"words721.txt")))
    (loop for group in anagrams do
      (setf group (sort group #'string-lessp)))
    (loop for group in (sort anagrams #'longest-first) do
      (format t "~{~a~^ ~}~%" group)))

For comparison, I wrote Perl code to do the same task:

  #! /usr/bin/perl

  sub longest_first {
    my $bylen = scalar(@$b) <=> scalar(@$a);

    if ($bylen) {
      return $bylen;
    }
    else {
      my $byalpha;
      for (0 .. $#$a) {
        $byalpha = $a->[$_] cmp $b->[$_];
        return $byalpha if $byalpha;
      }
      0;
    }
  }

  @ARGV = "words721.txt" unless @ARGV;

  my %group;
  while (<>) {
    s/\s+\z//;

    push @{ $group{ join "", sort split //, $_ } } => $_;
  }

  my @anagrams = map [ sort @$_ ], grep @$_ >= 2, values %group;

  for (sort longest_first @anagrams) {
    print join(" " => @$_), "\n";
  }

The sort comparator is syntactically awkward and bulky, but in the other
areas, the Perl code seems more concise.

I am sure it is. Conciseness is a Perl Prime Directive. Lisp is naturally concise, but avoids syntax by making things like DEFUN explicit, so in small examples it can look bloated.





Please understand that I don't mean this as yetanotherflame.

Well then watch out for sound bites like "conciseness is power". To a point yes. Beyond that point lies obscurity. The K language (an APL-like tool) really does make conciseness the Prime Directive. You should see their one-page spread*** application. It is a howler, but they are serious.


I mean, we just have to write this stuff, not read it. And even with COBOL there just is not that much to type.

kenny
.