Lisp for Java Users: Read Symbols

A new version of the ListReader read method will return Symbols when we type a word. For simplicity, this version no longer parses numbers but it should be obvious to an experienced developer how to merge that capability into this definition.

private static Map<String, Symbol> symbolTable = new HashMap<> (); public Object read () throws IOException { stream.skipBlanks (); final int chr = stream.peekChar (); if (chr == OPEN_PAREN) { stream.readChar (OPEN_PAREN); final List<Object> result = new ArrayList<> (); while (!stream.peekChar (CLOSE_PAREN)) { result.add (read ()); stream.skipBlanks (); } stream.readChar (CLOSE_PAREN); return result; } final StringBuilder buffer = new StringBuilder (); while (!Character.isWhitespace (stream.peekChar ()) && stream.peekChar () != OPEN_PAREN && stream.peekChar () != CLOSE_PAREN) { buffer.append ((char)stream.readChar ()); } final String name = buffer.toString (); Object result = symbolTable.get (name); if (result == null) { result = new Symbol (name); symbolTable.put (name, (Symbol)result); } return result; }

Notice how the read method always looks in the symbolTable for a Symbol before creating a new one, so there will never be more than one Symbol of the same name returned by the read method. This saves a little bit of space but that is not really the point. It also means that Lisp code can determine if two Symbols are the same just by checking the pointers. In other words, == can be used instead of equals. This saves a little but of time, but that still is not really the point. The real value of keeping only one copy of a Symbol is that shared properties can be attached to a Symbol. We are going to use Symbols as variables and function names so it is important that the value or function definition is global.