Swift make method พารามิเตอร์ไม่แน่นอน?


123

ฉันจะจัดการกับข้อผิดพลาดนี้โดยไม่ต้องสร้างตัวแปรเพิ่มเติมได้อย่างไร

func reduceToZero(x:Int) -> Int {
    while (x != 0) {
        x = x-1            // ERROR: cannot assign to 'let' value 'x'
    }
    return x
}

ฉันไม่ต้องการสร้างตัวแปรเพิ่มเติมเพื่อเก็บค่าของ x เป็นไปได้ไหมที่จะทำในสิ่งที่ฉันต้องการ?


3
ดูคำตอบที่อัปเดตด้านล่างนี้ Swift 3 ได้เลิกใช้คำตอบที่คุณยอมรับแล้ว
achi

คำตอบ:


193

ตามที่ระบุไว้ในคำตอบอื่น ๆ เนื่องจาก Swift 3 วาง var ก่อนที่ตัวแปรจะเลิกใช้งาน แม้ว่าจะไม่ได้ระบุไว้ในคำตอบอื่น ๆ แต่ความสามารถในการประกาศinoutพารามิเตอร์ คิดว่า: ผ่านตัวชี้

func reduceToZero(_ x: inout Int) {
    while (x != 0) {
        x = x-1     
    }
}

var a = 3
reduceToZero(&a)
print(a) // will print '0'

สิ่งนี้มีประโยชน์อย่างยิ่งในการเรียกซ้ำ

แอปเปิ้ลของinoutแนวทางการประกาศสามารถพบได้ที่นี่


2
ขอบคุณมาก!!!! ฉันติดอยู่ที่นี่ในคำถามการเรียกซ้ำ คุณช่วยชีวิตฉัน.
JW.ZG

2
ควรใช้สิ่งนี้ด้วยความระมัดระวังเนื่องจากจะปรับเปลี่ยนตัวแปรนอกขอบเขตฟังก์ชัน ตามหลักการแล้วคุณต้องการส่งคืนค่าที่คุณเปลี่ยนแปลงภายในฟังก์ชันอย่างชัดเจน
Chris Gunawardena

2
inoutควรวางคีย์เวิร์ดระหว่างชื่อพารามิเตอร์และประเภทพารามิเตอร์ดังนี้func reduceToZero(x: inout Int) ใน Swift 3 เวอร์ชันปัจจุบัน
AgustíSánchez

ยกเว้นสิ่งนี้ดูเหมือนจะใช้ไม่ได้กับการปิดเนื่องจากการปิดเห็นได้ชัดว่ามีเพียงการจับพารามิเตอร์ขาเข้าตามค่าเท่านั้น (อย่างน้อยนั่นคือข้อความแสดงข้อผิดพลาดที่ Xcode ให้ฉัน) ฉันใช้วิธีแก้ปัญหา @GeRyCh ในกรณีนี้
wcochran

ขอบคุณ. ตอนนี้ใช้งานได้แล้ว แต่มันเหมือนกับการใช้พอยน์เตอร์ใน C. สิ่งนี้จะอยู่รอดในเวอร์ชัน Swift อื่นหรือไม่?
Krishna Vedula

45

พารามิเตอร์ 'var' เลิกใช้งานแล้วและจะถูกลบออกใน Swift 3 ดังนั้นการกำหนดให้กับพารามิเตอร์ใหม่ดูเหมือนจะเป็นวิธีที่ดีที่สุดในตอนนี้:

func reduceToZero(x:Int) -> Int {
    var x = x
    while (x != 0) {
        x = x-1            
    }
    return x
}

ดังที่กล่าวไว้ที่นี่: พารามิเตอร์ 'var' เลิกใช้งานแล้วและจะถูกลบออกใน Swift 3


1
ในกรณีนี้มันลอกแบบxใหม่จริงvar xหรือ? หรือ Swift ทำอะไรที่มีประสิทธิภาพมากกว่านั้น?
Genki

3
สิ่งนี้ได้ผลและเป็นสิ่งที่ฉันทำ แต่มันดูอึดอัดมาก
wcochran

1
@Gomfucius ไม่มีคำเกี่ยวกับสิ่งนี้ในคู่มือ Swift 3.1 ในกรณีนี้ ( xเหมาะกับการลงทะเบียน) แทบไม่มีค่าใช้จ่าย ถ้าxเป็นอาร์เรย์โครงสร้างหรือออบเจ็กต์ที่กลายพันธุ์แล้วจะต้องมีการทำสำเนาเกือบจะแน่นอน (เว้นแต่เครื่องมือเพิ่มประสิทธิภาพจะสามารถวิเคราะห์แบบอินไลน์และใช้นามแฝงได้)
wcochran

1
@wcochran นี่เป็นเคล็ดลับที่เรียบร้อย แต่จริงๆแล้วไม่มีอะไรพิเศษเกิดขึ้น เพียงแค่บดบังพารามิเตอร์อินพุตด้วยสำเนา var ในเครื่อง ในสถานการณ์ของ OP จะเป็นการทดแทนvarargs ที่ดีกว่าการใช้inoutซึ่งอาจมีผลข้างเคียงโดยไม่ได้ตั้งใจโดยเฉพาะ ถ้า var เป็นตัวชี้
Echelon

45

สำหรับ Swift 1 และ 2 (สำหรับ Swift 3 ดูคำตอบโดย achi โดยใช้พารามิเตอร์ inout): อาร์กิวเมนต์ของฟังก์ชันใน Swift เป็นletค่าเริ่มต้นดังนั้นให้เปลี่ยนเป็นvarถ้าคุณต้องการแก้ไขค่าเช่น

func reduceToZero(var x:Int) -> Int {
    while (x != 0) {
        x = x-1     
    }
    return x
}

2
ทำไมคำตอบนี้ถึงได้รับการโหวตให้เหมือนนรก? คำตอบอื่นถูกวางไว้ก่อนคำตอบนี้และมีข้อมูลมากกว่าคำตอบนี้
Cristik

16
/! \ การใช้ var จะสร้างสำเนาของตัวแปรที่ส่งผ่านพารามิเตอร์ ดังนั้นการแก้ไขจะไม่แก้ไขค่าดั้งเดิม นอกจากนี้varในพารามิเตอร์ยังมีแนวโน้มที่จะหายไปใน Swift เวอร์ชันใหม่กว่าต่อ github.com/apple/swift-evolution/blob/master/proposals/…
Matthieu Riegler

17
คีย์เวิร์ด var ใน method paremeter จะเลิกใช้งานใน Swift 3
Boon

4
ฉันคิดว่าด้วย Swift 3 เราจะไม่สามารถทำสิ่งนี้ได้อีกต่อไป เราจะต้องสร้างสำเนาตัวแปรของอาร์เรย์และส่งคืนอาร์เรย์ที่แก้ไขนั้น
C0D3

คำตอบนี้เป็นคำตอบที่ถูกต้อง: stackoverflow.com/questions/24077880/…
achi

14

คำตอบ Swift3 สำหรับการส่งผ่านตัวชี้อาร์เรย์แบบผันแปร

ฟังก์ชั่น:

func foo(array: inout Array<Int>) {
    array.append(1)
}

เรียกใช้ฟังก์ชัน:

var a = Array<Int>()
foo(array:&a)

จริงๆแล้วฉันไม่แน่ใจว่าถูกต้องหรือไม่เนื่องจากพื้น Swift มีการเปลี่ยนแปลงตลอดเวลา ฉันคิดว่าสิ่งนี้ดีกว่าการทำ var array = array ภายในฟังก์ชันเพราะทำสำเนา (และไม่ส่งผลกระทบต่อโครงสร้างอาร์เรย์ดั้งเดิมจริง ๆ )? แนวทางการออกแบบที่ดีกว่าสำหรับแนวทาง var ดังกล่าวข้างต้นแล้วส่งคืนอาร์เรย์ที่กลายพันธุ์ใหม่หรือไม่
joshd

7

ใน Swift คุณเพียงแค่เพิ่มvarคำหลักก่อนชื่อตัวแปรในการประกาศฟังก์ชัน:

func reduceToZero(var x:Int) -> Int { // notice the "var" keyword
    while (x != 0) {
        x = x-1            
    }
    return x
}

อ้างถึงส่วนย่อย "ค่าคงที่และพารามิเตอร์ตัวแปร" ในบท "ฟังก์ชัน"ของหนังสือ Swift (หน้า 210 ของ iBook ตามที่เป็นอยู่ในปัจจุบัน)


7
เลิกใช้พารามิเตอร์ 'var' และจะถูกลบออกใน Swift 3
Regis St-Gelais

1
ใช้ไม่ได้กับ Swift 4 และใหม่กว่า
ilkayaktas

0

มีบางกรณีที่เราไม่จำเป็นต้องใช้ inout

เราสามารถใช้สิ่งนี้ได้หากคุณต้องการให้การเปลี่ยนแปลง / ขอบเขตอยู่ในฟังก์ชันเท่านั้น:

func manipulateData(a: Int) -> Int {
    var a = a
    // ...
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.