Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Swift Zoomin' #8
Search
Yuta Koshizawa
October 23, 2021
Programming
730
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Swift Zoomin' #8
Yuta Koshizawa
October 23, 2021
More Decks by Yuta Koshizawa
See All by Yuta Koshizawa
Heart of Swift Concurrency
koher
0
1.4k
How Swift's Type System Guides AI Agents
koher
0
490
Swift Updates - Learn Languages 2025
koher
2
840
Swiftのstructとイミュータビリティ
koher
4
820
Swift 6のTyped throwsとSwiftにおけるエラーハンドリングの全体像を学ぶ
koher
4
6.5k
Swift Concurrency時代のiOSアプリの作り方
koher
15
9.9k
async/awaitやactorでiOSアプリ開発がどう変わるか Before & Afterの具体例で学ぶ
koher
9
8k
Swift Language Updates - Learn Languages 2021
koher
8
1.9k
先取り! Swift 6 の async/await
koher
15
4.2k
Other Decks in Programming
See All in Programming
ソニーのクラウド共通基盤の変遷とAI時代の開発スタイルに合わせた進化 / The Journey of Sony’s Common Cloud Platform and Its Evolution for AI-Native Development
kenjiyoneyama
0
270
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
8.5k
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.7k
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.6k
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.9k
Simple Storage Service(S3) is not simple
iwatsukayura
0
290
なぜCTOを降りてFDEを選んだのか?〜なぜプロダクト企業がFDEで顧客の現場に踏み込むのか〜
gonta
1
210
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
790
半永久的に提供し続けられるプライベートクラウドを目指して ― 利用者の認知負荷を抑えるAPI抽象化とハードウェア世代交代の基盤設計
tomokon
0
500
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
2
650
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
35
17k
npm との違いを手がかりにGo の依存管理を理解したい
optim
0
610
Featured
See All Featured
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Code Reviewing Like a Champion
maltzj
529
40k
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.2k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
590
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Automating Front-end Workflow
addyosmani
1369
210k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
260
Between Models and Reality
mayunak
4
500
Transcript
Swi$ Zoomin' #8 Actor ϋϯζΦϯ
Actor ͱ
ɾɾɾͷલʹ
Actor async/await Λଟ༻͢Δ
async/await ͷ؆୯ͳ෮श
ίʔϧόοΫʹΑΔඇಉظؔ // એݴ func downloadData(from url: URL, completion: @escaping (Data)
-> Void) // ར༻ downloadData(from: url) { data in // data Λ͏ॲཧ }
async/await ʹΑΔඇಉظؔ // એݴ func downloadData(from url: URL) async ->
Data // ར༻ let data = await downloadData(from: url) // data Λ͏ॲཧ
ίʔϧόοΫʹΑΔඇಉظؔ // એݴ func downloadData(from url: URL, completion: @escaping (Result<Data,
Error>) -> Void) // ར༻ downloadData(from: url) { result in do { let data = try result.get() // data Λ͏ॲཧ } catch { /* ΤϥʔϋϯυϦϯά */ } }
async/await ʹΑΔඇಉظؔ // એݴ func downloadData(from url: URL) async throws
-> Data // ར༻ do { let data = try await downloadData(from: url) // data Λ͏ॲཧ } catch { /* ΤϥʔϋϯυϦϯά */ }
࿅श༻ϦϙδτϦ h"ps:/ /github.com/koher/swi4-zoomin-8
Q1: downloadData ίʔϧόοΫͰ݁ՌΛฦ͢ downloadData ͕ؔ Download.swi, ʹ࣮͞Ε͍ͯ·͢ɻ async/await Λར༻͠ ͯɺΓͰ݁ՌΛฦ͢
downloadData ؔΛ࣮ͯ͠Լ͞ ͍ɻ ! iOS 15 ͔Β URLSession ʹՃ͞Εͨ࣍ͷϝιου͕ʹཱ ͪ·͢ɻ1 func data(from url: URL) async throws -> (Data, URLResponse) 1 h$ps:/ /developer.apple.com/documenta6on/founda6on/urlsession/3767353-data
Q1: ղྫ
async ؔ async ؔͷதͰ͔͠ݺͼग़ͤͳ͍ func foo() async func bar() async
{ await foo() // ✅ OK }
async ؔ async ؔͷதͰ͔͠ݺͼग़ͤͳ͍ func foo() async func bar() {
await foo() // ⛔ NG }
async ؔ async ؔͷதͰ͔͠ݺͼग़ͤͳ͍ func foo() async func bar() async
{ await foo() // ✅ OK } func baz() async { await bar() // ✅ OK } ...
async ؔΛ࠷ॳʹݺͼग़͢ͱ͖ʁ
ಉظ͔ؔΒͷ async ؔͷݺͼग़͠ override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated)
await foo() // ⛔ NG }
ಉظ͔ؔΒͷ async ؔͷݺͼग़͠ override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated)
Task { await foo() // ✅ OK } }
ಉظ͔ؔΒͷ async ؔͷݺͼग़͠ override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated)
Task(operation: { await foo() // ✅ OK }) }
Task.init 2 @discardableResult init( priority: TaskPriority? = nil, operation: @escaping
@Sendable () async throws -> Success ) 2 h$ps:/ /developer.apple.com/documenta6on/swi9/task/3856790-init
Q2: UserViewController.viewDidAppear UserViewController User ͷใΛऔಘͯ͠දࣔ͢Δ View Controller Ͱ͢ɻ viewDidAppear
ͷதͰ downloadData ؔΛ ͍ɺ User ͱΞΠίϯΛऔಘͯ͠දࣔ͠·͢ɻ ͜ΕΛɺ async/await Ͱ࣮͞Εͨ downloadData ؔΛར ༻ͯ͠࠶࣮ͯ͠Լ͍͞ɻ
Q2: ղྫ
Actor ͱ
Actor ΫϥεʹࣅͨࢀরܕͰɺσʔλڝ߹ Λ͙ͨΊͷϘΠϥʔϓϨʔτ͕ෆཁʹͳ Δɻ ͦͷͨΊɺίʔυ͕؆͔ܿͭ҆શʹͳΔɻ
σʔλڝ߹ͱ
Χϯλʔͷσʔλڝ߹ final class Counter { private var count: Int =
0 func increment() -> Int { count += 1 return count } }
Χϯλʔͷσʔλڝ߹ let counter: Counter = .init() Task { print(counter.increment()) //
? } Task { print(counter.increment()) // ? }
Χϯλʔͷσʔλڝ߹ let counter: Counter = .init() Task { print(counter.increment()) //
1 } Task { print(counter.increment()) // 2 }
Χϯλʔͷσʔλڝ߹ let counter: Counter = .init() Task { print(counter.increment()) //
2 } Task { print(counter.increment()) // 1 }
Χϯλʔͷσʔλڝ߹ let counter: Counter = .init() Task { print(counter.increment()) //
2 } Task { print(counter.increment()) // 2 }
Χϯλʔͷσʔλڝ߹ final class Counter { private var count: Int =
0 func increment() -> Int { count += 1 Thread.sleep(forTimeInterval: 1.0) return count } }
Χϯλʔͷσʔλڝ߹ let counter: Counter = .init() Task { print(counter.increment()) //
1 } Task { print(counter.increment()) // 1 }
final class Counter { private var count: Int = 0
func increment() -> Int { let count = self.count Thread.sleep(forTimeInterval: 1.0) self.count = count + 1 return self.count } }
σʔλڝ߹ͷରԠํ๏ • ϩοΫ • ʢ DispatchQueue ͷʣγϦΞϧΩϡʔ
γϦΞϧΩϡʔʹΑΔσʔλڝ߹ͷղফ final class Counter { private let queue: DispatchQueue =
.init(label: "Counter") private var count: Int = 0 func increment(completion: @escaping (Int) -> Void) { queue.async { [self] in count += 1 completion(count) } } }
γϦΞϧΩϡʔʹΑΔσʔλڝ߹ͷղফ let counter: Counter = .init() Task { counter.increment {
print($0) } // 1 } Task { counter.increment { print($0) } // 2 }
γϦΞϧΩϡʔʹΑΔσʔλڝ߹ͷղফ final class Counter { private let queue: DispatchQueue =
.init(label: "Counter") private var count: Int = 0 func increment(completion: @escaping (Int) -> Void) { queue.async { [self] in count += 1 completion(count) } } }
σʔλڝ߹ͷରԠํ๏ • ϩοΫ • ʢ DispatchQueue ͷʣγϦΞϧΩϡʔ • Actor
Actor ʹΑΔσʔλڝ߹ͷղফ final class Counter { private var count: Int
= 0 func increment() -> Int { count += 1 return count } }
Actor ʹΑΔσʔλڝ߹ͷղফ actor Counter { private var count: Int =
0 func increment() -> Int { count += 1 return count } }
Actor ʹΑΔσʔλڝ߹ͷղফ let counter: Counter = .init() Task { print(await
counter.increment()) } Task { print(await counter.increment()) }
Q3: BankAccount.deposit ࣍ͷΑ͏ͳ BankAccount ΫϥεΛ࣮͠ɺฒߦʹ༬ۚ͢Δ͜ͱ Ͱσʔλڝ߹͕ൃੜ͢Δ͜ͱΛ֬ೝͯ͠Լ͍͞ɻͦͷޙɺ BankAccount Λ actor ʹมߋ͠ɺσʔλڝ߹͕ࢭ͞ΕΔ͜ͱ
Λ֬ೝͯ͠Լ͍͞ɻ final class BankAccount { // ۜߦޱ࠲ var balance: Int = 0 // ༬ۚߴ func deposit(_ amount: Int) -> Int // ೖۚʢΓߴʣ }
Q3: ղྫ
Actor ͷಉҰΠϯελϯεͰͷϝιουݺͼग़͠ actor A { func foo() { ... }
func bar() { foo() // ಉظ } } await foo() // ඇಉظ
Q4: BankAccount.getInterest BankAccount ʹ getInterest ϝιουΛ࣮ͯ͠Լ͍͞ɻ getInterest ϝιου࣍ͷΑ͏ͳγάωνϟΛ࣋ͪɺҾͰ རΛड͚औΓɺͦΕΛݩʹརଉΛܭࢉͯ͠༬ۚߴΛมಈͤ͞ ্ͨͰɺ৽͍͠༬ۚߴΛฦ͢ͷͱ͠·͢ɻͨͩ͠ɺ༬ۚߴ
ͷมಈʹ deposit ϝιουΛར༻͢Δͷͱ͠·͢ɻ func getInterest(with rate: Double) -> Int
Q4: ղྫ
Actor ͷΠϯελϯεؒͰͷϝιουݺͼग़͠ actor A { func foo() { ... }
} actor B { func bar(a: A) async { await a.foo() // ඇಉظ } }
Actor ͷΠϯελϯεؒͰͷϝιουݺͼग़͠ actor A { func foo() { ... }
func bar(a: A) async { foo() // ಉظ await a.foo() // ඇಉظ } }
Actor ͷΠϯελϯεؒͰͷϝιουݺͼग़͠ actor A { func foo() { ... }
func bar(a: A) async { self.foo() // ಉظ await a.foo() // ඇಉظ } }
Actor ͷΠϯελϯεؒͰͷϝιουݺͼग़͠ actor A { func foo() { ... }
func bar(a: A) async { foo() // ಉظ await a.foo() // ඇಉظ } }
Q5: BankAccount.transfer BankAccount ʹ࣍ͷೋͭͷϝιουΛՃͯ͠Լ͍͞ɻ • ޱ࠲͔Βग़ۚ͢ΔͨΊͷ withdraw ϝιου • ޱ࠲ؒͰૹۚ͢ΔͨΊͷ
transfer ϝιου // ߴ͕Γͳ͍߹ΤϥʔΛ throw func withdraw(_ amount: Int) throws -> Int // Γߴ func transfer(_ amount: Int, to account: BankAccount) async throws
Q5: ղྫ
Sendable
Sendable 3 actor ڥքΛ͑ͯΓͱΓͰ͖Δ͜ͱΛද͢ϓϩτίϧ 3 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0302-concurrent-value-and-concurrent- closures.md
final class User { let id: ID var name: String
var age: Int ... }
actor A { let user: User = ... } let
a: A = ... Task { let user = await a.user user.age += 1 // ⛔ } Actor ͷΩϡʔͷ֎Ͱ Actor ͷ෦ঢ়ଶΛมߋͰ͖ͯ͠·͏
final class User: Sendable { let id: ID var name:
String var age: Int ... } ⛔ ࢀরܕͰ var ϓϩύςΟΛ࣋ͭͷͰίϯύΠϧΤϥʔ
struct User { let id: ID var name: String var
age: Int ... } public Ͱͳ͍ܕ҉తʹద߹4 4 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0302-concurrent-value-and-concurrent- closures.md#implicit-structenum-conformance-to-sendable
public struct User: Sendable { public let id: ID public
var name: String public var age: Int ... } public ͩͱ໌ࣔతʹద߹ͤ͞Δඞཁ͋Γ
struct User: Sendable { let id: ID var name: NSString
var age: Int ... } ⛔ Sendable Ͱͳ͍ϝϯόʔΛ࣋ͭͷͰίϯύΠϧΤϥʔ
final class User: Sendable { let id: ID let name:
String let age: Int ... } ✅ ࢀরܕͰΠϛϡʔλϒϧͳΒ OK
final class User: Sendable { let id: ID let firstName:
String let familyName: String let age: Int var name: String { "\(firstName) \(familyName)" } ... } ✅ Computed Property Λ͍࣋ͬͯͯΠϛϡʔλϒϧͳͷͰ OK
final class User: Sendable { let id: ID let firstName:
String let familyName: String let age: Int private var _name: String? // var name: String { if _name == nil { _name = "\(firstName) \(familyName)" } return _name! } ... }
final class User: @unchecked Sendable { let id: ID let
firstName: String let familyName: String let age: Int private var _name: String? // var name: String { if _name == nil { _name = "\(firstName) \(familyName)" } return _name! } ... }
actor Counter { private var count: Int = 0 func
increment() -> Int { count += 1 return count } } actor ҉తʹ Sendable ʹద߹
ϓϩτίϧʹద߹ͤ͞ΒΕͳ͍߹ʁ
actor Foo { func bar(_ f: (String) -> Int) {
// // ... } }
actor Foo { func bar(_ f: @Sendable (String) -> Int)
{ // // ... } } Ϋϩʔδϟϓϩτίϧʹద߹Ͱ͖ͳ͍ͷͰ @Sendable Λ͏
final class User { var name: String ... } let
user: User = ... Task { let name = user.name // } @Sendable Ϋϩʔδϟ Sendable ͳ͔͠ΩϟϓνϟͰ͖ͳ ͍ʢ Task.init ʹ͢Ϋϩʔδϟ @Sendable ʣ
var a = 42 Task { print(a) // ⛔ }
@Sendable ΫϩʔδϟมΛΩϟϓνϟͰ͖ͳ͍
var a = 42 Task { [a] in print(a) //
✅ } by-value ΩϟϓνϟՄೳ
None
Actor-isolated Context ͷҾܧ͗
@nonescaping, non-@Sendable ʢ context ΛҾ͖ܧ͙ʣ actor A { func foo(values:
[Int]) { // A values.forEach { value in // A } } }
@escaping, non-@Sendableʢ context ΛҾ͖ܧ͙ʣ actor A { func foo(value: Int)
{ // A let square: (Int) -> Int = { // @escaping // A $0 * $0 } print(square(value)) print(square(square(value))) } }
@Sendable ʢ context ΛҾ͖ܧ͕ͳ͍ʣ actor A { func foo() {
// A let foo: Foo = .init() // Foo: Sendable DispatchQueue.global().async { [foo] in // @Sendable // not A foo.value = 2 } foo.value = 3 print(foo.value) } } ※ͨͩ͠ɺ Swi% 5.5 ݱࡏ @Sendable Ͱͳ͍
Task.initʢ context ΛҾ͖ܧ͙ʣ actor A { func foo() { //
A Task { // @Sendable // A } } }
@_inheritActorContext extension Task where Failure == Never { ... @discardableResult
@_alwaysEmitIntoClient public init( priority: TaskPriority? = nil, @_inheritActorContext @_implicitSelfCapture operation: __owned @Sendable @escaping () async -> Success ) { ... } } 10 h%ps:/ /github.com/apple/swi7/blob/main/stdlib/public/Concurrency/Task.swi7
Task.initʢ context ΛҾ͖ܧ͙ʣ actor A { func foo() { //
A Task { // @Sendable // A } } }
Task.detachedʢ context ΛҾ͖ܧ͕ͳ͍ʣ actor A { func foo() { //
A Task.detached { // @Sendable // not A } } }
Actor-isolated Context ͷҾܧ͗ͷؔ͢Δ swi2-developers-japan ͰͷΓͱΓ11 11 h$ps:/ /discord.com/channels/291054398077927425/291054454793306112/890858321693769748
UserViewController
None
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Task { do
{ // User ͷ JSON ͷऔಘ let url: URL = ... let data = try await downloadData(from: url) ... // View ͷө iconImageView.image = iconImage } catch { // ΤϥʔϋϯυϦϯά print(error) } } }
View Controller ʹϩδοΫΛॻ͖ͨ͘ͳ͍
ViewModel తͳΫϥεΛಋೖ
UserViewState final class UserViewState { let id: User.ID @Published private(set)
var user: User? @Published private(set) var iconImage: UIImage? init(id: User.ID) { self.id = id } }
Q6: UserViewState UserViewState ʹ loadUser ϝιουΛՃ͠ɺϢʔβʔ͓Α ͼϢʔβʔΞΠίϯΛऔಘ͢ΔίʔυΛ UserViewController ͔Βͯ͠Լ͍͞ɻ UserViewController
ʹ UserViewState ܕͷ state ϓϩύςΟΛ࣋ͨͤɺ state ͷঢ় ଶΛ View ʹө͢ΔΑ͏ʹͯ͠Լ͍͞ɻͳ͓ɺ͜ͷ Actor ʹؔ͋Γ·ͤΜɻ ! state.user Ͱͳ͘ state.$user ͱॻ͘͜ͱͰɺ user Λ Publisher ͱͯ͠औಘ͢Δ͜ͱ͕Ͱ͖·͢ɻ
Q6: ղྫ
loadUser Λฒߦʹݺͼग़ͯ͠େৎ͔ʁ
loadUser Ͱى͜ΓಘΔσʔλڝ߹ let data = try await downloadData(from: url) let
user = try JSONDecoder().decode(User.self, from: data) self.user = user // ͕͜͜ಉ࣌ʹ࣮ߦ͞ΕΔͱʁ
UserViewState Λ actor ʹ͍ͨ͠
Q7: actor UserViewState UserViewState Λ Actor ʹͯ͠Լ͍͞ɻ
Q7: ղྫ
Swi$ Concurrency Λͬͯ Publisher ΛߪಡͰ͖Δ
Publisher.values 5 for await value in publisher.values { ... }
5 h$ps:/ /developer.apple.com/documenta6on/combine/publisher/values-1dm9r
AsyncSequence 6 protocol AsyncSequence { associatedtype AsyncIterator: AsyncIteratorProtocol where AsyncIterator.Element
== Element associatedtype Element func makeAsyncIterator() -> AsyncIterator } protocol AsyncIteratorProtocol { associatedtype Element mutating func next() async throws -> Element? } 6 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0298-asyncsequence.md
Q8: Publisher.values UserViewState ͷ user iconImage ͷߪಡΛɺ for await
Λ͏ܗͰॻ͖͑ͯԼ͍͞ɻ
Q8: ղྫ
await state ͷ await ͕ᓔಃ͍͠ for await user in await
state.$user.values { ... }
state ͷΩϡʔ͕ϝΠϯΩϡʔͳΒɾɾɾ
ܕΛ͑ͯΩϡʔͰอޢ͍ͨ͠
Global Actor 7 7 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0316-global-actors.md
MainActor 8 8 h$ps:/ /github.com/apple/swi6-evolu9on/blob/main/proposals/0316-global-actors.md#the-main-actor
@MainActor @MainActor func foo() { // isolated // ϝΠϯεϨου }
@MainActor ͕༩͞ΕͨؔϝιουɺϓϩύςΟ MainActor ʹ actor-isolated
@MainActor @MainActor final class Foo { var value: Int =
42 // isolated func a() { // isolated // ϝΠϯεϨου } } @MainActor ͕༩͞ΕͨܕͷϝιουɺϓϩύςΟ MainActor ʹ actor-isolated
Q9: @MainActor UserViewState ʹ @MainActor Λ༩ͯ͠ɺ UserViewController ͱͷΓͱΓΛ MainActor ͷॲཧͱ
ͯ͠ѻ͑ΔΑ͏ʹͯ͠Լ͍͞ɻ
Q9: ղྫ
ObservableObject
UserViewState Λ ObservableObject ʹ final class UserViewState: ObservableObject { ...
}
UserViewState Λ ObservableObject ʹ • Swi%UI ͷҠߦΛݟਾ͑ͯ • Computed Property
@Published ʹͰ͖ͳ͍
UserViewState Λ ObservableObject ʹ • user iconImage Λݸผʹߪಡ͢ΔͷͰͳ͘ɺ objectWillChange9
Λߪಡ͢Δ 9 h$ps:/ /developer.apple.com/documenta6on/combine/observableobject/objectwillchange-2oa5v
Q10: ObservableObject UserViewState Λ ObservableObject ʹద߹ͤ͞ɺ user, iconImage Λݸผʹߪಡ͢ΔͷͰͳ͘ɺ objectWillChange
Λߪಡͯ͠ View ʹө͢Δܗʹमਖ਼ͯ͠Լ͍͞ɻ
Q10: ղྫ
Q10 Ͱ࣮ͨ͠ UserViewState Swi(UI Ͱͦͷ··ར༻Մೳ
Q11: Swi(UI UserViewController ͱಉ༷ͷݟͨɾڍಈΛ࣮ݱ͢Δ UserView Λ Swi%UI Ͱ࣮ͯ͠Լ͍͞ɻ ! @StateObject
Ͱ UserViewState Λอ࣋͠·͢ɻ @StateObject private var state: UserViewState
Q11: ղྫ