সুইট ডো-ট্রাই-ক্যাচ সিনট্যাক্স ax


162

আমি দ্রুত এটিতে নতুন ত্রুটি পরিচালনার জিনিসটি বোঝার চেষ্টা করি give আমি যা করেছি তা এখানে: আমি প্রথমে একটি ত্রুটি এনাম ঘোষণা করেছিলাম:

enum SandwichError: ErrorType {
    case NotMe
    case DoItYourself
}

এবং তারপরে আমি এমন একটি পদ্ধতি ঘোষণা করলাম যা ত্রুটি ছুড়ে ফেলে (ব্যতিক্রম লোকেরা নয় এটি একটি ত্রুটি। এই পদ্ধতিটি এখানে:

func makeMeSandwich(names: [String: String]) throws -> String {
    guard let sandwich = names["sandwich"] else {
        throw SandwichError.NotMe
    }

    return sandwich
}

সমস্যাটি কলিং দিক থেকে। কোডগুলি যা এই পদ্ধতিটিকে কল করে:

let kitchen = ["sandwich": "ready", "breakfeast": "not ready"]

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it \(sandwich)")
} catch SandwichError.NotMe {
    print("Not me error")
} catch SandwichError.DoItYourself {
    print("do it error")
}

doলাইন সংকলক পরে Errors thrown from here are not handled because the enclosing catch is not exhaustive। তবে আমার মতে এটি সম্পূর্ণরূপে, কারণ SandwichErrorএনামে কেবল দুটি মামলা রয়েছে ।

নিয়মিত স্যুইচ স্টেটমেন্টের জন্য সুইফটি বুঝতে পারে যে এটি প্রতিটি ক্ষেত্রে পরিচালনা করা হলে তা সম্পূর্ণ হয়।


3
আপনি যে ধরণের ত্রুটি
ফেলেছিলেন

ত্রুটির ধরণ নির্দিষ্ট করার কোনও উপায় আছে কি?
মোস্তফা

আমি সুইফট বইয়ের নতুন সংস্করণে কিছু খুঁজে পাচ্ছি না - কেবল এখনই কীওয়ার্ডটি ছুঁড়েছে
ফারলেই হেইনেন

কোনও ত্রুটি বা সতর্কতা ছাড়াই একটি খেলার মাঠে আমার পক্ষে কাজ করে।
ফগমিস্টার

2
খেলার মাঠগুলি doশীর্ষ স্তরের ব্লকগুলিকে মঞ্জুরি দেয় না যা অবসানহীন - যদি আপনি না-নিক্ষেপ ফাংশনটিতে কাজটি আবদ্ধ করেন তবে এটি ত্রুটি তৈরি করবে।
স্যাম

উত্তর:


267

সুইফট 2 ত্রুটি পরিচালনার মডেলটির জন্য দুটি গুরুত্বপূর্ণ বিষয় রয়েছে: ক্লান্তি এবং স্থিতিস্থাপকতা। একসাথে, তারা আপনার do/ catchবিবৃতিতে প্রতিটি সম্ভাব্য ত্রুটি ধরার প্রয়োজনে সিদ্ধ হয় , কেবল আপনি জানেন না আপনি নিক্ষেপ করতে পারেন।

লক্ষ্য করুন যে কোনও ফাংশন কোন ধরণের ত্রুটি ফেলতে পারে তা আপনি ঘোষণা করেন না কেবল কেবল এটি ছোঁড়ে কিনা। এটি একটি শূন্য-এক-অনন্ত ধরণের সমস্যা: অন্যের জন্য (যেমন আপনার ভবিষ্যতের স্ব) সহ কোনও ফাংশনকে সংজ্ঞায়িত করা হচ্ছে, আপনাকে আপনার ফাংশনের প্রতিটি ক্লায়েন্টকে তার প্রয়োগের প্রতিটি পরিবর্তনের সাথে খাপ খাইয়ে নিতে হবে না এটি কী ত্রুটিগুলি ফেলতে পারে তা সহ ফাংশন। আপনি এমন কোড চান যা আপনার ফাংশনকে এমন পরিবর্তনের জন্য স্থিতিস্থাপক হিসাবে কল করে।

যেহেতু আপনার ফাংশন এটি কোন ধরণের ত্রুটি নিক্ষেপ করতে পারে না (বা ভবিষ্যতে নিক্ষেপ করতে পারে), তাই catchযে ব্লকগুলি এটিকে ত্রুটিযুক্ত করে তা কী ধরণের ত্রুটি ফেলতে পারে তা জানে না। সুতরাং, আপনি যে ত্রুটি সম্পর্কে জানতেন সেগুলি পরিচালনা করার পাশাপাশি, আপনি catchযে সার্বজনীন বিবৃতি দিয়ে যা করেন না সেগুলি পরিচালনা করতে হবে - এইভাবে যদি আপনার ফাংশনটি ভবিষ্যতে এটির ত্রুটিগুলির সেটকে পরিবর্তন করে, কলকারীরা এখনও এটি ধরে ফেলবে ত্রুটি।

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it \(sandwich)")
} catch SandwichError.NotMe {
    print("Not me error")
} catch SandwichError.DoItYourself {
    print("do it error")
} catch let error {
    print(error.localizedDescription)
}

তবে আসুন না থামি। এই স্থিতিস্থাপকতা সম্পর্কে আরও কিছু ভাবুন। আপনি নিজের স্যান্ডউইচকে যেভাবে ডিজাইন করেছেন, যেখানে আপনি সেগুলি ব্যবহার করেন না কেন সেখানে আপনাকে ত্রুটি বর্ণনা করতে হবে। এর অর্থ হ'ল আপনি যখনই ত্রুটির কেসগুলির সেট পরিবর্তন করেন, আপনাকে সেগুলিকে ব্যবহার করা প্রতিটি জায়গা পরিবর্তন করতে হবে ... খুব মজাদার নয়।

আপনার নিজের ত্রুটি প্রকারের সংজ্ঞা দেওয়ার পিছনে ধারণাটি হ'ল আপনাকে সেই জাতীয় জিনিসকে কেন্দ্রিয় করে তোলা। আপনি descriptionআপনার ত্রুটিগুলির জন্য কোনও পদ্ধতি নির্ধারণ করতে পারেন :

extension SandwichError: CustomStringConvertible {
    var description: String {
        switch self {
            case NotMe: return "Not me error"
            case DoItYourself: return "Try sudo"
        }
    }
}

এবং তারপরে আপনার ত্রুটি পরিচালনার কোডটি আপনার ত্রুটির ধরণটি নিজেই বর্ণনা করতে বলতে পারে - এখন যেখানেই আপনি ত্রুটিগুলি পরিচালনা করেন সে জায়গাগুলি একই কোড ব্যবহার করতে পারে এবং ভবিষ্যতে সম্ভাব্য ত্রুটি কেসগুলিও পরিচালনা করতে পারে।

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it \(sandwich)")
} catch let error as SandwichError {
    print(error.description)
} catch {
    print("i dunno")
}

এটি ত্রুটি প্রকারের (বা তাদের উপর এক্সটেনশানগুলি) ত্রুটিগুলির প্রতিবেদন করার অন্যান্য উপায়গুলিকে সমর্থন করারও পথ প্রশস্ত করে - উদাহরণস্বরূপ, আপনার ত্রুটি টাইপের একটি এক্সটেনশান থাকতে পারে যা UIAlertControllerকোনও আইওএস ব্যবহারকারীর কাছে ত্রুটিটি রিপোর্ট করার জন্য কীভাবে উপস্থাপন করতে পারে তা জানে ।


1
@ ইরিস্টার: আপনি কি সত্যিই সংকলক ত্রুটিটি পুনরুত্পাদন করতে পারবেন? মূল কোডটি আমার জন্য ত্রুটি বা সতর্কতা ছাড়াই সংকলন করে। এবং যদি কোনও ছাড়ানো ব্যতিক্রম ছুঁড়ে ফেলা হয় তবে প্রোগ্রামটি বন্ধ হয়ে যায়- error caught in main()সুতরাং আপনি যা বলেছেন সমস্ত বুদ্ধিমান মনে হচ্ছে, আমি সেই আচরণটি পুনরুত্পাদন করতে পারব না।
মার্টিন আর

5
আপনি কীভাবে কোনও এক্সটেনশনে ত্রুটি বার্তাগুলি আলাদা করেছেন তা পছন্দ করুন। আপনার কোড পরিষ্কার রাখার সত্যিই দুর্দান্ত উপায়! দুর্দান্ত উদাহরণ!
Konrad77

এটি অত্যন্ত প্রস্তাবিত যে আপনি বাধ্যতামূলক - tryউত্পাদন কোডে প্রকাশটি ব্যবহার এড়িয়ে চলুন কারণ এটি রানটাইম ত্রুটির কারণ হতে পারে এবং আপনার অ্যাপ্লিকেশনটিকে ক্র্যাশ করতে পারে
ওতার

@ ওটার সাধারণভাবে চিন্তাভাবনা করুন তবে এটি সামান্য বিষয় - উত্তরটি ব্যবহার করে (বা ব্যবহার না করে) সম্বোধন করে না try!। এছাড়াও, তর্কসাপেক্ষে বৈধ, "নিরাপদ" ব্যবহারের ক্ষেত্রে সুইফটের বিভিন্ন "ফোর্স" ক্রিয়াকলাপের জন্য (আনপ্রেপ করুন, চেষ্টা করুন, ইত্যাদি) এমনকি প্রোডাকশন কোডও রয়েছে - পূর্বশর্ত বা কনফিগারেশনের মাধ্যমে যদি আপনি নির্ভরযোগ্যভাবে ব্যর্থতার সম্ভাবনাটি সরিয়ে ফেলে থাকেন তবে এটি হতে পারে ত্রুটি-হ্যান্ডলিং কোডটি অকেটেস্টেবলের চেয়ে তাত্ক্ষণিক ব্যর্থতায় শর্ট সার্কিটের কাছে আরও যুক্তিসঙ্গত হন।
রিক্সার

আপনার যদি প্রয়োজন কেবল ত্রুটি বার্তা প্রদর্শন করা হয় তবে সেই যুক্তিটিকে SandwichErrorশ্রেণীর ভিতরে রেখে দেওয়া অর্থপূর্ণ। তবে, বেশিরভাগ ত্রুটির জন্য আমি সন্দেহ করি, ত্রুটিটি পরিচালনা করার লজিকটি এতটা আবদ্ধ হতে পারে না। এর কারণ এটির জন্য সাধারণত কলারের প্রসঙ্গে (পুনরুদ্ধার করা, বা পুনরায় চেষ্টা করা, বা ব্যর্থতার উজানে রিপোর্ট করা ইত্যাদি) জ্ঞান প্রয়োজন। অন্য কথায়, আমি সন্দেহ করি যে সর্বাধিক সাধারণ প্যাটার্নটি যাইহোক নির্দিষ্ট ত্রুটির ধরণের সাথে মিলে যেতে হবে।
সর্বোচ্চ

29

আমি সন্দেহ করি এটি এখনও সঠিকভাবে প্রয়োগ করা হয়নি। সুইফট প্রোগ্রামিং গাইড স্পষ্টভাবে পরোক্ষভাবে যে কম্পাইলার 'একটি সুইচ বিবৃতি মত' সম্পূর্ণ ম্যাচ আবিষ্কার করতে পারেন বলে মনে হয়। এটি পরিশ্রমী হওয়ার জন্য কোনও জেনারেল প্রয়োজনের কোনও উল্লেখ করে না catch

আপনি আরও লক্ষ্য করবেন যে ত্রুটিটি tryলাইনের মধ্যে রয়েছে, ব্লকের প্রান্তে নয়, অর্থাত্ কোনও পর্যায়ে সংকলকটি নির্ধারণ করতে সক্ষম হবে tryযে ব্লকের কোন বিবৃতিটি নিয়ন্ত্রণহীন ব্যতিক্রম প্রকার রয়েছে।

ডকুমেন্টেশন যদিও কিছুটা অস্পষ্ট। আমি 'সুইফটে নতুন কী' ভিডিওটি দিয়ে স্কিম করেছি এবং কোনও চিহ্ন খুঁজে পাইনি; আমি চেষ্টা চালিয়ে যাব।

হালনাগাদ:

আমরা এখন ত্রুটি টাইপ অনুমানের কোনও ইঙ্গিত ছাড়াই বিটা 3 এ চলেছি। আমি এখন বিশ্বাস করি এটি যদি কখনও পরিকল্পনা করা হয় (এবং আমি এখনও মনে করি এটি কোনও পর্যায়ে ছিল), প্রোটোকল এক্সটেনশনের গতিশীল প্রেরণ সম্ভবত এটি বন্ধ করে দিয়েছে।

বিটা 4 আপডেট:

এক্সকোড 7 বি 4 ডক মন্তব্য সমর্থন যুক্ত করেছে Throws:, যা "কোন ত্রুটি নিক্ষেপ করা যেতে পারে এবং কেন তা নথিভুক্ত করতে ব্যবহার করা উচিত"। আমার ধারণা এটি এপিআই গ্রাহকদের ত্রুটি যোগাযোগ করার জন্য অন্তত কিছু ব্যবস্থা সরবরাহ করে। যখন আপনার ডকুমেন্টেশন আছে তখন কার টাইপ সিস্টেমের প্রয়োজন!

আরেকটি আপডেট:

কিছু সময় কাটানোর স্বয়ংক্রিয় জন্য প্রত্যাশী পর ErrorTypeইনফারেন্স এবং কাজ কি সীমাবদ্ধতা মডেলটির হবে, আমি আমার মন পরিবর্তন করেছি - এই আমি কি আশা অ্যাপল কার্যকরী পরিবর্তে হয়। মূলত:

// allow us to do this:
func myFunction() throws -> Int

// or this:
func myFunction() throws CustomError -> Int

// but not this:
func myFunction() throws CustomErrorOne, CustomErrorTwo -> Int

তবুও আরেকটি আপডেট

অ্যাপল এর ত্রুটি পরিচালনার যৌক্তিকতা এখন এখানে উপলব্ধ । দ্রুত-বিবর্তন মেলিং তালিকায় কিছু আকর্ষণীয় আলোচনাও হয়েছে । মূলত, জন ম্যাককাল টাইপ করা ত্রুটির বিরোধী কারণ তিনি বিশ্বাস করেন যে বেশিরভাগ গ্রন্থাগার যাইহোক জেনেরিক ত্রুটি মামলা সহ শেষ হয়ে যাবে, এবং টাইপ করা ত্রুটিগুলি বয়লারপ্লেট বাদে কোডে বেশি যোগ করার সম্ভাবনা নেই (তিনি 'এক্সপ্রেশনাল ব্লাফ' শব্দটি ব্যবহার করেছিলেন)। ক্রিস ল্যাটারার বলেছিলেন যে যদি এই স্নিগ্ধতা মডেলটি নিয়ে কাজ করতে পারে তবে তিনি সুইফট 3-এ টাইপ করা ত্রুটিগুলি করতে পারেন।


লিঙ্কগুলির জন্য ধন্যবাদ। জন যদিও রাজি হননি: "অনেক লাইব্রেরিতে 'অন্যান্য ত্রুটি' টাইপ অন্তর্ভুক্ত রয়েছে" এর অর্থ এই নয় যে প্রত্যেককে একটি "অন্যান্য ত্রুটি" ধরণের প্রয়োজন।
ফ্রাঙ্কলিন ইউ

সুস্পষ্ট কাউন্টারটি হ'ল কোনও ফাংশন কী ধরণের ত্রুটি ফেলবে তা জানার সহজ উপায় নেই, যতক্ষণ না এটি বিকাশকারীকে সমস্ত ত্রুটিগুলি ধরতে বাধ্য করে এবং যথাসম্ভব সর্বোত্তমভাবে পরিচালনা করার চেষ্টা করে। এটি বরং স্পষ্ট বলে মনে হচ্ছে বিরক্তিকর be
উইলিয়াম টি ফ্রোগার্ড

4

আপনার কেস স্টেটমেন্টটি সমস্ত কেসকে কাভার করছে না বলে সুইফ্ট চিন্তিত, এটির সমাধানের জন্য আপনাকে একটি ডিফল্ট কেস তৈরি করতে হবে:

do {
    let sandwich = try makeMeSandwich(kitchen)
    print("i eat it \(sandwich)")
} catch SandwichError.NotMe {
    print("Not me error")
} catch SandwichError.DoItYourself {
    print("do it error")
} catch Default {
    print("Another Error")
}

2
তবে কি সেই বিশ্রী নয়? আমার কাছে কেবল দুটি মামলা রয়েছে এবং এগুলির সবকটি catchবিবৃতিতে তালিকাভুক্ত ।
মোস্তফা

2
যোগ করার জন্য বর্ধিতকরণের অনুরোধের জন্য এখনই উপযুক্ত সময় func method() throws(YourErrorEnum), অথবা এমন throws(YourEnum.Error1, .Error2, .Error3)কি আপনি জানেন কী নিক্ষেপ করা যেতে পারে
ম্যাথিয়াস বাউচ

8
ডাব্লুডাব্লুডিসির একটি সেশনে সুইফ্ট সংকলক দলটি পরিষ্কার করে দিয়েছিল যে তারা 'জাওয়ার মতো' সমস্ত সম্ভাব্য ত্রুটির পেডেন্টিক তালিকা চায় না।
স্যাম

4
কোনও ডিফল্ট / ডিফল্ট ত্রুটি নেই; অন্যান্য পোস্টারগুলি যেমনটি দেখিয়েছে তেমন একটি ফাঁকা ধরা
leave leave

1
@ আইকারো যা আমাকে সুরক্ষিত করে না; ভবিষ্যতে যদি আমি "অ্যারেতে একটি নতুন এন্ট্রি যোগ করি", সমস্ত সংক্রামিত ক্যাচ ক্লজ আপডেট না করায় কম্পাইলারটি আমার দিকে চিত্কার করে।
ফ্র্যাঙ্কলিন ইউ

3

কোনও ফাংশন ফেলতে পারে এমন ধরণের অভাবের কারণে আমিও হতাশ হয়েছি, তবে আমি এখন এটি @ ক্রিস্টারের কাছে ধন্যবাদ পেয়েছি এবং এটির সংক্ষেপে এইভাবে করব: আসুন আমরা বলি যে আমরা কোনও ফাংশন নিক্ষেপ করার ধরণটি নির্দিষ্ট করতে পারি, আমাদের এরকম কিছু থাকবে:

enum MyError: ErrorType { case ErrorA, ErrorB }

func myFunctionThatThrows() throws MyError { ...throw .ErrorA...throw .ErrorB... }

do {
    try myFunctionThatThrows()
}
case .ErrorA { ... }
case .ErrorB { ... }

সমস্যাটি হ'ল আমরা মাই ফাংশনট্যাটস-এ কিছু পরিবর্তন না করলেও, আমরা যদি কেবল মাইআররে একটি ত্রুটি মামলা যুক্ত করি:

enum MyError: ErrorType { case ErrorA, ErrorB, ErrorC }

আমরা খারাপ হয়েছি কারণ আমাদের চেষ্টা / চেষ্টা / ধরা এখন আর পরিস্ফুট নয়, সেই সাথে অন্য কোনও জায়গাতে যেখানে আমরা মাইআরর ফেলে দেয় এমন ফাংশন বলেছি


3
নিশ্চিত না যে আমি কেন আপনার ক্ষতিগ্রস্থ হয়েছি তা অনুসরণ করছি। আপনি একটি সংকলক ত্রুটি পেয়েছেন, যা আপনি চান তাই না? আপনি যদি এনাম কেস যুক্ত করেন তবে স্টেটমেন্টগুলিতে স্যুইচ করার জন্য এটিই ঘটে।
স্যাম

এক অর্থে আমার কাছে এটি বেশিরভাগই মনে হয়েছিল যে এটি ত্রুটি এনামগুলি / ডু কেসের ক্ষেত্রে ঘটবে, তবে এটি ঠিক যেমন এনামস / স্যুইচে ঘটবে ঠিক তেমনি আপনি ঠিক বলেছেন। আমি এখনও নিজেকে বোঝানোর চেষ্টা করছি যে আমরা কী নিক্ষেপ করি তা টাইপ না করা অ্যাপলের পছন্দটি ভাল, তবে আপনি এই বিষয়ে আমাকে সাহায্য করেন না! ^^
গ্রেগ 3z

নিক্ষিপ্ত ত্রুটিগুলি ম্যানুয়ালি টাইপ করা অ-তুচ্ছ মামলায় একটি বিরাট গোলমাল হিসাবে শেষ হবে। প্রকারগুলি হ'ল ফাংশনটির মধ্যে সমস্ত থ্রো এবং চেষ্টা করার বিবৃতি থেকে সমস্ত সম্ভাব্য ত্রুটির একটি ইউনিয়ন। আপনি যদি ম্যানুয়ালি ত্রুটি এনামগুলি বজায় রাখেন তবে এটি বেদনাদায়ক হবে। একজন catch {}যে ব্লক নীচে যদিও তর্কসাপেক্ষে খারাপ। আমি আশা করি যে সংকলকটি শেষ পর্যন্ত ত্রুটি প্রকারের স্বয়ংক্রিয়ভাবে অনুমান করবে যেখানে এটি পারে তবে আমি নিশ্চিত করতে সক্ষম হইনি।
স্যাম

আমি সম্মত হই যে সংকলকটি তাত্ত্বিকভাবে কোনও ত্রুটির প্রকারের ত্রুটির প্রকারগুলি নির্ধারণ করতে সক্ষম হওয়া উচিত। তবে আমি মনে করি দেবগণের স্পষ্টতই সেগুলি স্পষ্ট করে লিখলে তা বোঝা যায়। আপনি যে-অপ্রয়োজনীয় বিষয়ে কথা বলছেন তাতে বিভিন্ন ত্রুটির প্রকারের তালিকাটি আমার কাছে ঠিক বলে মনে হয়: func f () ত্রুটি টাইপ, ত্রুটি টাইপবি th gre
গ্রেগ 3z

এখানে অবশ্যই একটি বড় অংশ অনুপস্থিত রয়েছে যে ত্রুটি প্রকারের (ডক্ট মন্তব্য ব্যতীত) যোগাযোগ করার কোনও ব্যবস্থা নেই। তবে সুইফট টিম বলেছে যে তারা ত্রুটির ধরণের সুস্পষ্ট তালিকা চায় না। আমি নিশ্চিত যে অতীতে জাভা চেক করা ব্যতিক্রমগুলি নিয়ে বেশিরভাগ লোকেরা সম্মত হবে 😀
স্যাম

1
enum NumberError: Error {
  case NegativeNumber(number: Int)
  case ZeroNumber
  case OddNumber(number: Int)
}

extension NumberError: CustomStringConvertible {
         var description: String {
         switch self {
             case .NegativeNumber(let number):
                 return "Negative number \(number) is Passed."
             case .OddNumber(let number):
                return "Odd number \(number) is Passed."
             case .ZeroNumber:
                return "Zero is Passed."
      }
   }
}

 func validateEvenNumber(_ number: Int) throws ->Int {
     if number == 0 {
        throw NumberError.ZeroNumber
     } else if number < 0 {
        throw NumberError.NegativeNumber(number: number)
     } else if number % 2 == 1 {
         throw NumberError.OddNumber(number: number)
     }
    return number
}

এখন বৈধতা নম্বর:

 do {
     let number = try validateEvenNumber(0)
     print("Valid Even Number: \(number)")
  } catch let error as NumberError {
     print(error.description)
  }

-2

এটির মতো এনাম তৈরি করুন:

//Error Handling in swift
enum spendingError : Error{
case minus
case limit
}

এর মতো পদ্ধতি তৈরি করুন:

 func calculateSpending(morningSpending:Double,eveningSpending:Double) throws ->Double{
if morningSpending < 0 || eveningSpending < 0{
    throw spendingError.minus
}
if (morningSpending + eveningSpending) > 100{
    throw spendingError.limit
}
return morningSpending + eveningSpending
}

এখন চেক ত্রুটি আছে কি নেই এবং এটি পরিচালনা করুন:

do{
try calculateSpending(morningSpending: 60, eveningSpending: 50)
} catch spendingError.minus{
print("This is not possible...")
} catch spendingError.limit{
print("Limit reached...")
}

সিগার নেই তবে সিগার নেই। ব্যবধানটি ঠিক করার চেষ্টা করুন এবং এনাম উট কেস তৈরি করুন।
আলেক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.