iA


Common Lisp vs Java

by Vijay Kiran

I’ve been sort of wanting to learn LISP for long time (~ 10 years). Now finally I got some chance to try that out. I’ve started reading On Lisp by Paul Graham along with Practical Common Lisp by Peter Seibel. I find them pretty invaluable in learning Lisp.

It has been nearly 9 years since I’ve started learning Java, during my programming adventures, I’ve used COBOL, Perl and Ruby. But never got to build a complete application purely using functional programming. Partly inspired by on The Reinvigorated Programmer, I start my journey of learning Common Lisp.

I’m trying to compare how I do things in Java with the exercises/programs I write while learning Lisp. Here’s the first installment:

The following Common Lisp created a database of CDs with some data, and provides methods to store the database to a file and load the same from the file.

First the Common Lisp program:

(defvar *db* nil)
 
(defun make-cd (title artist rating ripped)
  (list :title title :artist artist :rating rating :ripped ripped))
 
(defun add-record (cd) (push cd *db*))
 
(defun prompt-read (prompt)
  (format *query-io* "~a: " prompt)
  (force-output *query-io*)
  (read-line *query-io*))
 
(defun dump-db ()
  (dolist (cd *db*)
    (format t "~{~{~a:~10t~a~%~}~%}" cd)))
 
(defun prompt-for-cd ()
  (make-cd
   (prompt-read "Title")
   (prompt-read "Artist")
   (or (parse-integer (prompt-read "Rating") :junk-allowed t) 0)
   (y-or-n-p "Ripped [y/n]:")))
 
(defun add-cds ()
  (loop (add-record (prompt-for-cd))
     (if (not (y-or-n-p "Another? [y/n]:")) (return))))
 
(defun save-db (filename)
  (with-open-file (out filename
		       :direction :output
		       :if-exists :supersede)
    (with-standard-io-syntax
      (print *db* out))))
 
(defun load-db (filename)
  (with-open-file (in filename)
    (with-standard-io-syntax
      (setf *db* (read in)))))

And here’s the Java version (without saving and reading from file).

Database.java

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
 
public class Database {
    List cdList;
 
    public Database() {
        cdList = new ArrayList();
    }
 
    public Database(List cdList) {
        this.cdList = cdList;
    }
 
    public void addRecord(CompactDisc cd ) {
        cdList.add(cd);
    }
 
    public void dump(){
        for (CompactDisc compactDisc : cdList) {
            System.out.println("Title: " + compactDisc.getTitle());
            System.out.println("Artist: " + compactDisc.getArtist());
            System.out.println("Rating: " + compactDisc.getRating());
            System.out.println("Ripped: " + compactDisc.isRipped());
            System.out.println("---------------------------");
        }
        System.out.println("Total Items: " + cdList.size());
    }
 
    public void save(String path){
        try {
            PrintWriter fileWriter = new PrintWriter(
                                                   new FileOutputStream(path)
                                                   );
 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
 
        }
    }
 
}

CompactDisc.java

public class CompactDisc {
 
    public CompactDisc() {
    }
 
    public CompactDisc(String title,
                                     String artist,
                                      int rating,
                                       boolean ripped) {
        this.title = title;
        this.artist = artist;
        this.rating = rating;
        this.ripped = ripped;
    }
 
    private String title;
    private String artist;
    private int rating;
    private boolean ripped;
 
    public String getTitle() {
        return title;
    }
 
    public void setTitle(String title) {
        this.title = title;
    }
 
    public String getArtist() {
        return artist;
    }
 
    public void setArtist(String artist) {
        this.artist = artist;
    }
 
    public int getRating() {
        return rating;
    }
 
    public void setRating(int rating) {
        this.rating = rating;
    }
 
    public boolean isRipped() {
        return ripped;
    }
 
    public void setRipped(boolean ripped) {
        this.ripped = ripped;
    }
}

Main.java

import java.util.Scanner;
 
public class Main {
 
    public static void main(String... args) {
        Database db = new Database();
        Scanner input = new Scanner(System.in);
        String inputString;
 
        while (true) {
 
            CompactDisc cd = new CompactDisc();
            System.out.print("Title: ");
            cd.setTitle(input.nextLine());
 
            System.out.print("Artist: ");
            cd.setArtist(input.nextLine());
 
            System.out.print("Rating: ");
            cd.setRating(Integer.valueOf(input.nextLine()));
 
            System.out.print("Ripped [y/n]: ");
            inputString = input.nextLine();
            if (inputString.equals("y")) {
                cd.setRipped(true);
            } else if (inputString.equals("n")) {
                cd.setRipped(false);
            } else {
                System.out.println("Invalid ripped status, setting it to false!");
            }
 
            db.addRecord(cd);
 
            System.out.print("Enter another ? [y/n]: ");
            inputString = input.nextLine();
            if(inputString.equalsIgnoreCase("n")){
                break;
            }
        }
 
        db.dump();
 
    }
 
}

This is not one-to-one comparison between Common Lisp version and Java version, this is just part of my note taking while learning LISP and wrap my head around a new language.