คำสำหรับฟังก์ชั่นที่เรียกซ้ำหลายครั้งจะมีผลเช่นเดียวกับการโทรครั้งเดียว?


96

(สมมติว่ามีสภาพแวดล้อมแบบเธรดเดียว)

ฟังก์ชั่นที่ตอบสนองเกณฑ์นี้คือ:

bool MyClass::is_initialized = false;

void MyClass::lazy_initialize()
{
    if (!is_initialized)
    {
        initialize(); //Should not be called multiple times
        is_initialized = true;
    }
}

ในสาระสำคัญฉันสามารถเรียกใช้ฟังก์ชั่นนี้ได้หลายครั้งและไม่ต้องกังวลกับการเริ่มทำงานMyClassหลายครั้ง

ฟังก์ชันที่ไม่เป็นไปตามเกณฑ์นี้อาจเป็น:

Foo* MyClass::ptr = NULL;

void initialize()
{
    ptr = new Foo();
}

การโทรinitialize()หลายครั้งจะทำให้หน่วยความจำรั่ว

แรงจูงใจ

มันจะดีถ้ามีคำสั้น ๆ เพื่ออธิบายพฤติกรรมนี้เพื่อให้ฟังก์ชั่นที่คาดว่าจะได้พบกับเกณฑ์นี้สามารถแสดงความคิดเห็นได้อย่างถูกต้อง (โดยเฉพาะอย่างยิ่งมีประโยชน์เมื่ออธิบายฟังก์ชั่นอินเตอร์เฟสที่คาดว่าจะถูกแทนที่)


67
สำหรับผู้ลงคะแนนปิด: ในขณะที่มันเป็นความจริงที่ 99.999% (การประมาณคร่าวๆ) ของคำถาม "ชื่อ - สิ่ง - สิ่ง" นั้นไม่ได้อยู่ในหัวข้อเพราะพวกเขาไม่มีคำตอบเดียวที่ถูกต้องชัดเจนไม่คลุมเครือและ การตั้งชื่อเป็นอย่างหมดจดอัตนัยและความคิดเห็นตามคนนี้ไม่ได้มีเพียงหนึ่งเดียวที่ถูกต้องโปร่งใสคำตอบวัตถุประสงค์ซึ่งถูกกำหนดโดย OP ตัวเอง
Jörg W Mittag

30
เรียกมันว่าหลาย ๆ ครั้งจะมีผลเช่นอาจจะมีรหัสอื่น ๆ ที่มีการเปลี่ยนแปลง 'var' ในระหว่าง
RemcoGerlich

7
ทำไมคำถามนี้ถามถ้า OP รู้คำตอบในเวลาที่ถาม ? มีเหตุผลอื่นนอกเหนือจากการสร้างตัวแทน / คะแนน / กรรม?
dotancohen

13
@dotancohen Q / A การตอบคำถามด้วยตนเองสไตล์เป็นหนึ่งในแนวคิดหลักของ StackExchange
glglgl

17
@glglgl: ฉันเห็นด้วยกับคำถามเกี่ยวกับบุญ มีบุญอะไรมีคำถามนี้? ฉันกังวลอย่างจริงจังว่าเราจะเริ่มได้รับคำถาม CS 101 ทุกข้อและตอบทันทีจาก OP คำศัพท์ CS แต่ละคำที่ถูกถามและกำหนดโดย OP ทันทีและข้อดีและข้อเสียของอัลกอริธึมพื้นฐานทุกคำถามจากนั้นจะตอบทันทีโดย OP ( ไม่จำเป็นต้อง OP นี้) นั่นเป็นเว็บไซต์ที่เราต้องการให้มีการวางระบบซอฟต์แวร์หรือไม่
dotancohen

คำตอบ:


244

ฟังก์ชัน / การทำงานประเภทนี้เรียกว่าIdempotent

Idempotence (UK: / ˌɪdɛmˈpoʊtəns /, [1] US: / ˌaɪdəm - /) [2] เป็นทรัพย์สินของการดำเนินการบางอย่างในวิชาคณิตศาสตร์และวิทยาศาสตร์คอมพิวเตอร์โดยที่พวกเขาสามารถนำมาประยุกต์ใช้ได้หลายครั้งโดยไม่ต้องเปลี่ยนผลลัพธ์เลย

ในทางคณิตศาสตร์นี้หมายความว่าถ้าFเป็น idempotent, F ( F (x)) = F (x) ซึ่งเป็นเช่นเดียวกับคำพูดF = F

ในวิทยาการคอมพิวเตอร์นี้หมายความว่าถ้าf(x);เป็น idempotent, เป็นเช่นเดียวกับf(x);f(x); f(x);

หมายเหตุ:ความหมายเหล่านี้ดูเหมือนแตกต่างกัน แต่ภายใต้ความหมายเชิง Denotational ของรัฐคำว่า "idempotent" จริง ๆ แล้วมีความหมายที่แน่นอนเหมือนกันทั้งในวิชาคณิตศาสตร์และวิทยาศาสตร์คอมพิวเตอร์


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
maple_shaft

51

คำที่ถูกต้องสำหรับสิ่งนี้ (ตามที่Woofas กล่าวถึง ) คือ idempotence ฉันต้องการเพิ่มว่าในขณะที่คุณสามารถเรียกfunc1ใช้ idempotent วิธีการของคุณคุณไม่สามารถเรียกมันว่าฟังก์ชั่นบริสุทธิ์ คุณสมบัติของฟังก์ชั่น pure เป็นสอง: มันจะต้อง idempotent และจะต้องไม่มีผลข้างเคียงซึ่งจะบอกว่าไม่มีการกลายพันธุ์ของตัวแปรคงที่ในท้องถิ่นตัวแปรที่ไม่ใช่ในท้องถิ่นอาร์กิวเมนต์ที่ไม่แน่นอนหรือกระแส I / O

เหตุผลที่ฉันพูดถึงเรื่องนี้ก็คือฟังก์ชั่น idempotent ที่มีผลข้างเคียงไม่ดีเช่นกันเนื่องจาก idempotent ในทางเทคนิคหมายถึงเอาท์พุทส่งคืนของฟังก์ชั่นและไม่ใช่ผลข้างเคียง ดังนั้นfunc2วิธีการทางเทคนิคของคุณคือ idempotent เนื่องจากเอาต์พุตไม่เปลี่ยนแปลงตามอินพุต

คุณมักจะต้องการระบุว่าคุณต้องการฟังก์ชั่นที่บริสุทธิ์ ตัวอย่างของฟังก์ชั่น pure อาจเป็นดังนี้:

int func1(int var)
{
    return var + 1;
}

อ่านเพิ่มเติมสามารถพบใน Wikipedia article "ฟังก์ชั่นเพียว"


37
ฉันคิดว่านิยามของ idempotency ของคุณแคบเกินไปหรือใช้วิธีอื่นคุณกำลังใช้นิยามทางคณิตศาสตร์ของ idempotency ไม่ใช่การเขียนโปรแกรม ตัวอย่างเช่นวิธีการPUTและDELETEHTTP นั้นเรียกว่าidempotentอย่างแม่นยำเนื่องจากการดำเนินการผลข้างเคียงหลายครั้งมีผลเช่นเดียวกับการเรียกใช้งานเพียงครั้งเดียว คุณกำลังพูดว่า "idempotency แปลว่าf∘f = f" ในขณะที่ในการเขียนโปรแกรมเราหมายถึง "การดำเนินการfมีผลเหมือนกันคือการดำเนินการf; f" โปรดทราบว่าคุณสามารถเปลี่ยนความหมายที่สองให้กลายเป็นอดีตโดยการเพิ่มพารามิเตอร์ "โลก"
Jörg W Mittag

23
@Neil "Idempotency เป็นศัพท์คณิตศาสตร์อย่างเคร่งครัด" ไม่มันไม่ใช่มันยังใช้ในระบบเครือข่ายและการสื่อสารเซิร์ฟเวอร์ / ระบบกระจายลูกค้าเช่นกันและถูกอธิบายว่าJörgWMittagอธิบาย มันเป็นแนวคิดที่มีประโยชน์เพราะมันช่วยให้คำขอหลายครั้งไปยังเซิร์ฟเวอร์ / ไคลเอนต์ที่มีการดำเนินงาน / ข้อความเดียวกันโดยไม่ต้องเปลี่ยนสิ่งที่ข้อความต้นฉบับกำหนดไว้ให้ทำ สิ่งนี้มีประโยชน์เมื่อคุณมีการสื่อสารที่ไม่น่าเชื่อถือและคุณจำเป็นต้องลองคำสั่งอีกครั้งเนื่องจากข้อความไคลเอนต์ถูกทิ้งหรือเซิร์ฟเวอร์ตอบกลับ
อัยการศึก

7
คุณควรดูรายละเอียดเพิ่มเติมเกี่ยวกับความแตกต่างระหว่างความบริสุทธิ์และ idempotent func1 func1(1) != func1(func1(1))ตัวอย่างของคุณไม่ได้เพราะ
Tezra

5
ความบริสุทธิ์และ idempotence นั้นแตกต่างกัน ฟังก์ชั่นที่บริสุทธิ์ไม่จำเป็นต้องเป็น idempotent ในแง่ทางคณิตศาสตร์ ฟังก์ชั่น Idempotent (ในแง่การเขียนโปรแกรม) ไม่จำเป็นต้องบริสุทธิ์ตามตัวอย่างที่ให้โดย OP นอกจากนี้ตามที่กล่าวไว้ opa idempotence เป็นคุณสมบัติที่มีประโยชน์ที่มีการใช้แตกต่างกันอย่างเคร่งครัดกว่าความบริสุทธิ์ คำจำกัดความของความบริสุทธิ์ในฐานะ "idempotent และไม่มีผลข้างเคียง" เป็นสิ่งที่ผิดหรืออย่างน้อยก็ทำให้เข้าใจผิด downvoting
Frax

5
ในบริบทของการเขียนโปรแกรมไม่มี "ผลข้างเคียง" แต่ถ้าคุณต้องขยายคำนิยามเพื่อรวมสิ่งนี้แล้วฟังก์ชัน idempotent และฟังก์ชั่นบริสุทธิ์จะหมายถึงสิ่งเดียวกัน ไม่พวกเขาไม่ได้หมายถึงสิ่งเดียวกันเลย idempotent void f(int var) { someGlobalVariable = var; }ไม่บริสุทธิ์ บริสุทธิ์ไม่ int func1(int var) { return var + 1; }idempotent:
JLRishe

6

ระยะเวลาเป็นidempotence โปรดสังเกตด้านล่างว่ามีความแตกต่างที่ชัดเจนระหว่างฟังก์ชั่น Idempotent (เรียกซ้ำในตัวเองบล็อกโค้ดที่สองและคำจำกัดความทางคณิตศาสตร์) และ idempotence ที่ใช้งานได้ (เรียกซ้ำ ๆ กับอินพุตเดียวกันตามลำดับบล็อกโค้ดแรกและบ่อยครั้งที่

ฟังก์ชัน f พร้อมกับผลข้างเคียงถูกกล่าวว่าเป็น idempotent ภายใต้การจัดองค์ประกอบตามลำดับ f; f ถ้า, เมื่อเรียกสองครั้งด้วยรายการอาร์กิวเมนต์เดียวกัน, การเรียกครั้งที่สองจะไม่มีผลข้างเคียงและส่งกลับค่าเดียวกันกับการโทรครั้งแรก ของสายที่สอง)

ตัวอย่างเช่นพิจารณารหัส Python ต่อไปนี้:

x = 0

def setx(n):
    global x
    x = n

setx(5)
setx(5)

ที่นี่ setx เป็น idempotent เพราะการเรียกครั้งที่สองไปที่ setx (ที่มีอาร์กิวเมนต์เดียวกัน) จะไม่เปลี่ยนสถานะโปรแกรมที่มองเห็นได้: x ถูกตั้งค่าเป็น 5 ในการโทรครั้งแรกและตั้งค่าเป็น 5 ในการโทรครั้งที่สองอีกครั้ง ค่าเดียวกัน โปรดทราบว่าสิ่งนี้แตกต่างจาก idempotence ภายใต้องค์ประกอบของฟังก์ชั่น f ∘ f ตัวอย่างเช่นค่าสัมบูรณ์คือ idempotent ภายใต้องค์ประกอบของฟังก์ชัน:

def abs(n):
    if n < 0:
        return -n
    else:
        return n

abs(-5) == abs(abs(-5)) == abs(5) == 5

3

ในวิชาฟิสิกส์ฉันได้ยินสิ่งนี้เรียกว่าโปรเจคชัน :

ฉายเป็นแปลงเชิงเส้นPจากปริภูมิเวกเตอร์ให้ตัวเองดังกล่าวที่P 2 = P นั่นคือเมื่อใดก็ตามที่ P ถูกนำไปใช้สองครั้งกับค่าใด ๆ ก็จะให้ผลลัพธ์เช่นเดียวกับที่มันถูกนำมาใช้ครั้งเดียว (idempotent)

ในทางกราฟิกสิ่งนี้สมเหตุสมผลถ้าคุณดูการ์ตูนของการฉายภาพเวกเตอร์ :

ป้อนคำอธิบายรูปภาพที่นี่

ในภาพa 1คือการฉายภาพของaถึงbซึ่งเหมือนกับแอปพลิเคชั่นแรกของฟังก์ชั่นของคุณ ประมาณการที่ตามมาของ1เพื่อให้ผลเดียวกัน1 กล่าวอีกนัยหนึ่งเมื่อคุณเรียกใช้การฉายซ้ำ ๆ มันจะมีผลเช่นเดียวกับการเรียกมันครั้งเดียว

คำเตือนที่เป็นธรรม: ฉันไม่เคยได้ยินเรื่องนี้ใช้นอกวิชาฟิสิกส์ดังนั้นถ้าคุณไม่มีประเภทเหล่านั้นในทีมของคุณคุณอาจทำให้ทุกคนสับสน


2
นี่เป็นตัวอย่างที่ดีของวิธีการที่ฟังก์ชัน idempotent สามารถมองเห็นได้ (ทางคณิตศาสตร์และโดยเฉพาะอย่างยิ่งในเวกเตอร์เรขาคณิต / เขตพีชคณิตเชิงเส้น) ในขณะที่ "idempotence" ของฟังก์ชั่นซอฟต์แวร์เป็นแนวคิดที่ใกล้เคียงกันจริงๆฉันไม่คิดว่านักพัฒนา / นักวิทยาศาสตร์คอมพิวเตอร์มักจะใช้คำว่า "การฉายภาพ" ในบริบทนี้ ("ฟังก์ชั่นการฉายภาพ" ในวิศวกรรมซอฟต์แวร์ค่อนข้างจะอ้างถึงฟังก์ชั่น และส่งกลับวัตถุใหม่ที่ได้มาจากมันหรือคุณสมบัติของวัตถุนั้นเป็นต้น)
Pac0

2
@ Pac0 โอ้ตกลง ฉันทำงานกับขอบระหว่างวิทยาศาสตร์และการเขียนโปรแกรมและไม่ได้ตระหนักถึงคำว่ามากเกินไปแล้ว ฉันสามารถนึกถึงตัวอย่างที่วางแผนไว้ในที่ทำงานซึ่งฉันจะใช้คำศัพท์นี้ แต่ฉันยอมรับว่าทำงานร่วมกับคนที่ยินดีที่จะทนต่อคำศัพท์วิทยาศาสตร์ในชีวิตประจำวัน :-)
user1717828

3

มันเป็นอัลกอริธึมที่กำหนดได้เนื่องจากได้รับอินพุตเดียวกัน (ในกรณีนี้ไม่มีอินพุต) มันจะสร้างเอาต์พุตเดียวกันเสมอ

ในวิทยาการคอมพิวเตอร์อัลกอริธึมที่กำหนดขึ้นเป็นอัลกอริธึมที่ได้รับข้อมูลเฉพาะจะผลิตผลลัพธ์เดียวกันเสมอโดยเครื่องจักรพื้นฐานมักจะผ่านลำดับเดียวกันของรัฐเสมอ อัลกอริธึมที่กำหนดได้นั้นเป็นวิธีที่มีการศึกษาและคุ้นเคยเป็นอย่างดีรวมถึงหนึ่งในวิธีการปฏิบัติที่ดีที่สุดเนื่องจากสามารถทำงานบนเครื่องจักรจริงได้อย่างมีประสิทธิภาพ

ฐานข้อมูล SQL มีความสนใจในการทำงานตายตัว

ฟังก์ชันที่กำหนดขึ้นได้จะให้คำตอบเดียวกันเสมอเมื่อมันมีอินพุตเดียวกัน ฟังก์ชัน SQL ในตัวส่วนใหญ่ใน SQLite นั้นถูกกำหนดค่าไว้แล้ว ตัวอย่างเช่นฟังก์ชัน abs (X) จะส่งกลับคำตอบเดิมเสมอตราบใดที่อินพุต X เหมือนกัน

ฟังก์ชั่นจะต้องถูกกำหนดไว้ถ้ามันถูกใช้ในการคำนวณดัชนี

ยกตัวอย่างเช่นใน SQLite ต่อไปนี้ไม่ใช่หน้าที่ที่กำหนดไม่สามารถนำมาใช้ในดัชนี: random(), changes(), และlast_insert_rowid()sqlite3_version()


6
ผู้ถามfunc2เป็นคนกำหนดขึ้น (ไม่มีผลแบบสุ่มที่เกี่ยวข้อง) แต่ได้ประกาศว่าเป็นการละเมิดทรัพย์สินที่เขากำลังมองหา
Draco18s

ว่าผลลัพธ์เดียวกันนั้นเกิดจากการทำซ้ำไม่เหมือนกับการพูดว่าผลลัพธ์เดียวกันนั้นเกิดจากการซ้อนหรือผูกมัด ฟังก์ชั่นกำหนดได้มีความสำคัญสำหรับผลการแคชมากกว่าการทำดัชนี / hashing
mckenzm

3

นอกจากนี้ยังมีคำตอบอื่น ๆ หากมีการป้อนข้อมูลที่เฉพาะเจาะจงเพื่อ functon ที่มีคุณสมบัตินี้ก็เป็นจุดคงที่ , จุดคงที่หรือfixpointของฟังก์ชัน ตัวอย่างเช่น 1 ต่อกำลังใด ๆ เท่ากับ 1 ดังนั้น (1ⁿ) ⁿ = 1ⁿ = 1

กรณีพิเศษของโปรแกรมที่สร้างตัวเองเป็นเอาท์พุทเป็นควิน


Quines เป็นซอฟต์แวร์ตามที่ชุด Cantor ใช้กับคณิตศาสตร์ :-) และแน่นอน quines ไม่ใช่ idempotent - อาจล้มเหลวเมื่อมีเอาต์พุตอยู่แล้วหรือ "อุดตัน" ผลลัพธ์ก่อนหน้าและเขียนผลลัพธ์ใหม่แม้ว่าจะมีเอาต์พุตเหมือนกัน
Carl Witthoft
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.