ความแตกต่างระหว่างภาษาที่พิมพ์อย่างยิ่งและภาษาที่พิมพ์แบบคงที่คืออะไร?


441

อีกคนหนึ่งพูดถึงอีกคนด้วยหรือไม่


8
หมายเหตุใกล้เคียงกันที่stackoverflow.com/questions/2351190/…
Norman Ramsey

4
Tcl พิมพ์อย่างยิ่ง มีเพียงสตริง: P
nawfal

21
@nawfal nah, นั่นคือการพิมพ์อย่างเข้มงวด;)
geekonaut

คำตอบ:


543

ความแตกต่างระหว่างภาษาที่พิมพ์อย่างยิ่งและภาษาที่พิมพ์แบบคงที่คืออะไร?

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

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

คงที่เทียบกับแบบไดนามิก

ตรงกันข้ามของการพิมพ์แบบคงที่คือ "พิมพ์แบบไดนามิก" ซึ่งหมายความว่า

  1. ค่าที่ใช้ ณ รันไทม์ถูกจัดประเภทเป็นประเภท
  2. มีข้อ จำกัด ในการใช้ค่าดังกล่าว
  3. เมื่อมีการละเมิดข้อ จำกัด เหล่านั้นการละเมิดจะถูกรายงานเป็นข้อผิดพลาดประเภท (ไดนามิก)

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

แข็งแรงและอ่อนแอ

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

เกิดอะไรขึ้นที่นี่จริงเหรอ?

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

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

  • เห็นได้ชัดว่า "การพิมพ์ที่อ่อนแอ" ถูกใช้โดยบุคคลบางคนเพื่อพูดคุยเกี่ยวกับความชุกญาติหรือไม่มีการแปลงโดยนัย

  • ผู้เชี่ยวชาญไม่สามารถเห็นด้วยกับสิ่งที่คำว่า

  • โดยรวมแล้วคุณไม่น่าจะแจ้งหรือให้ความกระจ่างแก่ผู้ชมของคุณ

ความจริงที่น่าเศร้าก็คือเมื่อมันมาถึงระบบการพิมพ์"แข็งแรง" และ "อ่อนแอ" ไม่ได้มีการตกลงกันอย่างกว้างขวางเกี่ยวกับความหมายทางเทคนิค หากคุณต้องการพูดคุยเกี่ยวกับความแข็งแกร่งสัมพัทธ์ของระบบประเภทมันจะดีกว่าเพื่อหารือเกี่ยวกับสิ่งที่รับประกันและไม่ได้ให้ ตัวอย่างเช่นคำถามที่ดีที่จะถามคือ: "คือทุกค่าของประเภทที่กำหนด (หรือคลาส) ที่รับประกันว่าจะถูกสร้างขึ้นโดยการเรียกหนึ่งในคอนสตรัคเตอร์ของประเภทนั้น" ใน C คำตอบคือไม่ ใน CLU, F # และ Haskell คือใช่ สำหรับ C ++ ฉันไม่แน่ใจ - ฉันอยากรู้

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

คนหนึ่งพูดถึงอีกคนหนึ่งหรือไม่?

ในระดับอวดรู้ไม่เพราะคำว่า "แข็งแรง" ไม่ได้มีความหมายอะไรเลย แต่ในทางปฏิบัติผู้คนมักทำหนึ่งในสองสิ่งต่อไปนี้:

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

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

ไม่ว่าจะด้วยวิธีใดหากบุคคลเรียกภาษาที่ "พิมพ์อย่างรุนแรง" บุคคลนั้นมีแนวโน้มที่จะพูดถึงภาษาที่พิมพ์แบบคงที่


3
@ Adam: เห็นได้ชัดว่าไม่ถูกต้องพอที่จะถูกคว่ำ :) เนื่องจากคำตอบของ Cletus มีความเข้าใจผิดมากมาย (แม้ว่าฉันจะแก้ไขสิ่งที่เลวร้ายที่สุดของพวกเขา) ฉันรู้สึกว่าถูกสะกดทุกอย่างด้วยคำเดียวพยางค์ ...
Norman Ramsey

1
ดีฉัน upvoting คุณ :) แม้คำว่า "รวบรวม" ไม่ชัดเจนกับ VMs วันนี้ใช้ภาษาแบบไดนามิก ในทางเทคนิค Java และ C # ทั้งสองรวบรวม (JIT) และทั้งสองทำการวิเคราะห์บาง ภาษาเช่น Javascript ที่ทำงานใน. NET vm อาจมีประเภทที่ปลอดภัยมากกว่าเนื่องจาก VM
Adam Gent

2
ตอนนี้ฉันงงแล้ว! โอเคที่รักกลาดิเอเตอร์ที่ดีของเวทีวิญญาณที่น่าสงสารอย่างฉันไปด้วยความเข้าใจง่าย ๆ ดังต่อไปนี้? 1.Static: ค่าจะเชื่อมโยงกับชนิดในระหว่างเวลาคอมไพล์และไม่ใช่เวลารัน 2.Dynamic: ค่าจะเชื่อมโยงกับชนิดในระหว่างรันไทม์ดังนั้นชนิดของค่าสามารถเปลี่ยนแปลงได้ในระหว่างรันไทม์ ~ ดังนั้นจึงมีแนวโน้มที่จะพิมพ์ปัญหาที่เกี่ยวข้องกับการคัดเลือก ระหว่างรันไทม์ 3. แข็งแกร่ง / อ่อนแอ: ลืมมันไปเถอะ! สิ่งเหล่านี้ไม่ใช่ข้อกำหนดทางเทคนิคและระบบการตั้งชื่อไม่ดี ขึ้นอยู่กับบริบทที่เรากำลังพูดถึง ฉันสามารถดำเนินชีวิตของฉันด้วยความเข้าใจง่ายๆนี้ได้ไหม? :(
Saurabh Patil

"ทุกค่าของประเภทที่กำหนด (หรือคลาส) รับประกันว่าถูกสร้างขึ้นโดยการเรียกหนึ่งในตัวสร้างของประเภทนั้นหรือไม่" ใน C คำตอบคือไม่ มีคนให้ตัวอย่างสถานการณ์ที่เกิดขึ้นใน C หรือไม่ ฉันคิดว่ามันเกี่ยวข้องกับการชี้พอยน์เตอร์เพื่อ structs?
corazza

พิมพ์ดีดแข็งแรงและอ่อนแอ: ไม่มีการจำแนกประเภทดังกล่าว
Raúl

248

บ่อยครั้งที่ฉันเข้าใจผิด

การพิมพ์แบบคงที่ / ไดนามิก

การพิมพ์แบบคงที่คือที่ชนิดถูกผูกไว้กับตัวแปร ประเภทจะถูกตรวจสอบในเวลารวบรวม

พิมพ์แบบไดนามิกเป็นที่ที่คนประเภทที่ถูกผูกไว้กับความคุ้มค่า ประเภทจะถูกตรวจสอบในเวลาทำงาน

ดังนั้นใน Java เช่น:

String s = "abcd";

sจะ "ตลอดไป" Stringเป็น ในช่วงชีวิตของมันอาจชี้ไปที่Strings ที่แตกต่างกัน(เนื่องจากsเป็นข้อมูลอ้างอิงใน Java) มันอาจจะมีnullค่า แต่มันจะไม่เคยอ้างถึงหรือInteger Listนั่นคือการพิมพ์แบบคงที่

ใน PHP:

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

นั่นคือการพิมพ์แบบไดนามิก

แข็งแรง / พิมพ์ดีดอ่อนแอ

(แก้ไขการแจ้งเตือน!)

การพิมพ์ที่แข็งแกร่งเป็นวลีที่ไม่มีความหมายที่ตกลงกันอย่างกว้างขวาง โปรแกรมเมอร์ส่วนใหญ่ที่ใช้คำนี้หมายถึงสิ่งอื่นนอกเหนือจากการพิมพ์แบบสแตติกใช้เพื่อบ่งบอกว่ามีระเบียบวินัยประเภทที่บังคับใช้โดยคอมไพเลอร์ ตัวอย่างเช่น CLU มีระบบชนิดที่แข็งแกร่งที่ไม่อนุญาตให้โค้ดไคลเอ็นต์สร้างค่าประเภทนามธรรมยกเว้นโดยใช้ตัวสร้างที่จัดเตรียมโดยชนิด C มีระบบชนิดที่ค่อนข้างแข็งแกร่ง แต่สามารถ "subverted" ถึงระดับหนึ่งได้เนื่องจากโปรแกรมสามารถส่งค่าประเภทตัวชี้หนึ่งไปยังค่าชนิดตัวชี้อื่นได้เสมอ ตัวอย่างเช่นใน C คุณสามารถนำค่าที่ส่งคืนมาmalloc()และนำไปใช้อย่างสนุกสนานFILE*และคอมไพเลอร์จะไม่พยายามหยุดคุณ - หรือแม้แต่เตือนคุณว่าคุณกำลังทำอะไรหลบ ๆ

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

การพิมพ์ที่อ่อนแอหมายความว่าคอมไพเลอร์ไม่บังคับใช้ discpline หรือบางทีการบังคับใช้อาจล้มล้างได้ง่าย

ต้นฉบับของคำตอบนี้พิมพ์ด้วยคำว่าอ่อนแอโดยใช้การแปลงโดยนัย (บางครั้งเรียกว่า "การส่งเสริมโดยนัย") ตัวอย่างเช่นใน Java:

String s = "abc" + 123; // "abc123";

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

String s = "abc" + new Integer(123).toString();

พิจารณาปัญหา "เริ่มต้นด้วย" PHP แบบคลาสสิก:

if (strpos('abcdef', 'abc') == false) {
  // not found
}

ข้อผิดพลาดที่นี่คือการstrpos()ส่งคืนดัชนีของการแข่งขันโดยมีค่าเป็น 0 0 จะถูกรวมเข้ากับบูลีนfalseและทำให้เงื่อนไขเป็นจริง ทางออกคือการใช้===แทน==การหลีกเลี่ยงการแปลงโดยนัย

ตัวอย่างนี้แสดงให้เห็นว่าการผสมผสานการแปลงโดยนัยและการพิมพ์แบบไดนามิกสามารถทำให้โปรแกรมเมอร์หลงทางได้อย่างไร

เปรียบเทียบกับ Ruby:

val = "abc" + 123

ซึ่งเป็นข้อผิดพลาดรันไทม์เพราะใน Ruby วัตถุ 123 ไม่ได้ถูกแปลงโดยปริยายเพราะมันเกิดขึ้นเพื่อส่งผ่านไปยัง+เมธอด ใน Ruby โปรแกรมเมอร์จะต้องทำการแปลงอย่างชัดเจน:

val = "abc" + 123.to_s

การเปรียบเทียบ PHP และ Ruby เป็นภาพประกอบที่ดีที่นี่ ทั้งสองเป็นภาษาที่พิมพ์แบบไดนามิก แต่ PHP มีการแปลงโดยนัยจำนวนมากและ Ruby (อาจแปลกใจถ้าคุณไม่คุ้นเคยกับมัน)

คงที่ / ไดนามิก vs แข็งแกร่ง / อ่อนแอ

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

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

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

แต่สิ่งสำคัญคือต้องเข้าใจว่าภาษาสามารถเป็นแบบคงที่ / เข้มแข็งแบบคงที่ / แบบอ่อนแอแบบไดนามิก / แบบไดนามิกหรือแบบไดนามิก / แบบอ่อน


แทนที่จะบอกว่า $ s เป็นจำนวนเต็มหรือสตริงน่าจะดีกว่าถ้าคุณบอกว่าประเภทนั้นเกี่ยวข้องกับ "abcd" หรือ 1234 ไม่ใช่ตัวแปร $ s
Srinivas Reddy Thatiparthy

คำตอบที่ยอดเยี่ยมพร้อมตัวอย่างที่ชัดเจน อย่างไรก็ตามฉันคิดว่ามันไม่ได้แก้ไขความสับสนอย่างสมบูรณ์ว่าทำไมผู้คนถึงถามถึงความแข็งแกร่ง / คงที่ในฐานะคู่แนวคิด ตัวอย่างเช่นถ้อยคำของ OP ของ "การพิมพ์แบบสแตติก IMPLY strong การพิมพ์หรือไม่" คำตอบของคุณเน้นความเป็นอิสระของพวกเขา เพื่อให้การชี้แจงว่าเหตุใดความแข็งแรงจึงมักจะถูกจับคู่กับไฟฟ้าสถิตคำตอบก่อนหน้าของนอร์แมนแรมซีย์ก็ดีมาก: stackoverflow.com/questions/376611/…
JasDev

1
"abc" + 123เป็นข้อผิดพลาดรันไทม์ไม่ใช่ข้อผิดพลาดในการรวบรวมในทับทิม หากเป็นข้อผิดพลาดในการคอมไพล์ทับทิมจะถูกพิมพ์แบบคงที่
sepp2k

ตัวอย่างการพิมพ์ที่อ่อนแอจำเป็นต้องได้รับการปรับปรุง (ดูคำตอบของฉัน) แต่การจัดรูปแบบที่ดี
Adam Gent

ใน opion strong vs typgin ที่อ่อนแอของฉันคือ: Strong: "c" + True = runtime error หรือข้อผิดพลาดเวลาคอมไพล์ อ่อน: "c" + True = "b" หรือ "d" เพราะทุกอย่างถือว่าเป็นไบต์แบบดิบ แข็งแกร่ง: C #, Ruby, C ++ อ่อนแอ: Assembly, C (เนื่องจากตัวชี้โมฆะโดยปริยาย)
Jonathan Allen

17

ทั้งคู่เป็นเสาที่แตกต่างกันสองแกน:

  • พิมพ์อย่างยิ่งกับพิมพ์อย่างอ่อน
  • พิมพ์แบบคงที่และพิมพ์แบบไดนามิก

หมายถึงพิมพ์อย่างมาก , จะไม่ถูกแปลงโดยอัตโนมัติจากประเภทหนึ่งไปยังประเภทอื่น พิมพ์อ่อนอยู่ตรงข้าม: Perl สามารถใช้สตริงเช่น"123"ในบริบทที่เป็นตัวเลขโดยการแปลงมันโดยอัตโนมัติใน 123int ภาษาที่พิมพ์อย่างรุนแรงเช่น python จะไม่ทำเช่นนี้

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


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

1
ปกติแล้วฉันเห็นด้วยกับโจนาธาน แต่คุณไม่จำเป็นต้องพิมพ์ในรันไทม์เพื่อพิมพ์ถ้าคุณทำการวิเคราะห์แบบสแตติกและไม่อนุญาตให้ส่ง (ดูคำตอบที่แก้ไขของฉัน)
Adam Gent

1
Python เป็นตัวอย่างของการพิมพ์แบบไดนามิกและภาษาที่พิมพ์อย่างมาก
MaRoBet

13

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


ในการสาธิตสิ่งนี้: ในภาษาที่มีการพิมพ์อย่างมากคุณไม่สามารถเปรียบเทียบ "5" == 5 และทำให้เป็นจริงได้: สตริงไม่ใช่จำนวนเต็ม หากหน่วยความจำของฉันทำงานได้ภาษาสคริปต์ที่ทันสมัยส่วนใหญ่จะถูกพิมพ์แบบไดนามิกอย่างมาก Tcl / Tk อย่างไรก็ตามพิมพ์อย่างอ่อน - ทุกสิ่งสามารถถือเป็นสตริงได้
Bobby น้อย Tables

บ๊อบบี้ในภาษาที่พิมพ์อย่างอ่อน "5" == 5 อ่านเป็น 0x35 == 0x05 หรือในคำอื่น ๆ ทุกอย่างจะถือว่าเป็นไบต์ดิบ
Jonathan Allen

ฉันต้องไม่เห็นด้วยกับคุณทั้งคู่ ใช้ Lua; คุณสามารถเปรียบเทียบ "5" == 5 และมันจะกลับเท็จ แต่การแปลงอย่างรวดเร็วสามารถทำได้โดยไปที่ "5" + 0.
RCIX

12

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

ตัวอย่างด้านบนของ Java ถูกพิมพ์อย่างอ่อนเนื่องจาก

String s = "abc" + 123;

ไม่ได้เป็นตัวอย่างที่พิมพ์ออกมาไม่ดีนักเพราะมันกำลังทำอยู่:

String s = "abc" + new Integer(123).toString()

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

นี่คือสิ่งที่แตกต่างจาก C. C เป็นหนึ่งในตัวอย่างที่ดีที่สุดของการพิมพ์ที่อ่อนแอ รันไทม์ไม่มีความคิดถ้า 4 ไบต์เป็นจำนวนเต็ม struct ตัวชี้หรือ 4 ตัวอักษร

รันไทม์ของภาษากำหนดว่าจริง ๆ หรือไม่พิมพ์อ่อนอย่างนั้นมันเป็นเพียงความเห็น

แก้ไข: หลังจากคิดเพิ่มเติมนี้ไม่จำเป็นต้องเป็นจริงเพราะ runtime ไม่จำเป็นต้องมีชนิดทั้งหมด reified ในระบบ runtime เป็นระบบที่พิมพ์อย่างรุนแรง Haskell และ ML มีการวิเคราะห์แบบสแตติกที่สมบูรณ์ซึ่งพวกเขาสามารถได้ข้อมูลประเภท ommit จากรันไทม์


B น่าจะดีกว่าถ้าเป็นตัวอย่างที่รู้จักกันน้อย
Tom Hawtin - tackline

Javascript เป็นประเภทที่ค่อนข้างอ่อนแอ แต่เนื่องจากมีเพียงไม่กี่ประเภทและเนื่องจากคุณไม่สามารถสร้างประเภทใหม่ได้
Adam Gent

10

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

VS ที่พิมพ์อย่างอ่อนคืออะไร

พิมพ์อย่างมาก: จะไม่ถูกแปลงโดยอัตโนมัติจากประเภทหนึ่งเป็นประเภทอื่น

ใน Go หรือ Python เช่นภาษาที่พิมพ์อย่างยิ่ง "2" + 8 จะทำให้เกิดข้อผิดพลาดประเภทเนื่องจากไม่อนุญาตให้ใช้ "type coercion"

Weakly (loosely) Typed: จะถูกแปลงเป็นประเภทหนึ่งเป็นอีกประเภทโดยอัตโนมัติ: ภาษาที่พิมพ์อย่างอ่อนเช่น JavaScript หรือ Perl จะไม่เกิดข้อผิดพลาดและในกรณีนี้ JavaScript จะให้ผลลัพธ์ '28' และ perl จะส่งผลให้ 10

ตัวอย่าง Perl:

my $a = "2" + 8;
print $a,"\n";

บันทึกลงใน main.pl และเรียกใช้perl main.plแล้วคุณจะได้รับผลลัพธ์ 10

Static VS Dynamic เป็นประเภทใด

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

  • คงที่: ประเภทที่ตรวจสอบก่อนเวลาทำงาน
  • แบบไดนามิก: ชนิดที่ตรวจสอบได้ทันทีขณะดำเนินการ

นี่หมายถึงอะไร?

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

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

บันทึกไฟล์นี้ใน main.go และเรียกใช้คุณจะได้รับการรวบรวมข้อความล้มเหลวสำหรับเรื่องนี้

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

แต่กรณีนี้ใช้ไม่ได้กับ Python ตัวอย่างเช่นการบล็อกรหัสต่อไปนี้จะดำเนินการสำหรับการโทร foo (2) ครั้งแรกและจะล้มเหลวสำหรับการโทร foo (0) ครั้งที่สอง มันเป็นเพราะ Python ถูกพิมพ์แบบไดนามิกมันจะแปลและพิมพ์รหัสตรวจสอบที่มันทำงานอยู่เท่านั้น บล็อกอื่นจะไม่ดำเนินการกับ foo (2) ดังนั้น "2" + 8 จะไม่เคยดูแม้แต่และสำหรับ foo (0) การเรียกมันจะพยายามเรียกใช้บล็อกนั้นและล้มเหลว

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

คุณจะเห็นผลลัพธ์ต่อไปนี้

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects

8

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

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


7

การพิมพ์ที่รัดกุมอาจหมายความว่าตัวแปรมีประเภทที่กำหนดไว้อย่างดีและมีกฎที่เข้มงวดเกี่ยวกับการรวมตัวแปรประเภทต่าง ๆ ในนิพจน์ ตัวอย่างเช่นถ้า A เป็นจำนวนเต็มและ B เป็นทศนิยมดังนั้นกฎที่เข้มงวดเกี่ยวกับ A + B อาจเป็นได้ว่า A ถูกส่งไปที่ float และผลลัพธ์ที่ส่งกลับเป็น float ถ้า A เป็นจำนวนเต็มและ B เป็นสตริงกฎที่เข้มงวดอาจเป็นว่า A + B ไม่ถูกต้อง

การพิมพ์คงที่อาจหมายถึงประเภทที่กำหนดในเวลารวบรวม (หรือเทียบเท่าสำหรับภาษาที่ไม่ได้รวบรวม) และไม่สามารถเปลี่ยนแปลงได้ในระหว่างการดำเนินการโปรแกรม

โปรดทราบว่าการจำแนกประเภทเหล่านี้ไม่ได้เกิดขึ้นพร้อมกันโดยเฉพาะฉันคาดว่าพวกเขาจะเกิดขึ้นพร้อมกันบ่อยครั้ง ภาษาที่พิมพ์จำนวนมากยังมีการพิมพ์แบบคงที่

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

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