Swift らしい表現を目指そう #eventdots

>100 Views

November 20, 16

スライド概要

iOS オールスターズ2でお話しした資料です! Swift らしさってなんだろう、そんなところを API デザインガイドラインと Swift 標準ライブラリの表現に着目して 7 つほど紹介してみました。あくまでも "指針" なので『そういう風に考えていくのね』みたいに捉えて、そこからは "自分らしい" 言葉を紡いでいってくれたらいいのかなって思います。

※ Docswell での公開に移行する直前の Slideshare での閲覧数は 9,119 でした。

profile-image

正統派趣味人プログラマー。プログラミングとは幼馴染です。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

ΧδϡΞϧ4XJGUϓϩάϥϛϯά 4XJGU Β͍͠ද‫ݱ‬Λ໨ࢦͦ͏  J04Φʔϧελʔζ ‫۽‬୩༑޺ IUUQF[OFUKQ 4XJGU

2.

‫۽‬୩༑޺ 5PNPIJSP,VNBHBJ ⾣ 4XJGU‫͕ޠݴ‬௒େ޷͖Ͱ͢ʂ ⾣ ΈΜͳͰָ͠Ήษ‫ڧ‬ձ͕େ޷͖Ͱ͢ʂ ⾣ ϓϩάϥϛϯάͷָ͠͞Λ఻͍͖͍͑ͯͨɻ !FT@LVNBHBJ UPNPIJSPLVNBHBJ $PEF1JFDFGPSNBD04 IUUQF[OFUKQ 9DPEFపఈղઆ

3.

ษ‫ڧ‬ձΛ։࠵͍ͯ͠·͢ɻ Θ͍Θ͍ɺָ͘͠ɺ ΈΜͳͰ‫ޠ‬Β͑Δ৔ॴΛ໨ࢦͯ͠ ԣ඿J1IPOF։ൃऀษ‫ڧ‬ձ ୈճ໨͸݄೔ͷ։࠵ ZJEFW ˏԣ඿ɾഅंಓ IUUQTBUOEPSHHSPVQTZJEFW ΧδϡΞϧ4XJGUษ‫ڧ‬ձ DTXJGU !ԣ඿ɾ੨༿୆ ୈճ໨Λ݄͔݄̍ʹ։࠵ʢ‫ݕ‬౼தʣ IUUQTBUOEPSHHSPVQTDTXJGU ΈΜͳͰ4XJGU ෮शձ ୈճ໨Λ݄தʹ͸։࠵ʢ໨ඪʣ NJOOB@EF@TXJGU ˏौ୩ IUUQDTXJGUDPOOQBTTDPN

4.

NPPLNPPLSBEJP Ќ൛ ϜοΫϜοΫϥδΦ ‫۽‬୩ͱ៸໘͕ϓϩάϥϛϯάίʔυͷ಺͔Β ௌ͑ͯ͘͜Δ੠ʹࣖΛ܏ָ͚ͯ͠ΉϥδΦ ຖ݄ୈ̎ɾୈ̐ ݄༵೔ ʹ഑৴ IUUQNPPLNPPLSBEJPDPNB ⾣ ୈ̓࿩  ʢ݄೔ʹ഑৴༧ఆʣ ⾣ ୈ̒࿩  ʰϝιουΛͲ͜ʹඋ͑Α͏ʁʱ ⾣ ୈ̑࿩  ʰΞΫηείϯτϩʔϧʱ ⾣ ୈ̐࿩  ʰίϝϯτͷଓ͖ˍ੔਺‫ܕ‬ʱ ⾣ ୈ̏࿩  ʰίϝϯτʱ

5.

4XJGUrָ͍͠Ͱ͢ΑͶ

6.

͔͔ͤͬͩ͘Β 4XJGUΒ͍͠ίʔυΛඳ͖͍ͨ

7.

4XJGU Β͍͠ද‫ݱ‬Λ໨ࢦͦ͏

8.

4XJGU͸ද‫͕ྗݱ‬๛͔ͳ‫ݴ‬༿ 4XJGUΒ͠͞ ͬͯɺͳΜͩΖ͏ʜ

9.

ࠓճͷ໨ඪ ͜ΕΛҎͬͯ4XJGUΒ͠͞ ͱ‫͢ʹͱ͜Ϳݺ‬Δ  4XJGU"1*%FTJHO(VJEFMJOFTʹ஫໨  ‫͔༷࢓ޠݴ‬ΒӐ͑Δࢥ૝Λ἞Ή  4XJGUඪ४ϥΠϒϥϦͷද‫ʹݱ‬฿͏

10.

4XJGUΒ͍͠ද‫ݱ‬Λ໨ࢦͦ͏  ؔ਺໊ͱϝιου໊  "1*ࣗମ͕จষද‫ͱݱ‬৺ಘΔ  ΠχγϟϥΠβʔ໊ ‫ܕ‬Λੑ࣭Ͱઆ໌͢Δ  શ෯ม‫͋Ͱ׵‬Δ͔Λҙࣝ͢Δ  ‫ػ‬ೳͷॴଐ ৼΔ෣͍ͱͯ͠ओମʹඋ͑Δ  ‫ܕ‬Ωϟετ ม‫׵‬ઌͷ੹೚Ͱม‫͢׵‬Δ ൺֱՄೳͳ‫ܕ‬ ςΩετද‫ݱ‬Մೳͳ‫ܕ‬ $VTUPN4USJOH$POWFSUJCMFͰද‫ݱ‬  ࿈ଓతͳ஋Λड͚औΔ ੑ࣭ʹண໨ͯ͠‫ػ‬ೳΛ૊ΈཱͯΔ

11.

1/7 ؔ਺໊ͱϝιου໊ 10*/5⭐"1*ࣗମ͕จষද‫ͳʹݱ‬Δ

12.

ؔ਺໊ͱϝιου໊ ໊લͷ‫ج‬ຊํ਑ ⾣ ӳ‫Ͱޠ‬ίϝϯτΛॻ͘Α͏ͳ ྲྀΕΛҙࣝ ⾣ શͯͷ‫ݴ‬༿Ͱաෆ଍ͳ͘ҙຯΛ๰͙ ⾣ ૢ࡞ͷओମͰͳ͍΋ͷΛϥϕϧͰઆ໌ // 定義は、外部引数名、内部変数名、型名を活用して紡ぐ func insert(_ newItem: Item, into position: Int) // 使用時は、変数名も活用して紡ぐ bookshelf.insert(newBook, into: freeSpace) // item が冗長だったり、freeSpace が説明不足だったり bookshelf.insert(item: newBook, position: freeSpace)

13.

ؔ਺໊ͱϝιου໊ ओମͷઆ໌ྗ͕ෆ଍͢Δͱ͖ ⾣ ‫Ͱܕ‬ҙຯΛෆ଍ͳ͘๰͛ͳ͍ͱ͖ ⾣ ද‫ݱ‬ൣғ͕޿͍ͱҙਤΛ૊Έ೉͍͜ͱ΋ w "OZ "OZ0CKFDU /40CKFDUͳͲͷ൚༻‫ܕ‬ w *OU 4USJOHͳͲͷ‫ج‬ຊ‫ܕ‬

14.

ؔ਺໊ͱϝιου໊ ‫ܕ‬ͷઆ໌ྗ͕ෆ଍ͷͱ͖ // 定義を見れば、意図を汲めるけれど… func add(handler: () -> Void, for eventName: String) // 使用時に、説明不足で主体から用途が想像しにくい document.add(handler: () -> Void, for: String) // 定義時に名前で補足すると… func addEventHandler(_ handler: () -> Void, forEventName name: String) // 使用時に用途を汲みやすくなる document.addEventHandler(handler: () -> Void, forEventName: String)

15.

10*/5 "1*ࣗମ͕จষද‫ͳʹݱ‬ΔΑ͏ʹ "1*ΛσβΠϯ͢Δ ؔ਺໊ͱϝιου໊

16.

2/7 ΠχγϟϥΠβʔ໊ 10*/5⭐શ෯ม‫͋Ͱ׵‬Δ͔Λҙࣝ͢Δ

17.

ΠχγϟϥΠβʔ໊ ‫ج‬ຊతͳ໊લͷ෇͚ํ ⾣ ༻్ΛϥϕϧͰઆ໌͢Δ ⾣ Ҿ਺Λจষද‫͍ͳྀ͠ߟͯ͠ͱݱ‬ ⾣ ϓϩύςΟʔ໊Λ୯७ྻ‫͢ه‬Δ͜ͱ΋ଟ͍ // bytes と count をとって初期化する init(bytes: UnsafeRawPointer, count: Int) // value と radix と uppercase をとって初期化する init(_ value: Int, radix: Int, uppercase: Bool) // lower と upper をとって初期化する init(lower: Bound, upper: Bound)

18.

ΠχγϟϥΠβʔ໊ ม‫׵‬ΠχγϟϥΠβʔͷ໊લ ⾣ ผͷ‫ܕ‬Λࣗ਎ͷ‫ʹܕ‬ม‫͢׵‬ΔΠχγϟϥΠβʔ w ஋Λҡ࣋͢Δม‫׵‬͸ɺ࠷ॳͷϥϕϧΛ ল͘ w Ճ޻౳Λ൐͏ม‫׵‬͸ɺ࠷ॳͷϥϕϧͰ આ໌͢Δ // Int 型の値を String 型で忠実に再現(全幅変換) struct String { init(_ value: Int, radix: Int = 10) } // UInt32 型の値をビットパターンとして Int32 型に再解釈 struct Int32 { init(truncatingBitPattern pattern: UInt64) }

19.

ΠχγϟϥΠβʔ໊ ͜͏໊ͯ͠લΛ෇͚Δ͜ͱͰʜ ⾣ ϥϕϧ͔ΒΠχγϟϥΠβʔͷҙਤ ͕἞ΊΔ // Int 型の値を String 型にキャスト(全幅変換) let string = String(number, radix: 16) // ビットパターンを指定して Int32 型を生成(Narrow 変換) let value = Int32(truncatingBitPattern: number) // 範囲を生成 let range = MyRange(lower: start, upper: last)

20.

10*/5 શ෯ม‫͋Ͱ׵‬Δ͔Λҙࣝͯ͠ ϥϕϧ໊Ͱ‫ػ‬ೳΛઆ໌͢Δ ΠχγϟϥΠβʔ໊

21.

3/7 ‫ػ‬ೳͷॴଐ 10*/5⭐ৼΔ෣͍ͱͯ͠ओମʹඋ͑Δ

22.

‫ػ‬ೳͷॴଐ ओମʹ‫ػ‬ೳΛ࣮૷͢Δ ⾣ ϝιου΍ϓϩύςΟʔͱͯ͠ ओମʹ࣮૷͢Δ ⾣ ࣮૷΍ ‫֦ܕ‬ு ɺϓϩτίϧ֦ு Ͱ࣮૷͢Δ // 自作の型なら、直接でも拡張でも自由に備えられる struct Bookshelf : Collection { mutating func arrange() { … } } // 他者が作ったものにも、拡張で備えられる extension Collection where Iterator.Element == Book { func sortedByTitle() -> [Book] { … } }

23.

ϑϦʔͳؔ਺Ͱ࣮૷͢Δ৔໘

24.

‫ػ‬ೳͷॴଐ ϑϦʔͳؔ਺Ͱ࣮૷͢Δ৔໘ ⾣ ओମ͕̍ͭʹܾ·Βͳ͍ͱ͖ ⾣ ओମ͕ఆٛʹ‫ݱ‬Εͳ͍ͱ͖ ⾣ ෼໺తʹ ؔ਺ද‫ه‬ͷ΄͏͕ࣗવͳ ͱ͖ // 全ての値が対等で、主体が定まらない func average(of values: Double...) -> Double // 具体的な主体が定義に現れないため、所属できない func convert<T: Any, U: Compatible>(from: T) -> U // プログラミングの分野では、絶対値は関数 abs で取得する func abs(_ x: Double) -> Double

25.

10*/5 ‫ػ‬ೳ͸ৼΔ෣͍ͱͯ͠ओମʹඋ͑Δ ঢ়‫ʹگ‬Αͬͯ͸ϑϦʔͳؔ਺Ͱ ‫ػ‬ೳͷॴଐ

26.

4/7 ‫ܕ‬Ωϟετ 10*/5⭐ม‫׵‬͸ม‫׵‬ઌͷ੹೚Ͱߦ͏

27.

‫ܕ‬Ωϟετ ม‫׵‬ΠχγϟϥΠβʔͰ࣮૷͢Δ ⾣ ม‫׵‬ઌʹΠχγϟϥΠβʔΛඋ͑Δ ⾣ ੹೚Λ࣋ͬͯม‫ݩ׵‬ͷ஋Λड͚ೖΕΔ struct Int128 { fileprivate var low: UInt64 fileprivate var high: UInt64 // Int 型の値を Int128 型に全幅変換 init(_ value: Int) { low = UInt64(value) high = 0 } }

28.

‫ܕ‬Ωϟετ ‫ط‬ଘͷ‫ʹܕ‬ม‫͢׵‬Δ ⾣ ม‫׵‬ઌʹΠχγϟϥΠβʔΛ֦ு ͢Δ ⾣ ੹೚Λ࣋ͬͯม‫ݩ׵‬ͷ஋Λड͚ೖΕΔ extension Int { // Int128 型の値を Int 型に全幅変換 init(_ value: Int128) { guard value.high == 0 else { fatalError("Overflow") } self = Int(value.low) } }

29.

‫ܕ‬Ωϟετ ม‫׵‬ΠχγϟϥΠβʔΛ࢖͏ͱʜ ⾣ ͍ͭ΋ͷ‫ܕ‬Ωϟετͱ ॻ͖ํ͕ἧ͏ ⾣ ࣮ࡍɺͨͱ͑͹%PVCMF͔Β*OUͷΩϟετ΋ ม‫׵‬ΠχγϟϥΠβʔͰ࣮‫͞ݱ‬Ε͍ͯΔ // お馴染みの Double から Int へのキャスト例 let taxIncluded = Int(Double(price) * (1 + tax)) // お馴染みのキャストと同じ書き方になる let endOfInteger = Int128(Int64.max) + 1 // 自作の Int128 から Int への変換もいつも通り let stride = Int(Int128.max / samples)

30.

10*/5 ม‫׵‬ઌʹม‫׵‬ΠχγϟϥΠβʔΛඋ͑Δͱ ͍ͭ΋ͷΩϟετͷॻ͖ํʹͳΔ ‫ܕ‬Ωϟετ

31.

5/7 ൺֱՄೳͳ‫ܕ‬ 10*/5⭐‫ܕ‬Λੑ࣭Ͱઆ໌͢Δ

32.
[beta]
ൺֱՄೳͳ‫ܕ‬

&RVBUBCMFϓϩτίϧ
⾣

ൺֱՄೳੑΛࣔ͢ϓϩτίϧ

⾣

ඞཁ‫ػ‬ೳΛඋ͑Δͱɺͦͷੑ࣭Λ࣋ͭ‫ͳʹܕ‬Δ

// 標準ライブラリーに規定されている性質
/// A type that can be compared for value equality.

protocol Equatable {
/// Returns a Boolean value indicating
/// whether two values are equal.

static func ==(lhs: Self, rhs: Self) -> Bool
}

33.
[beta]
ൺֱՄೳͳ‫ܕ‬

‫&ʹܕ‬RVBUBCMFΛద༻͢Δ
⾣

‫ܕ‬Λ&RVBUBCMFϓϩτίϧͰઆ໌͢Δ

⾣

ൺֱͰ͖Δ‫ͯ͠ͱܕ‬ѻ͑ΔΑ͏ʹͳΔ

// プロトコルで比較可能性を説明すると…

extension Int128 : Equatable {
static func == (lhs: Int128, rhs: Int128) -> Bool {
return (lhs.low, lhs.high) == (rhs.low, rhs.high)
}
}
// 比較演算を使って比較可能になる

Int128(1000) == Int128(1000)
Int128(1000) != Int128(1000)

34.
[beta]
ൺֱՄೳͳ‫ܕ‬

δΣωϦοΫͳੈք͕޿͕Δ
⾣

ͦͷੑ࣭Λ૝ఆͨ͠ՕॴͰ࢖͑Δ

⾣

ੑ࣭͍͑ࣔͯ͞͠Ε͹ͲΜͳ‫Ͱܕ‬΋ྑ͍

// 比較可能な要素を扱う場合だけ使えるようになっている

extension Array where Element : Equatable {
func index(of element: Element) -> Int?
}
// 配列で、要素からインデックスを特定できるようになる

let values = [Int128(1), Int128(5), Int128(10)]
let index = values.index(of: Int128(5))

35.

10*/5 ‫ܕ‬ΛϓϩτίϧͰઆ໌͢Δͱ ͦͷੑ࣭ʹ͋ͬͨৼΔ෣͍͕උΘΔ ൺֱՄೳͳ‫ܕ‬

36.

6/7 ςΩετද‫ݱ‬Մೳͳ‫ܕ‬ 10*/5⭐$VTUPN4USJOH$POWFSUJCMFͰઆ໌

37.

ςΩετද‫ݱ‬Մೳͳ‫ܕ‬ $VTUPN4USJOH$POWFSUJCMF ⾣ ΠϯελϯεΛ4USJOHʹม‫͢׵‬Δํ๏Λ‫ن‬ఆ ⾣ ࣗ਎ΛςΩετͱͯ͠࠶ද‫͢ݱ‬Δͷʹ࢖͏ // 標準ライブラリーに規定されている性質 /// A type with a customized textual representation. protocol CustomStringConvertible { /// A textual representation of this instance. var description: String { get } }

38.

ςΩετද‫ݱ‬Մೳͳ‫ܕ‬ ‫ܕ‬ΛςΩετද‫ݱ‬Մೳʹ͢Δ ⾣ $VTUPN4USJOH$POWFSUJCMFϓϩτίϧͰઆ໌͢Δ ⾣ ಺༰Λ4USJOH‫Ͱܕ‬ද‫͖Ͱݱ‬Δ Α͏ʹͳΔ enum Device : CustomStringConvertible { case iPhone, iPad, appleWatch var description: String { switch self { case .iPhone: case .iPad: case .appleWatch: } } return "iPhone" return "iPad" return " Watch"

39.

ςΩετද‫ݱ‬Մೳͳ‫ܕ‬ จࣈྻද‫ݱ‬Λ‫ظ‬଴͢Δ৔໘Ͱ࢖ΘΕΔ ⾣ 4USJOH EFTDSJCJOH Ͱจࣈྻม‫͢׵‬Δͱ͖ ⾣ QSJOUؔ਺Ͱදࣔ͢Δͱ͖ ⾣ 4USJOH*OUFSQPMBUJPOͰѻ͏ͱ͖ let device = Device.appleWatch // String 型への変換(表示用の表現) let displayText = String(describing: device) // 文字列として表示(表示用の表現) print(device) // String Interpolation を介した変換(表示用の表現) let message = "I love \(device)"

40.

10*/5 $VTUPN4USJOH$POWFSUJCMFͰઆ໌͢Δͱ จࣈྻͱͯ͠ද‫͖Ͱݱ‬Δੑ࣭͕උΘΔ ςΩετද‫ݱ‬Մೳͳ‫ܕ‬

41.

7/7 ࿈ଓతͳ஋Λड͚औΔ 10*/5⭐ੑ࣭ʹண໨ͯ͠‫ػ‬ೳΛ૊ΈཱͯΔ

42.

࿈ଓతͳ஋Λड͚औΔ ࿩ΛਐΊΔ্Ͱͷલఏ ⾣ ม਺qPBU7BMVFT͕"SSBZ‫Ͱܕ‬ఆٛ͞Ε͍ͯΔ ⾣ "SSBZͷ෦෼഑ྻ͸<qPBU7BMVFT // 変数 floatValues が Array<Float> で定義されている let floatValues: [Float] // サブスクリプトに範囲を渡すと、部分配列が取れる let slice = floatValues[2 ..< 6] // 部分配列の型は ArraySlice<Float> になる type(of: slice) == ArraySlice<Float>.self

43.
[beta]
࿈ଓతͳ஋Λड͚औΔ

%PVCMF഑ྻͷ߹‫ܭ‬Λ‫ٻ‬ΊΔ
⾣

%PVCMF‫ܕ‬Λ഑ྻͰड͚औͬͯ‫͢ࢉܭ‬Δ

⾣

ཁ‫͓Ͳٻ‬Γ‫ͼݺʹີݫ‬ग़͢ඞཁ͕͋Δ

// 一般的な定義の仕方

func sum(of values: [Double]) -> Double {
return values.reduce(0, +)
}
// Float 型の配列の部分配列の合計を計算

sum(of: floatValues[2 ..< 6].map(Double.init))
εϥΠεͨ͠"SSBZ4MJDFͷ಺༰Λ'MPBU͔Β%PVCMFʹม‫ࢉܭͯ͠׵‬

44.
[beta]
࿈ଓతͳ஋Λड͚औΔ

খ਺఺਺ͷ ഑ྻͷ߹‫ܭ‬Λ‫ٻ‬ΊΔ
⾣

ුಈখ਺఺਺Λ഑ྻͰड͚औͬͯ‫͢ࢉܭ‬Δ

⾣

஋͸খ਺఺਺Ͱ͋Ε͹ͳΜͰ΋ྑ͍

// 任意の浮動小数点数を対象にする

func sum<T: FloatingPoint>(of values: [T]) -> T {
return values.reduce(0, +)
}
// Float 型の配列の部分配列の合計を計算

sum(of: Array(floatValues[2 ..< 6]))
εϥΠεͨ͠"SSBZ4MJDFΛ"SSBZʹม‫ࢉܭͯ͠׵‬

45.

࿈ଓతͳ஋Λड͚औΔ 4FRVFODFϓϩτίϧ ⾣ ཁૉ΁ͷ࿈ଓΞΫηεੑΛࣔ͢ϓϩτίϧ ⾣ ͜ͷੑ࣭Λ࣋ͭ‫͔ܕ‬Β͸ɺ஋Λॱ࣍औಘͰ͖Δ ⾣ "SSBZ΋"SSBZ4MJDF΋4FRVFODFʹ४‫͍ͯ͠ڌ‬Δ // 標準ライブラリーに規定されている性質 /// A type that provides sequential, /// iterated access to its elements. public protocol Sequence { /// A type that provides the sequence's iteration /// interface and encapsulates its iteration state. associatedtype Iterator : IteratorProtocol

46.
[beta]
࿈ଓతͳ஋Λड͚औΔ

খ਺఺਺ͷ߹‫ܭ‬Λ‫ٻ‬ΊΔ
⾣

࿈ଓ͢Δුಈখ਺఺਺Λड͚औͬͯ‫͢ࢉܭ‬Δ

⾣

‫ࢉܭ‬ର৅͸࿈ଓ͍ͯ͠Ε͹ͳΜͰ΋ྑ͍

// 連続する任意の浮動小数点数を対象にする

func sum<S: Sequence, T: FloatingPoint>
(of values: S) -> T where S.Iterator.Element == T {
return values.reduce(0, +)
}
// 連続する浮動小数点数の部分配列の合計を計算

sum(of: floatValues[2 ..< 6])
εϥΠεͨ͠"SSBZ4MJDFͰ‫ࢉܭ‬

47.

10*/5 ੑ࣭ʹண໨ͯ͠‫ػ‬ೳΛ૊ΈཱͯΔͱ ‫ʹܕ‬റΒΕͳ͍ੈքΛඳ͚Δ ࿈ଓతͳ஋Λड͚औΔ

48.

4XJGUΒ͠͞͸ͦΕͧΕͷ‫ݸ‬ੑ ΈΜͳͷ4XJGUΒ͠͞ Λ୳ͯ͠Έ·͠ΐ͏ʂ

49.

&OKPZ4XJGU 4XJGUΒ͍͠ද‫ݱ‬Λ໨ࢦͦ͏  ؔ਺໊ͱϝιου໊  "1*ࣗମ͕จষද‫ͱݱ‬৺ಘΔ  ΠχγϟϥΠβʔ໊ ‫ܕ‬Λੑ࣭Ͱઆ໌͢Δ  શ෯ม‫͋Ͱ׵‬Δ͔Λҙࣝ͢Δ  ‫ػ‬ೳͷॴଐ ৼΔ෣͍ͱͯ͠ओମʹඋ͑Δ  ൺֱՄೳͳ‫ܕ‬ ςΩετද‫ݱ‬Մೳͳ‫ܕ‬ $VTUPN4USJOH$POWFSUJCMFͰද‫ݱ‬  ࿈ଓతͳ஋Λड͚औΔ ੑ࣭ʹண໨ͯ͠‫ػ‬ೳΛ૊ΈཱͯΔ ‫ܕ‬Ωϟετ ม‫׵‬ઌͷ੹೚Ͱม‫͢׵‬Δ ‫۽‬୩༑޺ IUUQF[OFUKQ