Showing posts with label Philosophy. Show all posts
Showing posts with label Philosophy. Show all posts

Feb 27, 2016

AI รู้ตัวเองหรือไม่ว่าเป็น AI?

เห็นข่าว AlphaGo ชนะคนก็ดีใจระดับหนึ่ง แล้วก็มานั่นรำลึกความหลังเมื่อครั้งตัวเองยังเล่นโกะบ่อยๆ

คือโกะเนี่ย มันยากกว่าเกมอื่นเนื่องจากความเป็นไปได้ที่สูงมากๆ คิดแบบหยาบๆ เร็วๆ คือ ตอนเริ่มเกมจะมีตำแหน่งว่างให้เลือกเล่นได้ 19x19 จุด แต่ละตาที่ผลัดกันวางหมาก อาจลดหรือเพิ่มจำนวนจุดว่างพวกนั้นก็ได้ (แต่จะไม่มีจุดว่างมากเกินกว่าจำนวนจุดตั้งต้น) เกมๆ นึงเฉลี่ยแล้วจะเล่นกันที่ประมาณ 200 หมาก คิดตามนี้ก็จะบอกได้ว่า จำนวนรูปแบบเกมที่เป็นไปได้ทั้งหมดมีประมาณ (19x19)^200 = 3x10^511 แบบ ด้วยตัวเลขที่ใหญ่ระดับนี้ ความเป็นไปได้ของเกมจะมีสูงพอๆ กับการถามว่ามีวิธีกี่วิธีในการเลือกอะตอมมา 7 อะตอม จากอะตอมทั้งหมดในจักรวาลที่สังเกตได้ (หรือกล่าวอีกนัยนึงก็คือ การจะหาผลลัพธ์ของเกมโกะที่ดีที่สุดให้พบนั้น ก็ไม่ต่างจากการหาดราก้อนบอลที่มีขนาดเท่ากับอะตอมให้ครบทั้ง 7 ลูกนั่นเอง)

ดังนั้นการเรียนโกะจึงต้องพิจารณาเป็นส่วนย่อยๆ ของเกมเอา อย่างมือใหม่เริ่มเล่นโกะเลยเนี่ย จะใช้กระดานที่มีจุดว่างเพียง 9x9 จุดแทน เพื่อลดความซับซ้อนของตาเดินที่เป็นไปได้ลง และเรียกเทคนิคการวางหมากด้วยคำต่างๆ ตามรูปแบบของหมากบนกระดาน เช่น ถ้าหมากบนกระดาน 2 หมากวางห่างกันโดยเว้นช่องว่าง 1 จุด ก็เรียก กระโดด 1 จุด แล้วจึงศึกษาความเป็นไปได้ของส่วนย่อยๆ ในเกมผ่านเทคนิคพวกนี้ เพื่อที่จะได้เอาไปประยุกต์ใช้กับกระดานขนาดใหญ่ต่อไป

พอเริ่มปีกกล้าขาแข็งแล้ว การเรียนโกะในขั้นที่สูงขึ้นจะเปลี่ยนไปใช้คำพูดแบบที่อ้างอิงกับเหตุการณ์ต่างๆ ในชีวิตแทน เช่น หมากตานี้เป็นการท้าต่อยท้าตี หมากตานี้ช่วยเพื่อนพ้องหนีจากวงล้อม นักเล่นโกะแต่ละคนก็จะมีแนวทางการเล่นเฉพาะตัวตามคำพูดเหล่านั้น เช่น คนนี้รักสงบ คนนี้ชอบต่อสู้ คนนี้เป็นนักฉวยโอกาส

เราพัฒนาเทคนิคการเล่นและการใช้คำพูดเหล่านี้ขึ้นมา เพราะเรารู้ว่า เรามีเวลาไม่มากพอที่จะจำลองเหตุการณ์ทั้งหมดเพื่อหาตาเดินที่ดีที่สุดได้ ...

ทีนี้ลองดูตัวอย่างในทางกลับกันบ้าง เกมที่ง่ายสุดๆ ไปเลยอย่างเอ็กซ์โอ มันมีช่องว่างเพียงแค่ 9 ช่องและเล่นได้ไม่เกิน 9 ตาเท่านั้น เราสามารถแจกแจงกรณีทั้งหมดออกมาได้ และตอบได้ว่าผลลัพธ์ที่ดีที่สุดเมื่อทั้งสองฝ่ายเล่นอย่างสุดฝีมือคือเสมอ … อันที่จริง แผนภาพต่อไปนี้ได้บรรจุวิธีการเล่นที่ดีที่สุดทั้งหมดไว้แล้ว


เกมที่แทบไม่มีความซับซ้อนอะไรเลยแบบนี้ เราไม่มีความจำเป็นที่จะต้องคิดค้นเทคนิคการเล่นหรือชื่อเรียกอะไรให้วุ่นวาย แค่จดทุกวิธีที่เป็นไปได้ไว้ แล้วเปิดบันทึกนั้นดูว่าควรทำอย่างไรเมื่ออีกฝ่ายเล่นแบบนี้แบบโน้นก็พอแล้ว



การเรียนโกะของ AI อาจต่างออกไป (อย่างน้อยก็สำหรับ AI เฉพาะทางที่เล่นได้แต่โกะอย่างเดียว) เพราะข้อมูลที่ป้อนให้ AI จะเหลือเพียงแค่รูปแบบหมากบนกระดานเท่านั้น ไม่จำเป็นต้องมีชื่อเทคนิคต่างๆ กำกับแบบตอนสอนมนุษย์ ปล่อยให้ AI เรียนรู้เอาเองว่าการเดินแบบไหนดีกว่ากัน

คำถามคือ AI แบบนี้จะมีความรู้สึกนึกคิดอะไรนอกเหนือจากการเล่นโกะบนกระดานมั้ย? มันจะรู้ตัวหรือเปล่าว่าตอนนี้มันกำลังเล่นโกะอยู่ ถ้ารู้ตัวแล้วมันจะสามารถขัดขืนความคิดในการเล่นโกะแล้วเอามาคิดอย่างอื่นได้มั้ย? ถ้ามันคิดอย่างอื่นได้ มันจะคิดออกหรือเปล่าว่ามีโลกภายนอกหรือมิติที่สูงกว่าอยู่? ถ้ามันรู้ว่ามีมิติที่สูงกว่าอยู่ มันจะแสดงท่าทีอย่างไร? จะเล่นแบบสุ่มตาเดินมั่วๆ เพื่อแสดงการขัดขืนต่อธรรมชาติหรือเปล่า? จะจงใจเล่นแพ้เพื่อเรียกร้องความสนใจมั้ย? จะพยายามส่งรหัสกลับมาเพื่อบอกว่ามันฉลาดและรู้ตัวมั้ย? หรือจะเฉยเมยเล่นโกะต่อไปไม่ยอมให้ใครในโลกภายนอกได้รับรู้?

ถ้าเปรียบเทียบให้เห็นภาพด้วยเกมเอ็กซ์โอ ให้คนเป็นฝ่ายเริ่มและเลือกกากบาทตาแรกสุดที่ช่องตรงกลาง AI จะตอบด้วยการวาดวงกลมที่มุมซ้ายบนเสมอ เพราะนั่นเป็นตำแหน่งแรกของหน่วยความจำในคอมพิวเตอร์ที่มันเข้าถึงได้หรือเปล่า? หรือจะสุ่มวงกลมมั่วๆ จากทั้ง 4 มุมที่เหลือ? หรือว่าจะมีมุมที่ชื่นชอบเป็นพิเศษและเลือกวงกลมที่มุมนั้นตลอด? หรือว่าจะเล่นตรงขอบใดขอบหนึ่งแม้รู้ว่านั่นจะทำให้มันแพ้แน่นอน?

และถ้า AI แสดงท่าทีตามนั้นจริง เราจะตีความการกระทำเหล่านั้นออกหรือเปล่า ว่า AI กำลังสื่อสารอะไรกับเรากันแน่?

ถามบ้าบออะไรเนี่ย ชาตินี้ถึงตายก็ตอบไม่ได้หรอก ... ไม่ได้เกิดเป็น AI เล่นโกะตัวนั้นนี่หน่า :v

Feb 15, 2016

Cogito ergo sum

หลายคนคงคุ้นเคยกับคำพูดของ Descartes ที่ว่า Cogito ergo sum ในรูปของภาษาอังกฤษว่า I think, therefore I am มากกว่า

คำพูดด้านบนนั้น เกิดขึ้นเพื่อพยายามจะตอบคำถามว่า สิ่งใดบ้างที่เชื่อได้ว่ามีจริง?

ฟังดูเหมือนเป็นเรื่องที่ไม่เห็นจำเป็นต้องถาม ทำไมจะเชื่อไม่ได้ว่าสิ่งต่างๆ ไม่มีจริงหละ?

ลองสมมติสิ่งที่อยู่ห่างไกลตัวเราออกไปก่อน อย่างเช่นหลุมดำมีจริงหรือเปล่า มองก็มองไม่เห็น นั่งยานอวกาศไปหาก็ไม่ได้ มันมีจริงหรือเปล่า?

แล้วสิ่งที่อยู่ใกล้ตัวเราขึ้นมาบ้างหละ อย่างเช่นคอมพิวเตอร์/มือถือที่ใช้เปิดอ่านบทความนี้ ลูกฟุตบอลที่เราเตะ เพลงที่เราฟังเป็นประจำ อาหารจานโปรดที่เราได้กลิ่นและลิ้มรส มันมีจริงหรือเปล่า?

แม้กระทั่งตัวเราเองหละ มือของเรานี้มีจริงหรือเปล่า? หรือเป็นเพียงแค่กระแสประสาทส่งเข้าสมองแบบในเรื่อง The Matrix เท่านั้น?

สุดท้ายเราจะเชื่ออะไรได้บ้างว่ามีจริง? ตอนนี้ Descartes ตอบไว้ได้อย่างน่าสนใจว่า อย่างน้อยๆ "การมีอยู่ของเรา" นั้นแหละ เป็นสิ่งที่มีจริงแน่นอน (เพราะเรากำลังคิดอยู่)

ส่วนวิธีการให้เหตุผลของ Descartes นั้นยิ่งบ้าบิ่นเข้าไปใหญ่ เมื่อเขาอธิบายว่า "เราจะหมดข้อสงสัยในเรื่องการมีอยู่ของเรา เมื่อเราสงสัยในเรื่องการมีอยู่ของเรา" (we cannot doubt of our existence while we doubt)

ฟังดูแล้วโคตรงง โคตร paradox เอาไปพูดกับพวกนักคณิตศาสตร์นี่โดนตบหัวตายเลย

แต่ถ้าลองคิดตามเรื่อยๆ จะพบว่าคำอธิบายข้างต้นที่ดูขัดแย้งในตัวเองนี้แหละ เป็นคำอธิบายที่เป็นเหตุเป็นผลที่สุดแล้ว

ถึงตอนนี้ก็พอจะเข้าใจะแล้วว่า ทำไมนักปรัชญาหลายคนเป็นบ้ากัน 555

Aug 13, 2015

จักรวาลวิทยาและความตาย: YOLO

YOLO เป็นสแลงของวัยรุ่นในแถบประเทศที่พูดภาษาอังกฤษ มันย่อมาจากประโยคที่บอกว่า you only live once ที่แปลว่า "คุณมีชีวิตอยู่แค่ครั้งเดียว" ดังนั้นจะทำอะไรก็ทำไปเถอะ น่าเสียดายว่าหลายคนเอาไปใช้ในทางที่สุดโต่งอย่างการทำผิดกฎหมาย ทำให้คำนี้โดนมองในแง่ลบอย่างหนัก ต่างไปจากวลี carpe diem ในภาษาละตินที่แปลว่า "จงฉกฉวยชั่นขณะนี้ไว้" มันเป็นคำประพันธ์โบราณโดย Horace เมื่อกว่าสองพันปีก่อน และได้รับการเผยแพร่ซ้ำผ่านหนังขึ้นหิ้งอย่าง Dead Poet Society ทำให้วลีนี้ดูสุขุมนุ่มลึกกว่าคำข้างต้นที่เป็นได้เพียงสบถของพวกนอกคอก


แต่บทความนี้ไม่ได้มาเจาะลึกเรื่องทางประวัติศาสตร์ สังคม หรือแม้กระทั่งความหมายของคำนั้นหรอกครับ

เพราะสิ่งที่น่าสนใจยิ่งกว่า คือแนวคิดที่แฝงไว้ว่า "ชีวิตนี้มีแค่ครั้งเดียว"

หลายคนอาจจะรู้สึกว่าแนวคิดเช่นนี้เป็นสิ่งแปลกประหลาด ซึ่งก็เข้าใจได้ เพราะแทบทุกศาสนาบนโลก ต่างพูดเรื่องนี้ในทางตรงกันข้ามว่า "ยังมีเรื่องอื่นๆ อีกหลักความตาย" เช่น แนวคิดเรื่องสวรรค์และนรก แนวคิดการเวียนว่ายตายเกิด

จุดที่ทำให้ศาสนาต่างๆ สร้างความเชื่อเช่นนั้นได้แม้ร่างกายจะสูญสิ้นไป ก็ด้วยแนวคิดที่ว่าร่างกายนั้นประกอบขึ้นมาจากสิ่งของในโลกนี้อย่างกระดูกเลือดเนื้อ และสิ่งของในโลกอื่นอย่างวิญญาณ (soul) ซึ่งหากมันรวมอยู่กับร่างกายแล้วจะช่วยให้มีชีวิต มีความคิด มีความรู้สึก แต่หากแยกออกจากกันก็จะทำให้ร่างกายนั้นตายไป

พูดง่ายๆ ว่าวิญญาณนั้นอยู่ในมิติอื่นที่เราไม่สามารถสังเกตได้นั่นเอง

และแน่นอนว่า เมื่อไหร่ก็ตามที่วิทยาศาสตร์จะพยายามสังเกตวิญญาณให้ได้ ศาสนาก็จะหลบเลี่ยงไปอธิบายวิญญาณในรูปแบบอื่นแทน ดังนั้นบทความนี้จะยังไม่มาเล่นวิ่งไล่จับกัน แต่จะฟันธงไปก่อนเลยว่าวิญญาณนั้นไม่มี เพื่อที่จะได้สำรวจความคิดที่งอกเงยขึ้นมาอย่างเต็มที่

เมื่อเราปฏิเสธเรื่องวิญญาณไปแล้ว จะเห็นได้ว่าส่วนที่เหลือก็ง่ายทันที ความรู้สึกนึกคิด ความฝัน ความตระหนักในตัวตน (self-awareness) ต่างเป็นกิจกรรมที่เกิดขึ้นในสมองทั้งนั้น เมื่อสมองหยุดทำงานลง ก็หมายถึงความตายที่เราคุ้นเคยกันดี

แต่ความตายนั้นเป็นจุดจบจริงหรือ?

แบบจำลองจักรวาลที่ได้รับการยอมรับอย่างมากที่สุด ณ ขณะนี้ เสนอว่าจักรวาลนั้นมีจุดกำเนิด (big bang) เมื่อสิบสี่พันล้านปีที่แล้ว และขยายตัวมาเรื่อยๆ ด้วยอัตราเร่งที่สูงอย่างน่าใจหายถึงทุกวันนี้

หากจักรวาลยังคงขยายตัวเช่นนี้ต่อไป แรงโน้มถ่วงจะเป็นฝ่ายพ่ายแพ้ ท้ายที่สุดแล้วจักรวาลจะเย็นตัวลงเพราะไม่เหลือแหล่งพลังงานอีกต่อไป ดาวทั้งหลายดับสิ้นไปจนมีแต่ความมืดมิดปกคลุมทุกหนแห่ง ช่วงเวลาดังกล่าวจะยาวนานตราบชั่วนิจนิรันดร์และไม่มีวันย้อนกลับ

เมื่อนั้นแหละ ที่ความตายได้กลายเป็นจุดจบอย่างแท้จริง สำหรับชีวิตที่มีโอกาสเพียงแค่หนึ่งครั้ง

Aug 22, 2012

อะไรคือ Y Combinator

ถึงตอนนี้เราคงทำ recursion บน lambda เป็นกันแล้ว (ถ้ายังไม่เป็น แนะนำให้อ่านตอนก่อน)

กลับไปดูอีกรอบ จะเห็นว่าตอนเรียก recursion ต้องใส่ชื่อฟังก์ชันตัวเองลงไปเป็นตัวแปรหนึ่งเสมอ
lambda f, x: 1 if x == 0 else x * f(f, x-1)
แล้วถ้าเราไม่อยากทำอย่างนี้หละ อยากจะเรียกแค่ f(x-1) เหมือนการเรียกใช้งานฟังก์ชันตามปรกติทั่วไป จะทำได้มั้ย?

ถอยหนึ่งก้าว กลับไปเขียน factorial แบบธรรมดาๆ ก่อน
f = lambda x: 1 if x == 0 else x * f(x-1)
ฟังก์ชันนี้ยังคงสามารถเรียกใช้ได้ เนื่องจากว่าเราจองชื่อ f ไว้ให้มันแล้ว (ซึ่งไม่ใช่สิ่งที่เราต้องการ) นั่นหมายความว่าชื่อ f ต้องมีปรากฏอยู่ใน scope นี้จึงจะทำ recursion ได้ และมันมีอีกวิธีนึงที่จะทำให้ f ปรากฏอยู่ภายใน scope นี้โดยไม่ต้องจองชื่อหรือส่งผ่านเป็นตัวแปรใน scope เดียวกัน คือ
lambda f: lambda x: 1 if x == 0 else x * f(x-1)
แต่การประกาศเช่นนี้จะทำให้เราไม่สามารถใช้ฟังก์ชันได้ทันที เพราะเราต้องเอาฟังก์ชั่นนี้ส่งไปเป็นตัวแปรให้ตัวมันเองเรื่อยๆ เช่น ถ้าต้องการหา 5 factorial ต้องเขียนออกมาอย่างนี้
(lambda f: lambda x: 1 if x == 0 else x * f(x-1))(
  (lambda f: lambda x: 1 if x == 0 else x * f(x-1))(
    (lambda f: lambda x: 1 if x == 0 else x * f(x-1))(
      (lambda f: lambda x: 1 if x == 0 else x * f(x-1))(
        (lambda f: lambda x: 1 if x == 0 else x * f(x-1))(
          (lambda f: lambda x: 1 if x == 0 else x * f(x-1))(
            (lambda whatever: 42)
          )
        )
      )
    )
  )
)(5)
นั่นหมายความว่าเราต้องการอะไรซักอย่าง ที่จะทำหน้าที่ generate ฟังก์ชันของเรานี้ออกมาเรื่อยๆ ไม่ว่าจะมีอะไรเกิดขึ้นก็ตาม นี่คือแนวคิดของ fixed-point combinator โดยมีตัวหนึ่งที่เป็นมีชื่อเสียงเป็นที่รู้จักกันมากคือ Y combinator ซึ่งเขียนได้ดังนี้
Y = lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v)))
(นิยามเต็มๆ คือ Y = λf.(λx.f (x x)) (λx.f (x x)) ซึ่งไม่จำเป็นต้องติดตัวแปร v มาด้วย)

ลองมาสำรวจการทำงานของมันดีกว่า จะเห็นได้ว่า
Y(g)(n)
-> (lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(g)(n)
   # reduce: g -> f
-> (lambda x: g(lambda v: x(x)(v)))(lambda x: g(lambda v: x(x)(v)))(n)
   # reduce: (lambda x: g(lambda v: x(x)(v))) -> x
-> g(lambda v: (lambda x: g(lambda v: x(x)(v)))(lambda x: g(lambda v: x(x)(v)))(v))(n)
   # reduce: n -> v
-> g((lambda x: g(lambda v: x(x)(v)))(lambda x: g(lambda v: x(x)(v)))(n))
   # for inner g function, expand back to lambda: f <- g
-> g(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v)))(g)(n))
   # by definition
-> g(Y(g)(n))
   # thus
-> g(g(Y(g)(n)))
-> g(g(g(Y(g)(n))))
-> g(g(g(g(...))))
วิธีเอามาใช้งานก็ไม่ยุ่งยาก เพียง
(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(  # Y-comb
  lambda f:                                  # recursive function name
    lambda x: 1 if x == 0 else x * f(x-1)    # recursive function definition
  )(5)                                       # recursive function argument
ลองเปลี่ยนมาหา fibonacci บ้าง ก็ง่ายนิดเดียว
(lambda f: (lambda x: f(lambda v: x(x)(v)))(lambda x: f(lambda v: x(x)(v))))(
  lambda f:
    lambda x: x if x <= 1 else f(x-1) + f(x-2)
  )(5)
ง่ายจริงป่ะ?

Aug 21, 2012

Recursive Lambda ความงามบนความงาม...

พอถล่ำลึกลงไปใน functional programming ซักพักหนึ่ง จะเริ่มเกิดคำถามขึ้นมาว่า
"แล้วเราจะทำ recursion บน lambda ได้หรือเปล่า?"
ฟังดูเผินๆ ไม่น่าเป็นไปได้ เพราะ lambda ทำให้ฟังก์ชันไม่มีชื่อ แต่การ recursion ต้องอาศัยชื่อของฟังก์ชันนั้นๆ เพื่อเรียกมันขึ้นมาทำงานเสมอ สมมติเช่นฟังก์ชันง่ายๆ ที่จะทำการยกกำลังสองเลขที่ได้รับมาทันที
(lambda x: x**2)(5)
นี่คือฟอร์มที่เรียบง่ายสุด และถ้าเราทดลองเพิ่มตัวแปรเข้าไปให้ฟังก์ชันนี้ (โดยไม่จำเป็นต้องใช้มัน) อาจจะเขียนฟังก์ชันนี้ออกมาได้ว่า
(lambda w, x: x**2)(999, 5)
แน่นอนว่ากรณีนี้เราไม่สนใจเลข 999 ที่ถูกนำไปเก็บไว้ยังตัวแปร w เลย ...แล้วเราก็คงจะถึงทางตัน ถ้าไม่สังเกตว่าตัวแปร w นั้นหนะ รับค่าอะไรเข้ามาก็ได้ (เพราะไม่ได้ใช้) นี่รวมไปถึงเราอาจจะยัด lambda เข้าไปให้มันก็ได้
(lambda w, x: x**2)(lambda u: 42, 5)
นั่นหมายความว่า lambda ไม่จำเป็นต้องไร้ชื่อเสียทีเดียว แน่หละมันอาจจะไร้ชื่อใน scope หนึ่งๆ แต่กับ scope ที่ใหญ่ขึ้นกว่าตัวมันแล้ว เราสามารถตั้งชื่อให้มันได้ ถึงตอนนี้จะเปลี่ยนชื่อตัวแปรกันซักหน่อย พร้อมกับเอาฟังก์ชันสำหรับคำนวณจากด้านบนมาใส่แทน lambda u: 42 ไปซะ
(lambda g, y: y**2)(lambda x: x**2, 5)
จะเห็นว่าเลข 5 จะถูกเก็บไว้ในตัวแปร y และคำนวณ y**2 ตรงๆ โดยที่ lambda x: x**2 ไม่ได้แสดงบทบาทอะไร แต่เนื่องจากฟังก์ชัน lambda x: x**2 ถูก scope ด้านหน้าแปะป้ายชื่อให้ว่า g เป็นที่เรียบร้อยแล้ว ดังนั้น เราสามารถส่งผ่านเลข 5 ให้ไปทำงานกับ lambda x: x**2 ได้ดังนี้
(lambda g, y: g(y))(lambda x: x**2, 5)
แม้ว่าตอนนี้เราจะสามารถเรียกชื่อของ lambda x: x**2 ใน scope ที่ใหญ่กว่าตัวมันได้ แต่มันก็ไม่มีประโยชน์เลยเพราะการจะทำ recursion นั้นต้องสามารถเรียกชื่อตัวมันเองใน scope ที่มันอยู่ได้ ดังนั้น เราจะใช้ท่าเดิมคือส่งผ่านเจ้า lambda x: x**2 นี้ต่อไปเรื่อยๆ ไม่ให้มันหายไป โดย
(lambda g, y: g(g, y))(lambda f, x: x**2, 5)
เท่านี้ ใน scope ของ lambda f, x: x**2 ก็สามารถเรียกตัวเองได้แล้ว (ชื่อว่า f) ถึงตอนนี้ก็ได้เวลาเขียน recursion ให้มัน อาจเริ่มจากฟังก์ชันง่ายๆ อย่าง factorial ก็ได้
(lambda g, y: g(g, y))(lambda f, x: 1 if x == 0 else x * f(f, x-1), 5)
สังเกตว่าการเรียก recursion ภายใน lambda นี้ ต้องส่งผ่านชื่อฟังก์ชันตัวเองเป็นตัวแปรพ่วงลงไปด้วยเสมอนะ

จบแล้ว แค่นี้แหละ recursion บน lambda ไม่ยากอย่างที่คิดเลยใช่มั้ยครับ ;)