 //
 
 public protocol TensorProtocol : RangeReplaceableCollection, RandomAccessCollection {
-    associatedtype ItemType
-    var items: ContiguousArray<ItemType> { get }
-    var itemCountPerElement: IndexDistance { get }
+    associatedtype UnitType
+    var units: ContiguousArray<UnitType> { get }
+    var unitCountPerElement: IndexDistance { get }
     var elementShape: TensorShape? { get }
     subscript(index: Index) -> Self { get }
     subscript(index: TensorIndex) -> Self { get }

    }

    /// Access a sub-tensor at the current dimension at index
    public subscript(index: Int) -> Tensor<ItemType> {
        get {
            precondition(!isScalar, "I am a scalar and I have no dimensions!")
            let newShape = shape.dropFirst()
            let contiguousIndex = itemIndex(fromIndex: index)
            let range = contiguousIndex..<contiguousIndex+newShape.contiguousSize
            return Tensor(shape: newShape, items: items[range])
        }
        set {
            precondition(!isScalar, "I am a scalar and I have no dimensions!")
            let newShape = shape.dropFirst()
            let contiguousIndex = itemIndex(fromIndex: index)
            let range = contiguousIndex..<contiguousIndex+newShape.contiguousSize
            items.replaceSubrange(range, with: newValue.items)
        }
    }

    public var count: Int {
        return isScalar ? 0 : items.count / itemCountPerElement
    }

    /// Returns a sequence of tensor indices for scalar elements

                         "I am a scalar and I have no dimensions!")
            precondition(newValue.base.elementShape == elementShape,
                         "Element shape mismatch")
            units[unitSubrange(from: bounds)] =
                newValue.base.units[newValue.base.unitSubrange(from: newValue.baseRange)]
        }
    }

}

extension Tensor : RandomAccessCollection {
    public typealias Index = Int

    /// Access a sub-tensor at index
    public subscript(index: TensorIndex) -> Tensor<UnitType> {
        get {
            precondition(!isScalar || index.isEmpty, "I am a scalar and I have no dimensions!")
            let newShape = shape.dropFirst(index.count)
            let contiguousIndex = index.contiguousIndex(in: shape)
            let range = contiguousIndex..<contiguousIndex+newShape.contiguousSize as Range
            return Tensor(shape: newShape, units: units[range])
        }
        set {
            precondition(!isScalar || index.isEmpty, "I am a scalar and I have no dimensions!")
