Metaprogramming คืออะไร?


128

ผมอ่านบทความเกี่ยวกับ TheServerSide ในการเขียนโปรแกรม ployglot บนแพลตฟอร์ม ความคิดเห็นบางส่วนในบทความอ้างถึง metaprogramming ว่าเป็นความสามารถในการสร้างโค้ด (อาจจะทันที)

metaprogramming คือความสามารถในการสร้างโค้ดได้ทันทีหรือเป็นความสามารถในการแทรกเมธอดและแอตทริบิวต์ลงในอ็อบเจ็กต์ที่มีอยู่ในขณะรันไทม์ (เช่นภาษาไดนามิกบางภาษาเช่น Python, Ruby และ Groovy อนุญาต)


7
คุณอาจสนใจคำตอบนี้stackoverflow.com/questions/2565572/…
ewernli

@ewernli: คำตอบนั้นดีกว่าคำตอบใด ๆ ที่นี่!
JD

คำตอบ:


100

Metaprogramming หมายถึงวิธีต่างๆที่โปรแกรมมีความรู้ในตัวเองหรือสามารถจัดการเองได้

ในภาษาเช่น C # การสะท้อนกลับเป็นรูปแบบหนึ่งของการเขียนโปรแกรมเนื่องจากโปรแกรมสามารถตรวจสอบข้อมูลเกี่ยวกับตัวมันเองได้ ตัวอย่างเช่นส่งคืนรายการคุณสมบัติทั้งหมดของวัตถุ

ในภาษาเช่น ActionScript คุณสามารถประเมินฟังก์ชันที่รันไทม์เพื่อสร้างโปรแกรมใหม่เช่น eval ("x" + i) DoSomething () จะส่งผลต่อวัตถุที่เรียกว่า x1 เมื่อ i คือ 1 และ x2 เมื่อฉันเป็น 2

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

นอกจากนี้ยังเป็นที่น่าสังเกตว่าย้อนกลับไปในสมัยที่ดีของการเขียนโปรแกรมในแอสเซมบลีแบบตรงโปรแกรมที่เปลี่ยนแปลงตัวเองเมื่อรันไทม์เป็นสิ่งที่จำเป็นและเป็นเรื่องธรรมดามาก

จากเรียงความของ Paul Graham "What Made Lisp Different" :

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

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

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

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

แต่ฉันคิดว่าฉันสามารถโต้แย้งที่อาจทำให้เชื่อได้ ซอร์สโค้ดของตัวแก้ไข Viaweb น่าจะเป็นมาโครประมาณ 20-25% มาโครนั้นเขียนยากกว่าฟังก์ชัน Lisp ทั่วไปและถือว่าเป็นรูปแบบที่ไม่ดีที่จะใช้เมื่อไม่จำเป็น ดังนั้นทุกมาโครในโค้ดนั้นจะมีอยู่เพราะมันต้องมี หมายความว่าอย่างน้อย 20-25% ของโค้ดในโปรแกรมนี้กำลังทำสิ่งที่คุณไม่สามารถทำได้ในภาษาอื่น อย่างไรก็ตามโปรแกรมเมอร์ของ Blub อาจสงสัยเกี่ยวกับการอ้างสิทธิ์ของฉันเกี่ยวกับพลังลึกลับของ Lisp สิ่งนี้ควรทำให้เขาสงสัย เราไม่ได้เขียนโค้ดนี้เพื่อความสนุกของเราเอง เราเป็นสตาร์ทอัพเล็ก ๆ เขียนโปรแกรมให้หนักที่สุดเท่าที่จะทำได้เพื่อวางอุปสรรคทางเทคนิคระหว่างเรากับคู่แข่งของเรา

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


6
อย่าลืมเกี่ยวกับการเขียนโปรแกรมแม่แบบใน C ++ ความสามารถในการดำเนินการนิพจน์และการตัดสินใจในเวลาคอมไพล์และมีการรวบรวมผลลัพธ์แบบคงที่ในปฏิบัติการขั้นสุดท้าย
Remy Lebeau

1
ฉันตกใจมากin order to put technical barriers between us and our competitorsและนี่เป็นเรื่องที่ถูกต้อง
Evan Hu

4
โปรแกรมที่จัดการตัวเองเป็นส่วนย่อยของโปรแกรมเมตาโพรแกรมทั้งหมด Metaprogramming โดยทั่วไปหมายถึงโปรแกรมที่จัดการกับโปรแกรม
JD

55

คำถามที่ดี ขออภัยที่ไม่มีคำตอบใดที่ตอบคำถามของคุณได้อย่างถูกต้องในขณะนี้ บางทีฉันสามารถช่วย ...

คำจำกัดความของ metaprogramming นั้นค่อนข้างง่ายนั่นหมายถึงโปรแกรมที่จัดการกับโปรแกรม

คำตอบที่คุณยอมรับคือโปรแกรมที่จัดการตัวเอง สิ่งเหล่านี้เป็นโปรแกรม metaprogram แน่นอน แต่เป็นส่วนย่อยของ metaprograms ทั้งหมด

ทั้งหมด:

  • parsers
  • ภาษาเฉพาะโดเมน (DSL)
  • ภาษาเฉพาะโดเมนในตัว (EDSLs)
  • คอมไพเลอร์
  • ล่าม
  • ผู้เขียนซ้ำคำ
  • ผู้พิสูจน์ทฤษฎีบท

คือ metaprograms ดังนั้นคอมไพเลอร์ GCCจึงเป็น metaprogram ตัวแปล CPythonคือ metaprogram ระบบพีชคณิตของคอมพิวเตอร์ Mathematicaเป็นโปรแกรม metaprogram, Coq theorem proverเป็น metaprogram เป็นต้น

คำตอบอื่น ๆ ยืนยันว่า metaprograms เป็นโปรแกรมที่สร้างโปรแกรมอื่น ๆ สิ่งเหล่านี้เป็นโปรแกรม metaprogram แน่นอน แต่เป็นส่วนย่อยของ metaprograms ทั้งหมด ที่เร็วที่สุดในการแปลงฟูริเยร์ในเวสต์ (FFTW) ห้องสมุดเป็นตัวอย่างของการดังกล่าว metaprogram หนึ่ง ซอร์สโค้ดส่วนใหญ่เขียนในOCamlและสร้างบิตของโค้ด C (เรียกว่าโค้ดเล็ต) ที่รวมเข้าด้วยกันเพื่อสร้างรูทีนFast Fourier Transform ที่มีประสิทธิภาพสูงซึ่งปรับให้เหมาะกับเครื่องเฉพาะ ไลบรารีนั้นใช้เพื่อจัดเตรียมรูทีน FFT ใน Matlab คนที่ได้รับการเขียนโปรแกรมในการสร้างวิธีการเชิงตัวเลขสำหรับทศวรรษที่ผ่านมาตั้งแต่วันแรกของFORTRAN

ภาษาโปรแกรมแรกที่รวมการสนับสนุนสำหรับ metaprogramming คือภาษา LISt Processor (LISP) ในช่วงปลายทศวรรษ 1950 LISP 1.5มีคุณสมบัติหลายอย่างที่ทำให้การเขียนโปรแกรมเมตาง่ายขึ้น ประการแรกชนิดข้อมูลหลักของ LISP คือรายการที่ซ้อนกันเช่นโครงสร้างแบบต้นไม้(a (b c) d)ซึ่งหมายความว่ารหัส LISP ใด ๆ ที่สามารถแสดงเป็นโครงสร้างข้อมูลได้ สิ่งนี้เรียกว่า homoiconicity ประการที่สองรหัส LISP สามารถแปลงเป็นข้อมูลได้อย่างง่ายดายโดยใช้ QUOTE ตัวอย่างเช่น(+ 1 2 3)เพิ่ม 1 + 2 + 3 และ(QUOTE (+ 1 2 3))สร้างนิพจน์ที่เพิ่ม 1 + 2 + 3 เมื่อประเมิน ประการที่สาม LISP จัดเตรียมเครื่องมือประเมินแบบ meta-circular ที่ช่วยให้คุณสามารถใช้ล่ามโฮสต์หรือคอมไพเลอร์เพื่อประเมินรหัส LISP ในขณะทำงานรวมถึงรหัส LISP ที่สร้างขึ้นในเวลาทำงาน ลูกหลานของ LISP ได้แก่SchemeและClojure. ในทุกภาษาเหล่านี้การเขียนโปรแกรมมักจะพบเห็นได้บ่อยที่สุดในรูปแบบของโปรแกรมที่แก้ไขตัวเองโดยทั่วไปจะใช้มาโคร

ในปี 1970 ที่โรบินมิลเนอร์พัฒนาmetalanguage (ML) ที่พัฒนาเป็นครอบครัว ML ของการเขียนโปรแกรมภาษาซึ่งรวมถึงมาตรฐาน MLและOCamlและมีอิทธิพลอย่างมากHaskellและF # ภาษาเหล่านี้ช่วยให้แสดงภาษาอื่นได้ง่าย ในภาษาเหล่านี้มักจะพบเห็นโปรแกรมเมตาโพรแกรมในรูปแบบของตัวย่อตัวแยกวิเคราะห์ล่ามและคอมไพเลอร์

ในปี 1994, เออร์วิน Unruh พบว่า C ++ ระบบเทมเพลตทัวริงสมบูรณ์และสามารถนำมาใช้ในการดำเนินการโดยพลการโปรแกรมที่รวบรวมเวลา แม่แบบ C ++ metaprogramming นำ metaprogramming เพื่อมวลชนไม่เคยอาบน้ำที่ (AB) ใช้มันสำหรับสิ่งที่แตกต่างกันจำนวนมากรวมทั้งการสร้างวิธีการเชิงตัวเลขในสายฟ้าแลบห้องสมุด ++


33

ดี metaprogramming เป็นเพียงการเขียนโปรแกรม แต่มันเป็นพื้น"เขียนโค้ดที่เขียนรหัส"

ความสามารถที่คุณพูดถึงเมื่อโปรแกรมสามารถสังเกตและปรับเปลี่ยนโครงสร้างและพฤติกรรมของตัวเองเรียกว่าการสะท้อนกลับและเป็นประเภทหนึ่งของการเขียนโปรแกรมเมตา

ภาษาที่พิมพ์แบบไดนามิกมีคุณสมบัติการสะท้อนรันไทม์ที่มีประสิทธิภาพซึ่งเกิดขึ้นได้จากลักษณะการตีความของภาษาเหล่านี้ ...

ภาษาที่พิมพ์แบบคงที่ยังมีเทคนิคการเขียนโปรแกรมที่มีประสิทธิภาพเช่นการเขียนโปรแกรมแม่แบบ C ++ ...


14

นี่เป็นเพียงความคิดเห็นส่วนตัวของฉันซึ่งน่าจะเป็นคำจำกัดความของ metaprogramming ที่เสรีที่สุด

ฉันคิดว่ามันรวมถึง:

  1. การสร้างโค้ดคอมไพล์หรือการสร้างโค้ดรันไทม์ (หรือทั้งสองอย่าง)
  2. Aspect-Oriented Thinking หรือ Aspect Oriented Programming
  3. DRYคิด

ฉันคิดว่าคุณสามารถไปที่นั่นได้โดยใช้สิ่งเหล่านี้และร่วมกัน:

  1. การสะท้อน
  2. DSL (ภาษาเฉพาะโดเมน)
  3. Attributes (.NET) หรือ Annotations (Java)
  4. Generics (.NET / Java)
  5. เทมเพลต (C ++)
  6. method_missing (รูบี้)
  7. การปิด / ฟังก์ชันชั้นหนึ่ง / ผู้ได้รับมอบหมาย
  8. AOP - การเขียนโปรแกรมเชิงภาพ

คำตอบที่กระชับและรอบคอบ ให้เมนูที่ดีแก่ฉันในการตรวจสอบ ขอบคุณ!
swyx

6

Metaprogramming กำลังเขียนโปรแกรมที่เอาท์พุทโปรแกรมอื่น นี่เป็นภาษาที่ Lisp เก่งมาก มันง่ายกว่ามากที่จะทำในภาษาที่รองรับมาโครจริง (ไม่ใช่มาโคร C ++ แต่เป็นมาโครที่สามารถจัดการโค้ดที่ส่งออกได้) เช่น Ruby, Lisp, Scheme และอื่น ๆ มากกว่าในภาษาเช่น Java

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

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


5

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

โดยพื้นฐานแล้วเป็นการเขียนโค้ดที่ส่งออกโค้ดมากขึ้นซึ่งจะทำงานเพื่อบรรลุเป้าหมายบางอย่าง โดยปกติจะทำภายในภาษาเดียวกัน (โดยใช้ javascript เพื่อสร้างสตริง javascript จากนั้นeval) หรือเพื่อแสดงภาษาอื่น (โดยใช้. NET เพื่อสร้างไฟล์แบตช์ของ Windows)


4

wikipediaมีบทความดีๆในหัวข้อนี้ เราไม่ต้องทำการปรับเปลี่ยนรันไทม์สำหรับบางสิ่งเพื่อให้มีคุณสมบัติเป็น metaprogramming ตัวอย่างเช่นหลายคนใช้เทมเพลต C ++ เพื่อทำ metaprogramming ในเวลาคอมไพล์

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