diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -82,7 +82,7 @@
 
 husk scheme is developed by [Justin Ethier](http://github.com/justinethier).
 
-The interpreter is based on the code from the book [Write Yourself a Scheme in 48 Hours](http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours) written by Jonathan Tang and hosted / maintained by Wikibooks.
+The interpreter is based on code from the book [Write Yourself a Scheme in 48 Hours](http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours) written by Jonathan Tang and hosted / maintained by Wikibooks.
 
 If you would like to request changes, report bug fixes, or contact me, visit the project web site at [GitHub](http://github.com/justinethier/husk-scheme).
 
diff --git a/hs-src/Language/Scheme/Core.hs b/hs-src/Language/Scheme/Core.hs
--- a/hs-src/Language/Scheme/Core.hs
+++ b/hs-src/Language/Scheme/Core.hs
@@ -30,6 +30,7 @@
 import List
 import IO hiding (try)
 import System.Directory (doesFileExist)
+import System.IO.Error
 --import Debug.Trace
 
 {-| Evaluate a string containing Scheme code.
@@ -626,12 +627,23 @@
 
 readProc :: [LispVal] -> IOThrowsError LispVal
 readProc [] = readProc [Port stdin]
-readProc [Port port] = (liftIO $ hGetLine port) >>= liftThrows . readExpr
+readProc [Port port] = do
+    input <-  liftIO $ try (liftIO $ hGetLine port)
+    case input of
+        Left e -> if isEOFError e
+                     then return $ EOF
+                     else throwError $ Default "I/O error reading from port" -- FUTURE: ioError e
+        Right inpStr -> do 
+            liftThrows $ readExpr inpStr 
 readProc args@(_ : _) = throwError $ BadSpecialForm "" $ List args
 
 writeProc :: [LispVal] -> IOThrowsError LispVal
 writeProc [obj] = writeProc [obj, Port stdout]
-writeProc [obj, Port port] = liftIO $ hPrint port obj >> (return $ Nil "")
+writeProc [obj, Port port] = do
+    output <- liftIO $ try (liftIO $ hPrint port obj)
+    case output of
+        Left e -> throwError $ Default "I/O error writing to port"
+        Right _ -> return $ Nil ""
 writeProc other = if length other == 2
                      then throwError $ TypeMismatch "(value port)" $ List other 
                      else throwError $ NumArgs 2 other
@@ -729,6 +741,7 @@
               ("integer?", isInteger),
               ("list?", unaryOp isList),
               ("null?", isNull),
+              ("eof-object?", isEOFObject),
               ("symbol?", isSymbol),
               ("symbol->string", symbol2String),
               ("string->symbol", string2Symbol),
@@ -1049,6 +1062,10 @@
 isNull :: [LispVal] -> ThrowsError LispVal
 isNull ([List []]) = return $ Bool True
 isNull _ = return $ Bool False
+
+isEOFObject :: [LispVal] -> ThrowsError LispVal
+isEOFObject ([EOF]) = return $ Bool True
+isEOFObject _ = return $ Bool False
 
 isSymbol :: [LispVal] -> ThrowsError LispVal
 isSymbol ([Atom _]) = return $ Bool True
diff --git a/hs-src/Language/Scheme/Macro.hs b/hs-src/Language/Scheme/Macro.hs
--- a/hs-src/Language/Scheme/Macro.hs
+++ b/hs-src/Language/Scheme/Macro.hs
@@ -36,6 +36,7 @@
 import Language.Scheme.Types
 import Language.Scheme.Variables
 import Control.Monad.Error
+import Data.Array
 --import Debug.Trace -- Only req'd to support trace, can be disabled at any time...
 
 -- Nice FAQ regarding macro's, points out some of the limitations of current implementation
@@ -66,16 +67,14 @@
   rest <- mapM (macroEval env) xs
   return $ List $ first : rest
 
+-- Inspect code for macro's
 --
--- FUTURE: Issue #4
--- equivalent matches/transforms for vectors, and what about dotted lists?
+-- Only a list form is required because a pattern may only consist
+-- of a list here. From the spec:
 --
--- macroEval env (Vector v) = do
--- macroEval env (DottedList ls l) = do
+-- "The <pattern> in a <syntax rule> is a list <pattern> that 
+--  begins with the keyword for the macro."
 --
--- but first, need to confirm such syntax is even allowed
-
--- Inspect code for macro's
 macroEval env lisp@(List (Atom x : xs)) = do
   isDefined <- liftIO $ isNamespacedBound env macroNamespace x
   if isDefined
@@ -147,7 +146,11 @@
 loadLocal localEnv identifiers pattern input hasEllipsis outerHasEllipsis = do 
   case (pattern, input) of
 
-       -- Future: vector
+       -- For vectors, just use list match for now, since vector input matching just requires a
+       -- subset of that behavior. Should be OK since parser would catch problems with trying
+       -- to add pair syntax to a vector declaration.
+       ((Vector p), (Vector i)) -> do
+         loadLocal localEnv identifiers (List $ elems p) (List $ elems i) False outerHasEllipsis
 
        ((DottedList ps p), (DottedList is i)) -> do
          result <- loadLocal localEnv  identifiers (List ps) (List is) False outerHasEllipsis
@@ -266,11 +269,9 @@
                           _ -> throwError $ Default "Unexpected error in checkLocal (Atom)"
                 else defineVar localEnv pattern (List [val])
 
--- FUTURE: Issue #4 - vector support. And what the heck are these next two lines doing here? :)
---
--- , load into localEnv in some (all?) cases?: eqv [(Atom arg1), (Atom arg2)] = return $ Bool $ arg1 == arg2
--- : eqv [(Vector arg1), (Vector arg2)] = eqv [List $ (elems arg1), List $ (elems arg2)] 
---
+checkLocal localEnv identifiers hasEllipsis pattern@(Vector _) input@(Vector _) = 
+  loadLocal localEnv identifiers pattern input False hasEllipsis
+
 checkLocal localEnv identifiers hasEllipsis pattern@(DottedList _ _) input@(DottedList _ _) = 
   loadLocal localEnv identifiers pattern input False hasEllipsis
 --  throwError $ BadSpecialForm "Test" input
@@ -329,8 +330,27 @@
                   Nil _ -> return lst
                   _ -> throwError $ BadSpecialForm "Macro transform error" $ List [lst, (List l), Number $ toInteger ellipsisIndex]
 
--- FUTURE: issue #4 - vector transform (and taking vectors into account in other cases as well???)
+transformRule localEnv ellipsisIndex (List result) transform@(List ((Vector v) : ts)) (List ellipsisList) = do
+  if macroElementMatchesMany transform
+     then do 
+             -- Idea here is that we need to handle case where you have (vector ...) - EG: (#(var step) ...)
+             curT <- transformRule localEnv (ellipsisIndex + 1) (List []) (List $ elems v) (List result)
+             case curT of
+               Nil _ -> if ellipsisIndex == 0
+                                -- First time through and no match ("zero" case). Use tail to move past the "..."
+                           then transformRule localEnv 0 (List $ result) (List $ tail ts) (List [])  
+                                -- Done with zero-or-more match, append intermediate results (ellipsisList) and move past the "..."
+                           else transformRule localEnv 0 (List $ ellipsisList ++ result) (List $ tail ts) (List [])
+               List t -> transformRule localEnv (ellipsisIndex + 1) (List $ result ++ [asVector t]) transform (List ellipsisList)
+               _ -> throwError $ Default "Unexpected error in transformRule"
+     else do lst <- transformRule localEnv ellipsisIndex (List []) (List $ elems v) (List ellipsisList)
+             case lst of
+                  List l -> do
+                      transformRule localEnv ellipsisIndex (List $ result ++ [asVector l]) (List ts) (List ellipsisList)
+                  Nil _ -> return lst
+                  _     -> throwError $ BadSpecialForm "transformRule: Macro transform error" $ List [(List ellipsisList), lst, (List [Vector v]), Number $ toInteger ellipsisIndex]
 
+ where asVector lst = (Vector $ (listArray (0, length lst - 1)) lst)
 
 transformRule localEnv ellipsisIndex (List result) transform@(List (dl@(DottedList _ _) : ts)) (List ellipsisList) = do
   if macroElementMatchesMany transform
@@ -463,7 +483,8 @@
     initializePatternVars localEnv src identifiers $ List ps
     initializePatternVars localEnv src identifiers p
 
--- FUTURE: Issue #4: vector
+initializePatternVars localEnv src identifiers (Vector v) = do
+    initializePatternVars localEnv src identifiers $ List $ elems v
 
 initializePatternVars localEnv src identifiers (Atom pattern) =  
        -- FUTURE:
@@ -502,7 +523,8 @@
         Bool False -> lookupPatternVarSrc localEnv p
         _ -> return result
 
--- FUTURE: Issue #4: vector
+lookupPatternVarSrc localEnv (Vector v) = do
+    lookupPatternVarSrc localEnv $ List $ elems v
 
 lookupPatternVarSrc localEnv (Atom pattern) =  
     do isDefined <- liftIO $ isNamespacedBound localEnv "src" pattern
diff --git a/hs-src/Language/Scheme/Types.hs b/hs-src/Language/Scheme/Types.hs
--- a/hs-src/Language/Scheme/Types.hs
+++ b/hs-src/Language/Scheme/Types.hs
@@ -141,6 +141,7 @@
                         -- FUTURE: stack (for dynamic wind)
                        }
          -- ^Continuation
+ 	| EOF
  	| Nil String
          -- ^Internal use only; do not use this type directly.
 
@@ -214,6 +215,7 @@
 -- |Create a textual description of a 'LispVal'
 showVal :: LispVal -> String
 showVal (Nil _) = ""
+showVal (EOF) = "#!EOF"
 showVal (String contents) = "\"" ++ contents ++ "\""
 showVal (Char chr) = [chr]
 showVal (Atom name) = name
diff --git a/hs-src/shell.hs b/hs-src/shell.hs
--- a/hs-src/shell.hs
+++ b/hs-src/shell.hs
@@ -52,7 +52,7 @@
   putStrLn " | | | | |_| \\__ \\   <    /// \\\\\\   \\__ \\ (__| | | |  __/ | | | | |  __/ "
   putStrLn " |_| |_|\\__,_|___/_|\\_\\  ///   \\\\\\  |___/\\___|_| |_|\\___|_| |_| |_|\\___| "
   putStrLn "                                                                         "
-  putStrLn " husk Scheme Interpreter                                     Version 2.1 "
+  putStrLn " husk Scheme Interpreter                                     Version 2.2 "
   putStrLn " (c) 2010 Justin Ethier              github.com/justinethier/husk-scheme "
   putStrLn "                                                                         "
 
diff --git a/husk-scheme.cabal b/husk-scheme.cabal
--- a/husk-scheme.cabal
+++ b/husk-scheme.cabal
@@ -1,5 +1,5 @@
 Name:                husk-scheme
-Version:             2.1
+Version:             2.2
 Synopsis:            R5RS Scheme interpreter program and library.
 Description:         Husk is a dialect of Scheme written in Haskell that implements 
                      a subset of the R5RS standard. Advanced R5RS features are
