2017-07-26 26 views
9

Tôi đã giải quyết được vấn đề kết hợp Y. Ngay bây giờ tôi thấy rằng tôi không thể tham chiếu một tham số chung một cách đệ quy.Làm cách nào để tham chiếu một tham số chung theo cách đệ quy?

Y = λf.(λx.f (x x)) (λx.f (x x)) 

ví dụ:

IntUnaryOperator fact = Y(rec -> n -> n == 0 ? 1 : n * rec.applyAsInt(n - 1)); 

IntUnaryOperator Y(Function<IntUnaryOperator, IntUnaryOperator> f) { 
    return g(g -> f.apply(x -> g.apply(g).applyAsInt(x))); 
} 

IntUnaryOperator g(G g) { 
    return g.apply(g); 
} 

//  v--- I want to remove the middle-interface `G` 
interface G extends Function<G, IntUnaryOperator> {/**/} 

Q: Làm thế nào tôi có thể sử dụng tham số chung vào phương pháp g để tránh giới thiệu một giao diện bổ sung G, và tham số chung nên tránh UNCHECKED cảnh báo?

Xin cảm ơn trước.

+2

Tôi khá chắc chắn điều đó là không thể. Java không cung cấp một cách để yêu cầu một tham số chung nhất định là một giao diện chức năng AFAIK. – Ryan

Trả lời

4

Bạn có thể khai báo một phương pháp chung với một loại định nghĩa đệ quy

<G extends Function<G, IntUnaryOperator>> IntUnaryOperator g(G g) { 
    return g.apply(g); 
} 

gì không làm việc, là để gọi phương pháp này với một biểu thức lambda, gán biểu thức lambda để G. The specification nói

15.27.3. Loại một biểu thức Lambda

Một biểu thức lambda là tương thích trong một bối cảnh chuyển nhượng, bối cảnh gọi, hoặc bối cảnh đúc với một loại mục tiêu T nếu T là một kiểu giao diện chức năng (§9.8) ...

G được không phải là giao diện chức năng, mà là tham số kiểu và không có cách nào để suy ra loại giao diện thực tế cho G tại đây.

Đó vẫn hoạt động, khi bạn sử dụng giao diện thực tế G cho biểu thức lambda:

IntUnaryOperator Y(Function<IntUnaryOperator, IntUnaryOperator> f) { 
    return g((G)g -> f.apply(x -> g.apply(g).applyAsInt(x))); 
} 

// renamed the type parameter from G to F to avoid confusion 
<F extends Function<F, IntUnaryOperator>> IntUnaryOperator g(F f) { 
    return f.apply(f); 
} 

// can't get rid of this interface 
interface G extends Function<G, IntUnaryOperator> {/**/} 

hoặc

IntUnaryOperator fact = Y(rec -> n -> n == 0 ? 1 : n * rec.applyAsInt(n - 1)); 

IntUnaryOperator Y(Function<IntUnaryOperator, IntUnaryOperator> f) { 
    return this.<G>g(g -> f.apply(x -> g.apply(g).applyAsInt(x))); 
} 

// renamed the type parameter from G to F to avoid confusion 
<F extends Function<F, IntUnaryOperator>> IntUnaryOperator g(F f) { 
    return f.apply(f); 
} 

// can't get rid of this interface 
interface G extends Function<G, IntUnaryOperator> {/**/} 

Vì vậy, các phương pháp g là chung không có sự phụ thuộc vào giao diện G, nhưng giao diện vẫn được yêu cầu để được sử dụng làm loại mục tiêu cho biểu thức lambda.

+0

có, tôi chỉ tìm thấy biến kiểu có thể được tham chiếu đệ quy quá. và vấn đề xảy ra trong biểu thức lambda. cảm ơn rất nhiều. ví dụ: 'g (null)' hoạt động tốt, nhưng 'g (g -> null)' không thể hoạt động. –

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