ทำไมชื่อฟังก์ชั่นตัวเลขไม่ได้รับอนุญาต


10

พิจารณาสิ่งต่อไปนี้:

$ ksh -c '1(){ echo hi;};1'
ksh: 1: invalid function name
$ dash -c '1(){ echo hi;};1'
dash: 1: Syntax error: Bad function name
$ bash -c '1(){ echo hi;};1'
bash: `1': not a valid identifier
bash: 1: command not found
$ mksh -c '1(){ echo hi;};1'
hi

โดยทั่วไปผมพยายามที่จะประกาศฟังก์ชั่น1และ0ซึ่งจะเป็น shorthands สำหรับtrueและfalseแต่อย่างที่คุณเห็นฉันวิ่งเข้าไปในปัญหาเกี่ยวกับการใช้ชื่อที่เป็นตัวเลขในการทำงาน พฤติกรรมเดียวกันนี้เกิดขึ้นกับชื่อแทนและชื่อสองหลัก

คำถามคือ "ทำไม" มันคือข้อบังคับโดย POSIX? หรือแค่เปลือกหอยที่มีลักษณะคล้ายบอร์น?

ดูคำถามที่เกี่ยวข้องกับคำถามนี้


1
สิ่งที่ได้รับคำสั่งจาก posix ส่วนใหญ่บางครั้งก็เหมือนหอยเชลล์บอร์น : P
muru

ฉันรู้ว่าคุณทำอะไรที่นั่น . . . > :) lol
Sergiy Kolodyazhnyy

4
@fkraiem โปรดอ้างอิงmeta.askubuntu.com/q/13807/295286 Shells / shell scripting และอยู่เสมอในหัวข้อถาม Ask Ubuntu :) มันเป็นหัวข้อสำคัญในการบริหารระบบที่เหมาะสมของระบบ Ubuntu ใด ๆ
Sergiy Kolodyazhnyy

4
มันน่าสังเกตว่า0เป็นtrueในเปลือกสคริปต์และ1เป็นfalse(จริงๆใด ๆ ที่ไม่ใช่ศูนย์จะถือว่าเป็นเท็จ) ในกรณีที่คนที่อ่านข้อความนี้ไม่ทราบ นี่คือถอยหลังจากภาษาโปรแกรมส่วนใหญ่อื่น ๆ
Ethan Kaminski

2
@EthanKaminski yep เท่าที่สถานะทางออกของคำสั่งนั้นเป็นความจริงอย่างแน่นอน ค่าส่งคืนของ 0 อยู่trueในเปลือก อย่างไรก็ตามใน$((...))สถานะการส่งคืนการขยายเลขคณิตถูกพลิก - 1 คือtrueและ 0 falseสำหรับความสอดคล้องกับไวยากรณ์ภาษา C ลองตัวอย่างเช่นbash -c 'echo $((1==1));echo $((1==2))' สิ่งที่ฉันพยายามทำนอกคำถามนี้จริง ๆ แล้ว "ย้อนกลับ" พฤติกรรม ดูตัวอย่างสุดท้ายของคำตอบที่นี่เพื่อดูว่าฉันพยายามทำอะไร ความคิดที่โง่เง่า แต่กระนั้นผลงาน
Sergiy Kolodyazhnyy

คำตอบ:


14

POSIX พูดว่า:

2.9.5 คำสั่งนิยามฟังก์ชัน

ฟังก์ชั่นเป็นชื่อที่ผู้ใช้กำหนดซึ่งใช้เป็นคำสั่งง่าย ๆ ในการเรียกคำสั่งผสมกับพารามิเตอร์ตำแหน่งใหม่ ฟังก์ชั่นถูกกำหนดด้วย "คำสั่งนิยามฟังก์ชั่น"

รูปแบบของคำสั่งนิยามฟังก์ชันมีดังนี้:

 fname ( ) compound-command [io-redirect ...]

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

และ:

3.235 ชื่อ

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

หมายเหตุ: ชุดอักขระแบบพกพาถูกกำหนดโดยละเอียดในชุดอักขระแบบพกพา

ดังนั้นคำที่ขึ้นต้นด้วยตัวเลขไม่สามารถเป็นชื่อฟังก์ชันได้


ยัง POSIX ไม่ได้ค่อนข้างพูดว่าทำไม แต่ฉันจะใช้มันเป็น "เพราะมาตรฐาน" คำตอบ ขอบคุณ
Sergiy Kolodyazhnyy

4
@SergiyKolodyazhnyy ฉันจะบอกว่ามันเป็นสิ่งที่สืบทอดมา มาตรฐานสำหรับชื่อนี้ค่อนข้างทั่วไปในสิ่งอื่น ๆ เช่นกัน (ชื่อ IIRC C ยังเป็นไปตามมาตรฐานเดียวกัน) ดังนั้นอาจเป็นสิ่ง Unix นอกจากนี้ใน C ยังช่วยให้แยกวิเคราะห์ได้ง่ายขึ้น
muru

3
@muru ใน C จะทำให้เกิดความกำกวมหากได้รับอนุญาต เช่นจะ1Lหมายถึงอะไร ชื่อฟังก์ชั่น? หรือlong intตัวอักษร?
Ruslan

2
การเพิ่มไปยังข้างต้นเป็นสิ่งที่น่าสังเกตว่าใน C ชื่อฟังก์ชันเปล่าสามารถทำหน้าที่เป็นตัวชี้ไปยังฟังก์ชันนั้นได้ สิ่งนี้ช่วยให้คุณสามารถส่งผ่านฟังก์ชั่นเป็นพารามิเตอร์ไปยังฟังก์ชั่นจัดเก็บการอ้างอิงถึงพวกเขาในตัวแปร ฯลฯ มักจะใช้สำหรับการโทรกลับ สิ่งนี้ตรงกันข้ามกับชื่อของฟังก์ชันตามด้วย()อาจมีอาร์กิวเมนต์อยู่ภายในซึ่งหมายถึงการเรียกใช้ฟังก์ชันที่มีปัญหา (และรับค่าที่ส่งคืนโดยฟังก์ชันที่ถูกเรียก) ดังนั้นถ้าคุณมีฟังก์ชั่นint f() { return 42; }ใน C, fถูกต้องในบริบทของตัวชี้และf()ถูกต้องในบริบทที่ไม่ใช่ตัวชี้, จำนวนเต็ม
CVn

13

นั่นเป็นมาตรฐานในหลาย ๆ ภาษาเพื่อป้องกันความสับสนระหว่างการดำเนินการทางคณิตศาสตร์และตัวแปรหรือฟังก์ชั่นหรือวิธีการ

พิจารณา:

var 1 = 100

print 1*10 //should return 10 but would instead return 1000

var x = 5
x += 1
print x //returns 105, not 6    

def 100(num)
  return num * 1000
end

var y = 10 + 100(10)
print y // returns 100010 instead of 1010

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

โดยย่อนี่คือเหตุผลที่ภาษาส่วนใหญ่ไม่อนุญาตให้คุณใช้ตัวเลขเป็นชื่อของตัวแปรหรือฟังก์ชั่นหรือวิธีการหรืออื่น ๆ


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

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

2
@SergiyKolodyazhnyy การขยายเลขคณิตช่วยให้การอ้างอิงชื่อตัวแปรโดยไม่ต้อง$มีดังนั้น แต่ที่อาจจะรองเพื่อเหตุผลอื่น ๆ ของ "ดังต่อไปนี้เป็นเพียงแค่การประชุมทั่วไป"
ฮอบส์

@ ฮอบส์อือเห็นด้วยอย่างยิ่ง
Sergiy Kolodyazhnyy

1
คำอธิบาย "ภาษาส่วนใหญ่" นี้มีความหมายเล็กน้อยสำหรับเชลล์ ทั้งหมดหอยบอร์นสไตล์มีพารามิเตอร์ที่มีชื่อมีลักษณะเหมือนตัวอักษรตัวเลขหรือผู้ประกอบการ: 0เปลือกหรือสคริปต์ชื่อ1, 2, ... , สำหรับพารามิเตอร์ตำแหน่ง*สำหรับพวกเขาเข้าร่วม-สำหรับตัวเลือกที่เปิดใช้งาน?สำหรับสถานะทางออกที่ผ่านมาและ!สำหรับ PID ของงานอะซิงโครนัสล่าสุด (ดังนั้นแม้ใน$(( ))ที่$มักจะจำเป็น.) รหัสที่แสดงที่นี่แสดงให้เห็นถึงเหตุผลที่แนะนำคือไม่สคริปต์สำหรับการใด ๆ บอร์นเชลล์สไตล์เนื่องจากมีวิธีการที่จะแสดงให้เห็นถึงวิธีการที่ไม่เป็นก็ไม่ได้นำไปใช้ในการ พวกเขา
Eliah Kagan

10

ใน C ให้พิจารณาการแสดงออกเช่น:

1000l + 2.0f;

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

และคุณสามารถเห็นเอฟเฟกต์ของอิทธิพล C ได้ตลอดภาษาเชลล์ดังนั้นจึงไม่น่าแปลกใจที่ Bourne shell (หรือ C เชลล์) และด้วยเหตุนี้ POSIX จึง จำกัด คลาสของชื่อที่อนุญาตเช่นเดียวกับของ C


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

@Eliah เนื้อหาตัวเลขเป็นผลโดยตรงจากสถานะทางออกสำหรับความสำเร็จและความล้มเหลวใน C ดังนั้นฉันมักจะคิดในแง่ของความสำเร็จและความล้มเหลวแทนที่จะเป็นเรื่องจริงและเท็จเมื่อเขียนการทดสอบเชลล์ คุณอยู่ในไวยากรณ์เชลล์จำนวนมากนั้นไม่เหมือนกับ C แต่ตัวอย่างรวมถึงเครื่องหมายวงเล็บเซมิโคลอนการลัดวงจร&&และ||การขาดการสนับสนุน ASCII nul ในสตริง
Olorin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.