เสียงกระเพื่อมยังมีคุณสมบัติพิเศษที่ไม่ได้ใช้กับภาษาการเขียนโปรแกรมอื่น ๆ หรือไม่?


35

เสียงกระเพื่อมยังมีคุณสมบัติพิเศษที่ไม่ได้ใช้กับภาษาการเขียนโปรแกรมอื่น ๆ หรือไม่?

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

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

ฉันพลาดอะไรไปหรือเปล่าและ "Lisp ยังต่างกัน"

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


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

3
ขอบคุณสำหรับคำแนะนำ @gnat และผมได้ปรับปรุงคำถามของฉัน :)
iceX

10
ปัญหาหนึ่งคือเมื่อภาษามีชุดย่อยของคุณสมบัติ Lisp (ตัวอย่างเช่น S-expressions และ macros) ผู้คนอ้างว่าเป็น Lisp ซึ่งแน่นอนว่ามีผลที่ตามมา (ตามคนเหล่านี้) ไม่มีภาษาที่ไม่ใช่เสียงกระเพื่อมสามารถมีคุณสมบัติเหล่านี้

9
ฉันเดาว่าไม่มีภาษาอื่นที่มีเครื่องหมายวงเล็บกลมเป็นรูปแบบเดียวของการจัดกลุ่มสำหรับทุกอย่าง :-)
Doc Brown

เสียงกระเพื่อมเป็นครอบครัวอาจไม่ซ้ำกันชะมัด แต่ภาษาเสียงกระเพื่อมจำนวนมาก (แร็กเก็ต, CL, Scheme, Clojure) ยังคงมีคุณสมบัติที่เป็นประโยชน์ / ไม่ซ้ำกันจำนวนมาก
jozefg

คำตอบ:


28

การอ้างอิงที่ยอมรับสำหรับชนิดของคำถามนี้พอลเกรแฮมสิ่งที่ทำให้แตกต่างกันชัด คุณสมบัติหลักที่เหลืออยู่สองประการของ Lisp ที่ไม่สามารถใช้งานได้อย่างกว้างขวางตามบทความนี้ ณ เวลาที่ทำการเขียนคือ:

8. สัญลักษณ์สำหรับรหัสโดยใช้สัญลักษณ์ต้นไม้

9. ภาษาทั้งหมดพร้อมใช้งานเสมอ ไม่มีความแตกต่างที่แท้จริงระหว่างเวลาอ่านเวลาคอมไพล์และรันไทม์ คุณสามารถรวบรวมหรือเรียกใช้รหัสในขณะที่อ่านอ่านหรือเรียกใช้รหัสในขณะที่รวบรวมและอ่านหรือรวบรวมรหัสที่รันไทม์

คำอธิบายจะกล่าวถึงแต่ละจุดและตั้งชื่อภาษายอดนิยมที่มีคุณสมบัติดังกล่าว

8 ซึ่ง (กับ 9) เป็นสิ่งที่ทำให้มาโคร Lisp เป็นไปได้จนถึงตอนนี้ยังคงเป็นเอกลักษณ์ของ Lisp ซึ่งอาจเป็นเพราะ (a) มันต้องการ parens เหล่านั้นหรือบางสิ่งที่แย่มากและ (b) หากคุณเพิ่มพลังที่เพิ่มขึ้นในขั้นสุดท้าย คุณไม่สามารถอ้างสิทธิ์ได้ประดิษฐ์ภาษาใหม่อีกต่อไป แต่จะได้ออกแบบภาษา Lisp ใหม่ -)

โปรดทราบว่าบทความนี้ได้รับการแก้ไขครั้งล่าสุดในปี 2545 และในช่วง 11 ปีที่ผ่านมามีภาษาใหม่ที่หลากหลายซึ่งบางภาษาอาจรวมคุณลักษณะ LISP เหล่านี้ทั้งหมดไว้ในการออกแบบของพวกเขา


2
ฟีเจอร์เหล่านั้นไม่ซ้ำกับ Lisp (และตัวแปรที่ได้มาโดยตรง) และยังไม่เคยมีมานาน
Donal Fellows

21
@iceX: ความแตกต่างระหว่าง JavaScript และภาษาเช่น Lisp, Smalltalk, Self, Newspeak, APL, Factor, Forth เป็นต้นคือใน JavaScript โปรแกรมนั้น "ตาย" พวกเขาเป็นไฟล์ข้อความ คุณฆ่าโปรแกรมที่กำลังทำงานแก้ไขไฟล์ข้อความจากนั้นเริ่มโปรแกรมใหม่ทั้งหมด ในอื่น ๆ (ที่เรียกว่าสภาพแวดล้อม "มีชีวิตชีวา") ที่คุณไม่เคยหยุดการทำงานของโปรแกรม, โปรแกรมการทำงานตัวเองเป็นชุดของวัตถุในหน่วยความจำที่คุณจัดการเช่นเดียวกับคุณจัดการกับวัตถุอื่น ๆในขณะที่มันกำลังทำงานอยู่ (หมายเหตุ: นี่ไม่เป็นความจริงสำหรับ Clojure แต่ Lisps ที่มีอายุมากกว่าส่วนใหญ่ทำแบบนี้)
Jörg W Mittag

2
@ JörgWMittagว้าว ... ดังนั้นภาษาการเขียนโปรแกรมอย่าง Clojure, Clojurescript, lispyscript นั้นในความเป็นจริงไม่ใช่ "เสียงกระเพื่อมจริง" เพราะพวกเขาไม่สามารถเปลี่ยนรหัสในแบบที่เสียงกระเพื่อมโรงเรียนเหมือน Common Lisp ได้ แต่ ... ถ้าพวกเขาไม่สามารถเปลี่ยนมันได้ ... ทำไมต้องใช้ S-expression ซึ่งฉันคิดว่ามันมีจุดประสงค์เพื่อจัดการกับรหัส ... (รู้สึกเหมือนฉันเพิ่งตกลงไปในหลุมกระต่ายที่ลึกและมืด)
iceX

4
@iceX: หลาย ๆ ภาษามีevalหรือคล้ายคลึงกันและมีไม่กี่คนที่สามารถทำการเปรียบเทียบโปรแกรมเช่น Haskell's Template Haskell สิ่งที่ไม่ซ้ำกัน (arguably) เกี่ยวกับ Lisp คือการแสดงข้อมูลรหัสและเมตาดาต้าเหมือนกัน - ไม่ใช่แค่ในรูปแบบไวยากรณ์ แต่จริงๆแล้วมันเป็นสิ่งเดียวกัน
tdammers

2
@iceX Eval เป็นเพียงส่วนหนึ่งของมัน แต่ไม่ใช่ทั้งหมด ใน Lisp คุณสามารถรันโค้ดในเวลาคอมไพล์ คุณสามารถรันโค้ดในเวลาที่อ่าน ใช่ Clojure รองรับพลวัตของ Lisp ทั้งหมดมันมีมาโครมาโครเครื่องอ่านและอีวาลรวมทั้งความสามารถในการแนบ REPL เข้ากับโปรแกรมที่กำลังทำงานอยู่เพื่อปรับเปลี่ยนได้ทันที
หิน

15

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

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

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

ลองคิดดูสิว่าการสร้างรูปแบบตรงนั้นเป็นมาโครชนิดเดียวที่มีให้ใน Lisp: ฉันไม่เคยเห็นคอมไพเลอร์หรือมาโครของผู้อ่านที่อื่น

ความสามารถของภาษาถิ่นบางตัว (เช่นSBCL ) เพื่อบันทึกภาพกระบวนการที่สมบูรณ์และกลับมาทำงานได้นั้นยอดเยี่ยม แต่ก็ไม่ใช่เรื่องแปลก: Smalltalkได้ทำสิ่งนั้นมานานหลายสิบปีแล้ว

ภาษาอื่น ๆ อีกมากมายอนุญาตให้ทำการทำลายเมื่อเปิดอาร์เรย์ แต่วิธี # 'และ #' ค่าหลายค่า -bind / let-values ​​ยังคงดูเหมือนจะเฉพาะเจาะจงกับ Common Lisp และ Scheme (ซึ่งยังสามารถทำการทำลาย 'ปกติ' ได้เช่นกัน ) Perl 'wantarray' อนุญาตให้ฟังก์ชั่นเพื่อตรวจสอบว่ามันถูกเรียกในเกลา, รายการหรือเป็นโมฆะบริบทเพื่อให้สามารถปรับค่าตอบแทนในลักษณะที่คล้ายกัน (--ish) แต่ฉันไม่เห็น 'จริง' หลายคืนค่านอก ของโครงการ / CL

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


3
มาโคร Scala นั้นมีพลังน้อยกว่ามาโคร Lisp เช่นเดียวกับมาโคร TH, มาโครที่ถูกสุขลักษณะของ Scheme และอื่น ๆ ระบบที่ทรงพลังสามารถพบได้ใน MetaLua และ Converge
SK-logic

4

หลังจากหลายทศวรรษที่ผ่านมาฉันไม่คิดว่าจะมีอะไรพิเศษเฉพาะกับเสียงกระเพื่อม แต่แม้กระทั่งทุกวันนี้ก็มีสิ่งที่น่าสนใจมากมายที่หาได้ยากจาก Lisps บางสิ่งที่อยู่ในใจ:

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

ในที่สุดมีอะไรอีกมากมายให้เรียนรู้จาก Lisp ที่ไม่เกี่ยวกับภาษา แต่กลายเป็นส่วนหนึ่งของประวัติ Lisp และเสียเวลา เช่น Interlisp, Symbolics Genera, ฯลฯ ... หากคุณไม่เคยใส่ Genera ให้ดูที่หัวข้อ comp.lang.lisp นี้ที่ Kent Pitman อธิบายว่า "Emacs เป็นเพียงเงาสีซีดของ Genera Zmacs" ซึ่งทั้งหมดถูกเปิดใช้งานโดย มีระบบเสียงกระเพื่อมที่มีประสิทธิภาพซึ่ง Zmacs เป็นส่วนหนึ่งของซึ่งวิ่งบนเครื่องเสียงกระเพื่อม


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

พวกเขามีความแตกต่างที่สำคัญ หากคุณมีปัญหาในการค้นหาแหล่งข้อมูลคุณสามารถสร้างคำถามใหม่ได้ที่นี่ ..
Thiago Silva

จูเลียมีหลายวิธีและความแตกต่างของตัวแปรของ Haskell นั้นคล้ายกับหลายวิธี มีวิธีการจำลองหลายวิธีในหลายภาษา ระบบเงื่อนไขเป็นสิ่งที่ฉันต้องการอย่างยิ่งโดยเฉพาะ (แก้ไขและดำเนินการต่อไปแม้ว่าฉันจะเห็นมันสำหรับโปรแกรม debuggers C #)
aoeu256

4

มันไม่จำเป็นต้องเป็นคนเดียวบางคุณลักษณะ มันคือรูปลักษณ์และความรู้สึกโดยรวมและฟีเจอร์บางอย่างทำงานร่วมกันได้อย่างไร

JavaScript หรือ Java มีคุณสมบัติมากมายของ Lisp (เครื่องเสมือน, คอมไพเลอร์ / ผู้ประเมิน, การรวบรวมขยะ ฯลฯ ) แต่ JavaScript เช่นไม่มีส่วนการเขียนโปรแกรมสัญลักษณ์มันขาดความสามารถทางคณิตศาสตร์ (ภายในมีเพียงลอย) มันขาดการจัดการข้อผิดพลาดและอื่น ๆ

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

ตอนนี้บางสิ่งอย่างเช่นจาวาสคริปต์ก็ถูกใช้เพื่อขยายโปรแกรมโดยทั่วไปคือเว็บเบราว์เซอร์ แต่เวลาส่วนใหญ่นั้นไม่ค่อยมีการเขียนโปรแกรมเมตาใน JavaScript - นอกเหนือจากการแฮ็กOOP

ตัวอย่าง:

หนึ่งสามารถใช้ซอฟต์แวร์คณิตศาสตร์ขั้นสูงทั่วไปสำหรับโดเมนของพีชคณิตคอมพิวเตอร์ส่วนใหญ่สองวิธี: เขียนเครื่องยนต์ใน C ด้วยภาษาเฉพาะด้านบน (เช่นMathematica ) หรือในภาษา Lisp ขั้นสูงบางอย่าง Macsyma / Maximaใน Lisp สามัญ, ลดลงใน Lisp มาตรฐาน, Axiomใน Lisp สามัญ

(นอกจากนี้ยังมีการเขียนอย่างน้อยหนึ่งรายการใน Python)

มีระบบไม่มากที่เสนอชุดคุณลักษณะของAxiomซึ่งทำงานบน Common Lisp

สิ่งที่ทำให้ Lisp น่าสนใจสำหรับแอปพลิเคชั่นประเภทนี้คือการผสมผสานของคุณสมบัติ: คณิตศาสตร์พื้นฐานขั้นสูง (bignums, อัตราส่วน, ... ), การคำนวณเชิงสัญลักษณ์, คอมไพเลอร์เชิงโต้ตอบ ฯลฯ เป็นไปได้ค่อนข้างมากที่จะได้รับสิ่งเหล่านี้ ภาษาระดับ ด้วยวิธีนี้เราจะใช้ระบบเสียงกระเพื่อม 50% ขึ้นไป


2

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

: (   41 word drop ; immediate
( That was the definition for the comment word. )
( Now we can add comments to what we are doing! )

1
สนุกเท่าที่ Forth ดูเหมือนว่าจะเป็นฉันมักจะพบว่ามันทึบและไร้ความหวังอย่างไร้เหตุผลบางทีอาจเป็นเพราะมันเป็นแบบกองซ้อนและทุกอย่างกลับด้าน
Robert Harvey

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

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

1
@stonemetal ไม่ต้องกังวล แต่เป็นเรื่องที่ควรสังเกตว่าไม่มีอะไรมาโครเฉพาะเจาะจงเกี่ยวกับการอ้างอิงไวยากรณ์ใน Common LISP หรือ Clojure มันสะดวกบางครั้งจะมี backtick นิพจน์ในคำจำกัดความของฟังก์ชั่นปกติและร่างกายแมโครสามารถสร้างขึ้นด้วยตนเองกับรายการธรรมดา (แม้ว่าคุณจะต้องทำเพียงครั้งนี้ครั้งเดียวหรือสองครั้งเพื่อตัดสินใจว่าไวยากรณ์คำพูดเป็นสิ่งที่ดี!)
แดนนี่วูดส์

1
เพื่อความเป็นธรรมสามารถทำได้ใน Lisp โดยการลงทะเบียนแมโครตัวอ่านที่กำหนดเอง
fjarri

2

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

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


ไม่ทราบว่าจะตรวจสอบออกขอบคุณสำหรับคำตอบของคุณ :)
iceX

7
นี่เป็นสิ่งเดียวกันกับการต่อเนื่องของ Scheme หรือไม่?
Nicola Musatti

1
@NicolaMusatti, "spaghetti stack" เป็นกลยุทธ์การใช้งานทั่วไปสำหรับการดำเนินการต่อเนื่องที่คล้าย Scheme (ซึ่งสามารถเรียกได้หลังจากฟังก์ชั่นที่สร้างพวกเขาได้ส่งคืน)
Alex D
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.