นี่คือการสนทนาที่น่าสนใจ ฉันคิดว่าตัวอย่างของ @ flodel นั้นยอดเยี่ยม แต่ผมคิดว่ามันแสดงให้เห็นถึงจุดของฉัน (และ @koshke กล่าวนี้ในความคิดเห็น) ที่returnทำให้รู้สึกเมื่อคุณใช้ความจำเป็นแทนการทำงานรูปแบบการเข้ารหัส
ไม่ต้องปฏิเสธประเด็นนี้ แต่ฉันจะเขียนใหม่fooเช่นนี้:
foo = function() ifelse(a,a,b)
outputสไตล์การทำงานหลีกเลี่ยงการเปลี่ยนแปลงสถานะเช่นเดียวกับการจัดเก็บค่าของ ในสไตล์นี้returnอยู่นอกสถานที่; fooดูเหมือนฟังก์ชั่นทางคณิตศาสตร์มากขึ้น
ผมเห็นด้วยกับ @flodel: การใช้ระบบซับซ้อนของตัวแปรบูลีนในจะมีความชัดเจนน้อยลงและไม่มีจุดหมายเมื่อคุณมีbar returnสิ่งที่ทำให้barคล้อยตามreturnงบก็คือมันถูกเขียนในรูปแบบที่จำเป็น แท้จริงแล้วตัวแปรบูลีนเป็นตัวแทนของการเปลี่ยนแปลง "สถานะ" ที่หลีกเลี่ยงในรูปแบบการทำงาน
มันยากมากที่จะเขียนbarในรูปแบบการใช้งานจริง ๆ เพราะมันเป็นรหัสปลอม แต่ความคิดนั้นเป็นดังนี้:
e_func <- function() do_stuff
d_func <- function() ifelse(any(sapply(seq(d),e_func)),2,3)
b_func <- function() {
do_stuff
ifelse(c,1,sapply(seq(b),d_func))
}
bar <- function () {
do_stuff
sapply(seq(a),b_func) # Not exactly correct, but illustrates the idea.
}
ห่วงจะเป็นสิ่งที่ยากที่สุดที่จะเขียนเพราะมันจะถูกควบคุมโดยรัฐเปลี่ยนแปลงไปwhilea
การสูญเสียความเร็วที่เกิดจากการโทรหาreturnมีน้อยมาก แต่ประสิทธิภาพที่ได้รับจากการหลีกเลี่ยงreturnและการเขียนใหม่ในสไตล์การใช้งานมักเป็นเรื่องใหญ่โต การบอกให้ผู้ใช้รายใหม่หยุดใช้returnอาจจะไม่ช่วย แต่การชี้แนะผู้ใช้ให้เข้ากับรูปแบบการใช้งานจะเป็นการตอบแทน
@Paul returnมีความจำเป็นในรูปแบบที่จำเป็นเพราะคุณมักต้องการออกจากฟังก์ชั่นที่จุดต่าง ๆ ในลูป returnสไตล์การทำงานไม่ได้ใช้ลูปและดังนั้นจึงไม่จำเป็นต้อง ในรูปแบบที่ใช้งานได้จริงการโทรครั้งสุดท้ายเกือบจะเป็นค่าตอบแทนที่ต้องการทุกครั้ง
ใน Python ฟังก์ชั่นต้องการreturnคำสั่ง อย่างไรก็ตามหากคุณตั้งโปรแกรมฟังก์ชั่นของคุณในสไตล์การใช้งานคุณจะมีreturnคำสั่งเพียงคำสั่งเดียว: ในตอนท้ายของฟังก์ชัน
ใช้ตัวอย่างจากโพสต์ StackOverflow อื่นให้เราบอกว่าเราต้องการฟังก์ชั่นที่คืนค่าTRUEถ้าค่าทั้งหมดในค่าที่กำหนดxมีความยาวคี่ เราสามารถใช้สองรูปแบบ:
# Procedural / Imperative
allOdd = function(x) {
for (i in x) if (length(i) %% 2 == 0) return (FALSE)
return (TRUE)
}
# Functional
allOdd = function(x)
all(length(x) %% 2 == 1)
ในสไตล์การใช้งานค่าที่ส่งคืนจะตกหล่นที่ส่วนท้ายของฟังก์ชันตามธรรมชาติ อีกครั้งดูเหมือนว่าฟังก์ชันทางคณิตศาสตร์
@ GSee คำเตือนที่ระบุไว้ใน?ifelseนั้นมีความน่าสนใจ แต่ฉันไม่คิดว่าพวกเขากำลังพยายามที่จะห้ามการใช้ฟังก์ชั่น ในความเป็นจริงifelseมีข้อดีของฟังก์ชั่นเวกเตอร์อัตโนมัติ ตัวอย่างเช่นพิจารณาเวอร์ชันที่แก้ไขเล็กน้อยของfoo:
foo = function(a) { # Note that it now has an argument
if(a) {
return(a)
} else {
return(b)
}
}
ฟังก์ชั่นนี้ใช้งานได้ดีเมื่อlength(a)เป็น 1 แต่ถ้าคุณเขียนใหม่fooด้วยifelse
foo = function (a) ifelse(a,a,b)
ตอนนี้ทำงานอยู่กับระยะเวลาของการใดfoo ๆ aในความเป็นจริงมันจะทำงานได้แม้aเป็นเมทริกซ์ การคืนค่าเป็นรูปร่างเดียวกับที่testเป็นคุณลักษณะที่ช่วยในการทำให้เป็น vectorization ไม่ใช่ปัญหา
returnไม่จำเป็นแม้แต่ในตัวอย่างสุดท้าย การนำออกreturnอาจทำให้เร็วขึ้นเล็กน้อย แต่ในมุมมองของฉันนี่เป็นเพราะ R ถูกกล่าวว่าเป็นภาษาที่ใช้ในการเขียนโปรแกรม