some View
SE-0244 দ্বারা প্রবর্তিত হিসাবে এটি একটি অস্বচ্ছ ফলাফলের ধরণ এবং এক্সকোড ১১ সহ সুইফ্ট 5.1 এ উপলব্ধ You
একজন নিয়মিত জেনেরিক স্থানধারীর থেকে পৃথক যা কলার দ্বারা সন্তুষ্ট:
protocol P {}
struct S1 : P {}
struct S2 : P {}
func foo<T : P>(_ x: T) {}
foo(S1()) // Caller chooses T == S1.
foo(S2()) // Caller chooses T == S2.
একটি অস্বচ্ছ ফলাফলের ধরণটি প্রয়োগের মাধ্যমে সন্তুষ্ট একটি জড়িত জেনেরিক স্থানধারক , যাতে আপনি এটি সম্পর্কে ভাবতে পারেন:
func bar() -> some P {
return S1() // Implementation chooses S1 for the opaque result.
}
যেমন দেখতে খুঁজছেন:
func bar() -> <Output : P> Output {
return S1() // Implementation chooses Output == S1.
}
প্রকৃতপক্ষে, এই বৈশিষ্ট্যটির সাথে শেষ লক্ষ্যটি আরও স্পষ্ট আকারে বিপরীত জেনেরিকদের অনুমতি দেওয়া, যা আপনাকে বাধাও যুক্ত করতে দেয়, যেমন -> <T : Collection> T where T.Element == Int
। আরও তথ্যের জন্য এই পোস্টটি দেখুন ।
এ থেকে দূরে সরে আসার প্রধান বিষয় হ'ল ফাংশন some P
রিটার্ন হ'ল এমনটি যা একটি নির্দিষ্ট একক কংক্রিটের মানকে মানায় যা ফিরে আসে P
। ফাংশনটির মধ্যে বিভিন্ন অনুসরনকারী প্রকারগুলি ফেরত দেওয়ার চেষ্টা করা একটি সংকলক ত্রুটি দেয়:
// error: Function declares an opaque return type, but the return
// statements in its body do not have matching underlying types.
func bar(_ x: Int) -> some P {
if x > 10 {
return S1()
} else {
return S2()
}
}
অন্তর্ভুক্ত জেনেরিক স্থানধারক একাধিক ধরণের দ্বারা সন্তুষ্ট হতে পারে না।
এটি কোনও ফাংশন প্রত্যাবর্তনের বিপরীতে P
, যা উভয়কে উপস্থাপন করতে ব্যবহার করা যেতে পারে S1
এবং S2
কারণ এটি একটি স্বেচ্ছাসেবী P
অনুসারে মান উপস্থাপন করে:
func baz(_ x: Int) -> P {
if x > 10 {
return S1()
} else {
return S2()
}
}
ঠিক আছে, তাহলে -> some P
প্রোটোকল রিটার্নের ধরণের উপর অস্বচ্ছ ফলাফল ধরণের কী কী সুবিধা রয়েছে -> P
?
১. অস্বচ্ছ ফলাফলের ধরণগুলি প্যাটগুলির সাথে ব্যবহার করা যেতে পারে
প্রোটোকলের একটি প্রধান বর্তমান সীমাবদ্ধতা হ'ল প্যাটগুলি (সম্পর্কিত ধরণের প্রোটোকল) প্রকৃত প্রকার হিসাবে ব্যবহার করা যায় না। যদিও এটি এমন একটি বিধিনিষেধ যা ভাষার ভবিষ্যতের সংস্করণে সম্ভবত তুলে নেওয়া হবে, কারণ অস্বচ্ছ ফলাফলের ধরণগুলি কার্যকরভাবে কেবল জেনেরিক স্থানধারক, সেগুলি আজ প্যাটগুলির সাথে ব্যবহার করা যেতে পারে।
এর অর্থ আপনি এই জাতীয় জিনিসগুলি করতে পারেন:
func giveMeACollection() -> some Collection {
return [1, 2, 3]
}
let collection = giveMeACollection()
print(collection.count) // 3
২. অস্বচ্ছ ফলাফলের ধরণের পরিচয় রয়েছে
যেহেতু অস্বচ্ছ ফলাফলের প্রকারগুলি কার্যকর করে একটি একক কংক্রিটের প্রকারটি ফিরে আসে, সংকলক জানে যে একই ফাংশনে দুটি কল একই ধরণের দুটি মান ফেরত দিতে পারে।
এর অর্থ আপনি এই জাতীয় জিনিসগুলি করতে পারেন:
// foo() -> <Output : Equatable> Output {
func foo() -> some Equatable {
return 5 // The opaque result type is inferred to be Int.
}
let x = foo()
let y = foo()
print(x == y) // Legal both x and y have the return type of foo.
এটি আইনী কারণ সংকলক উভয়ই জানেন x
এবং y
একই ধরনের কংক্রিটের प्रकार রয়েছে। এটি ==
উভয় পরামিতি প্রকারের জন্য এটি একটি গুরুত্বপূর্ণ প্রয়োজনীয়তা Self
।
protocol Equatable {
static func == (lhs: Self, rhs: Self) -> Bool
}
এর অর্থ এটি দুটি মানের প্রত্যাশা করে যা উভয়ই কংক্রিটের অনুসারে রূপের ধরণের are এমনকি যদি Equatable
এটি কোনও ধরণের হিসাবে ব্যবহারযোগ্য হয় তবে আপনি দুটি স্বতঃস্ফূর্ত Equatable
মানিয়ে যাওয়া মানগুলি একে অপরের সাথে তুলনা করতে সক্ষম হবেন না , উদাহরণস্বরূপ:
func foo(_ x: Int) -> Equatable { // Assume this is legal.
if x > 10 {
return 0
} else {
return "hello world"
}
}
let x = foo(20)
let y = foo(5)
print(x == y) // Illegal.
যেহেতু সংকলক প্রমাণ করতে পারে না যে দুটি স্বেচ্ছাচারিত Equatable
মান একই অন্তর্নিহিত কংক্রিট ধরণের থাকে।
একইভাবে, আমরা যদি অন্য একটি অস্বচ্ছ ধরণের রিটার্নিং ফাংশনটি চালু করি:
// foo() -> <Output1 : Equatable> Output1 {
func foo() -> some Equatable {
return 5 // The opaque result type is inferred to be Int.
}
// bar() -> <Output2 : Equatable> Output2 {
func bar() -> some Equatable {
return "" // The opaque result type is inferred to be String.
}
let x = foo()
let y = bar()
print(x == y) // Illegal, the return type of foo != return type of bar.
উদাহরণটি অবৈধ হয়ে যায় কারণ উভয়ই foo
এবং bar
ফিরে আসার some Equatable
পরেও তাদের "বিপরীত" জেনেরিক স্থানধারক Output1
এবং Output2
বিভিন্ন ধরণের দ্বারা সন্তুষ্ট হতে পারে।
৩. জেনেরিক স্থানধারীদের সাথে অস্পষ্ট ফলাফলের ধরণের রচনাগুলি
নিয়মিত প্রোটোকল-টাইপ করা মানগুলির থেকে পৃথক, অস্বচ্ছ ফলাফলের ধরণগুলি নিয়মিত জেনেরিক স্থানধারীদের সাথে ভালভাবে রচনা করে, উদাহরণস্বরূপ:
protocol P {
var i: Int { get }
}
struct S : P {
var i: Int
}
func makeP() -> some P { // Opaque result type inferred to be S.
return S(i: .random(in: 0 ..< 10))
}
func bar<T : P>(_ x: T, _ y: T) -> T {
return x.i < y.i ? x : y
}
let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Legal, T is inferred to be the return type of makeP.
makeP
সবে ফিরে এলে এটি কাজ করবে না P
, কারণ দুটি P
মানের মধ্যে অন্তর্নিহিত কংক্রিটের ধরণ থাকতে পারে, উদাহরণস্বরূপ:
struct T : P {
var i: Int
}
func makeP() -> P {
if .random() { // 50:50 chance of picking each branch.
return S(i: 0)
} else {
return T(i: 1)
}
}
let p1 = makeP()
let p2 = makeP()
print(bar(p1, p2)) // Illegal.
কেন কংক্রিট ধরণের উপর একটি অস্বচ্ছ ফলাফল টাইপ ব্যবহার?
এই মুহুর্তে আপনি নিজেরাই ভাবছেন, কেন কেবল কোডটি এইভাবে লিখবেন না:
func makeP() -> S {
return S(i: 0)
}
ভাল, একটি অস্বচ্ছ ফলাফল ধরণের ব্যবহার আপনাকে ফাংশনের উপর নির্ভর করে কোনও কোড না ভেঙে কংক্রিটের ধরণটি পরবর্তীকালে লাইনের নীচে পরিবর্তন করার নমনীয়তা S
সরবরাহ করে কেবলমাত্র প্রদত্ত ইন্টারফেসটি প্রকাশ করে প্রকারের প্রয়োগের বিশদ P
তৈরি করতে দেয়।
উদাহরণস্বরূপ, আপনি প্রতিস্থাপন করতে পারেন:
func makeP() -> some P {
return S(i: 0)
}
সঙ্গে:
func makeP() -> some P {
return T(i: 1)
}
কল করে এমন কোনও কোড ভঙ্গ না করে makeP()
।
দেখুন অনচ্ছ প্রকারভেদ অধ্যায় ভাষা গাইডের এবং সুইফট বিবর্তন প্রস্তাব এই বৈশিষ্ট্যটি আরও তথ্যের জন্য।