2013-05-24 30 views
7

Tôi có this function để chuyển đổi một Array đến một ParArray, đưa ra các số đề như tham số:tham số kiểu Generic cho chuyển đổi vào bộ sưu tập song song

def parN[T](collection: Array[T], n: Int) = { 
    val parCollection = collection.par 
    parCollection.tasksupport = new ForkJoinTaskSupport(
     new concurrent.forkjoin.ForkJoinPool(n)) 
    parCollection 
} 

Bây giờ tôi muốn làm cho điều này chung chung, như vậy mà nó làm việc với các bộ sưu tập khác hơn Array:

def parN[S, T[S] <: Parallelizable[S, ParIterable[S]]](collection: T[S], n: Int) = { 
    val parCollection = collection.par 
    parCollection.tasksupport = new ForkJoinTaskSupport(
     new concurrent.forkjoin.ForkJoinPool(n)) 
    parCollection 
} 

Nhưng when I call it với parN(Array(1, 2, 3), 2), tôi nhận được lỗi này:

inferred type arguments [Int,Array] do not 
conform to method parN's type parameter bounds 
[S,T[S] <: scala.collection.Parallelizable[S,scala.collection.parallel.ParIterable[S]]] 

Mặt khác, điều này đang làm việc:

val x: Parallelizable[Int, ParIterable[Int]] = Array(1, 2, 3) 

Bất kỳ ý tưởng những gì có thể xảy ra với các tham số kiểu của tôi?

Trả lời

5

Trước hết, lưu ý rằng đây là sự cố cụ thể đối với Array: phương pháp của bạn hoạt động cho List hoặc bất kỳ bộ sưu tập thông thường nào khác (ngoại trừ những thông số có nhiều loại). Ví dụ:

scala> parN(List(1,2,3), 2) 
res17: scala.collection.parallel.ParIterable[Int] = ParVector(1, 2, 3) 

scala> parN(Set(1,2,3), 2) 
res18: scala.collection.parallel.ParIterable[Int] = ParSet(1, 2, 3) 

Array luôn là trường hợp đặc biệt khi nói đến bộ sưu tập, bởi vì ... nó không phải là bộ sưu tập. Vì Java, định nghĩa của nó là final class Array[T] extends Serializable with Cloneable. Tuy nhiên, có tồn tại hai implicits, có sẵn ở khắp mọi nơi, có thể chuyển đổi Array sang một loại bộ sưu tập (ArrayOpsWrappedArray). Và các loại làm thực hiện Parallelizable, vì vậy tất cả mọi thứ nên được tốt ... trừ loại suy luận được theo cách này:

tham số kiểu của bạn chỉ được định nghĩa là T[S], vì vậy khi nhận được Array[Int], nó sẽ sẵn sàng suy Array[Int], và sau đó kiểm tra giới hạn: thất bại, Array không mở rộng Parallelizable. Trò chơi kết thúc.

tôi thấy hai lựa chọn:

  • Bạn rõ ràng có thể nói rằng bạn muốn có một Parallelizable:

    def parN[S](collection: Parallelizable[S, ParIterable[S]], n: Int) 
    

    Hoặc nếu bạn cần truy cập vào các loại thực T (trong trường hợp của bạn không, nhưng ai biết):

    def parN[S, T[S] <: Parallelizable[S, ParIterable[S]]](collection: T[S] with 
        Parallelizable[S, ParIterable[S]], n: Int) 
    
  • hoặc bạn có thể chấp nhận anythin g có thể được ngầm chuyển đổi sang một Parallelizable, sử dụng một tham số ngầm:

    def parN[S, T <% Parallelizable[S, ParIterable[S]]](collection: T, n: Int) 
    

    đó là phiên bản ngắn:

    def parN[S, T](collection: T, n: Int)(implicit ev: T => 
        Parallelizable[S, ParIterable[S]]) 
    

Tất cả những nên làm việc. Trong trường hợp của bạn, tôi sẽ giới thiệu một trong những đầu tiên: nó là một trong những dễ đọc nhất mà không công việc.

+0

WOw, đánh bại tôi. Mẫu kiểu lớp là con đường để đi đến đây. Tuy nhiên, bạn không cần phải thêm vào một ': Manifest' yêu cầu để làm việc với mảng? – wheaties

+1

@wheaties không có 'Manifest \ ClassTag' thậm chí không cần thiết vì phương thức của anh ta không thực sự tạo ra một mảng (' Parallelizable.par' không cần một tệp kê khai, nó luôn biết cách xây dựng một bộ sưu tập par). Và trong trường hợp của mảng, nó chỉ kết thúc tốt đẹp mảng ban đầu, nó thậm chí không sao chép nó. – gourlaysama

+0

Cảm ơn câu trả lời chi tiết, tôi đã kết thúc bằng cách sử dụng một khung nhìn '<%' được kết hợp với 'CustomParallelizable'. – ValarDohaeris

Các vấn đề liên quan