 public extension Array {
     
     /// Maps a `transform` upon each element of the Array returning an Array of the same shape with the results.
+    ///
+    /// If transform is a throwing function, we compute the result eagerly.
     public func map<A>(transform: (Element) throws -> A) rethrows -> ComputedArray<A> {
         let baseArray = try self.allElements.map(transform)
         return ComputedArray(DenseArray(shape: self.shape, baseArray: baseArray))
     }
     
+    /// Maps a `transform` upon each element of the Array returning an Array of the same shape with the results.
+    public func map<A>(transform: (Element) -> A) -> ComputedArray<A> {
+        return ComputedArray(shape: self.shape, linear: { transform(self[linear: $0]) } )
+    }
+    
     /// Maps a `transform` upon a vector of elements from the Array. Either by rows (that is, row vectors of the column-seperated elements) or vectors of first-deminsion-seperated elements.
+    ///
+    /// If transform is a throwing function, we compute the result eagerly.
     public func vectorMap<A>(byRows rowVector: Bool = true, transform: ([Element]) throws -> [A]) rethrows -> ComputedArray<A> {
-        if let s = scalar {
-            return try transform([s]).ravel()
-        }
-        
         let slice = rowVector ? sequenceFirst : sequenceLast
         if let first = slice.first where first.isScalar { // Slice is a [ArraySlice<Element>], we need to know if its constituent Arrays are themselves scalar.
             return try transform(slice.map { $0.scalar! }).ravel()

    ///    1 2 | 5 6 --> 1 2 5 6
    ///    3 4 | 7 8 --> 3 4 7 8
    public func append<A: Array where A.Element == Element>(additionalItems: A) -> ComputedArray<Element> {
        return zipVectorMap(self, additionalItems, byRows: true, transform: {$0 + $1})
    }
    
    /// Returns a DenseArray with the contents of additionalItems concatenated to the first axis of the Array.

        }
        
        let rslice = rowVector ? right.sequenceFirst : right.sequenceLast
        let partialResults = try zip(slice, rslice).map { try internalZipVectorMap($0.0, $0.1, byRows: rowVector, transform: transform) }.ravel()
        return rowVector ? partialResults.disclose() : partialResults.discloseFirst()
    }
    
    return try ComputedArray(internalZipVectorMap(left, right, byRows: rowVector, transform: transform))
}

// Currently not exposed as part of the public API. Not sure it's useful for much else.
// Returns an Array with a rank equal to left's and a shape equal to the sums of the shapes (offset by one if byRows = false), whose (row or highest-dimensional) vectors are the output of the transform applied to pairs of left's & right's (row or highest-dimensional) vectors.
func zipVectorMap<A: Array, B: Array, X, Y where A.Element == X, B.Element == X>(left: A, _ right: B, byRows rowVector: Bool = true, transform: ([X], [X]) -> [Y]) -> ComputedArray<Y> {
    if rowVector {
        guard left.rank == right.rank     && left.shape.dropLast().elementsEqual(right.shape.dropLast()) ||
            left.rank == right.rank + 1 && left.shape.dropLast().elementsEqual(right.shape) else {
                fatalError("Shape of the right array must match the left array in all but the last dimension")
        }
    } else {
        guard left.rank == right.rank     && left.shape.dropFirst().elementsEqual(right.shape.dropFirst()) ||
            left.rank == right.rank + 1 && left.shape.dropFirst().elementsEqual(right.shape) else {
                fatalError("Shape of the right array must match the left array in all but the first dimension")
        }
    }
    let sameShape = left.shape == right.shape
    
    let enclosedLeft = left.enclose(rowVector ? [left.rank-1] : [0])
    let enclosedRight = sameShape ?
        right.enclose(rowVector ? [right.rank-1] : [0]) :
        right.map { ([$0] as [B.Element]).ravel() }
    let enclosed = zipMap(enclosedLeft, enclosedRight) { l, r in
        transform([X](l.allElements), [X](r.allElements)).ravel()
    }
    return rowVector ? enclosed.disclose() : enclosed.discloseFirst()
}


extension Array {
