Tại sao tên hàm số không được phép?


10

Hãy xem xét những điều sau đây:

$ 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

Về cơ bản, tôi đã cố gắng để khai báo các chức năng 10đó sẽ là shorthands cho truefalse, nhưng như bạn có thể thấy tôi chạy vào vấn đề với việc sử dụng tên số trong chức năng. Hành vi tương tự xảy ra với bí danh và tên hai chữ số.

Câu hỏi là "tại sao"? Được ủy quyền bởi POSIX? hoặc chỉ là một sự châm biếm của vỏ như bourne?

Xem thêm câu hỏi liên quan đến câu hỏi này.


1
Những thứ được ủy nhiệm bởi posix chủ yếu là đôi khi là những vỏ sò giống như Bourne. : P
muru

Tôi thấy những gì bạn đã làm ở đó . . . > :) lol
Sergiy Kolodyazhnyy

4
@fkraiem Vui lòng tham khảo meta.askubfox.com/q/13807/295286 Kịch bản shell / shell và luôn luôn là chủ đề trên Ask Ubuntu :) Đây là một chủ đề thiết yếu để quản trị hệ thống phù hợp cho bất kỳ hệ thống Ubuntu nào
Sergiy Kolodyazhnyy

4
Nó đáng chú ý là 0truetrong kịch bản shell và 1false(thực sự, bất kỳ khác không được coi là sai), trong trường hợp bất cứ ai đọc sách này không hề biết. Điều này là ngược từ hầu hết các ngôn ngữ lập trình khác.
Ethan Kaminski

2
@EthanK Vitaminki yep, theo như trạng thái thoát lệnh , điều đó hoàn toàn đúng. Giá trị trả về 0 là truetrong vỏ. Tuy nhiên, trong $((...))trạng thái trả về mở rộng số học được lật - 1 là truevà 0 là falseđể thống nhất với cú pháp ngôn ngữ C. Hãy thử ví dụ bash -c 'echo $((1==1));echo $((1==2))' Những gì tôi đã cố gắng thực hiện ngoài câu hỏi này thực sự là "đảo ngược" hành vi. Xem ví dụ cuối cùng về câu trả lời của tôi ở đây để xem chính xác những gì tôi đã cố gắng làm. Ý tưởng ngớ ngẩn, nhưng dù sao cũng hoạt động
Sergiy Kolodyazhnyy

Câu trả lời:


14

POSIX nói:

2.9.5 Lệnh định nghĩa hàm

Hàm là tên do người dùng định nghĩa, được sử dụng như một lệnh đơn giản để gọi lệnh ghép với các tham số vị trí mới. Một hàm được định nghĩa bằng "lệnh định nghĩa hàm".

Định dạng của lệnh định nghĩa hàm như sau:

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

Hàm được đặt tên là fname ; ứng dụng phải đảm bảo rằng đó là một tên (xem Tên XBD ) và đó không phải là tên của một tiện ích tích hợp đặc biệt. Việc triển khai có thể cho phép các ký tự khác trong tên hàm dưới dạng phần mở rộng. Việc thực hiện sẽ duy trì các không gian tên riêng cho các hàm và biến.

Và:

3.235 Tên

Trong ngôn ngữ lệnh shell, một từ chỉ bao gồm dấu gạch dưới, chữ số và bảng chữ cái từ bộ ký tự di động. Ký tự đầu tiên của tên không phải là chữ số.

Lưu ý: Bộ ký tự di động được xác định chi tiết trong Bộ ký tự di động.

Vì vậy, một từ bắt đầu bằng một chữ số không thể là một tên hàm.


Vẫn còn POSIX không nói rõ tại sao, nhưng tôi sẽ coi đó là câu trả lời "Vì tiêu chuẩn". Cảm ơn
Sergiy Kolodyazhnyy

4
@SergiyKolodyazhnyy Tôi muốn nói rằng đó là một điều được thừa hưởng. Tiêu chuẩn này cho tên cũng khá phổ biến trong những thứ khác (tên II II C cũng theo cùng tiêu chuẩn), vì vậy có lẽ đó là một thứ Unix. Ngoài ra, trong C, nó giúp phân tích cú pháp dễ dàng hơn
muru

3
@muru trong C nó sẽ mang lại sự mơ hồ nếu được phép. Ví dụ, điều đó 1Lcó nghĩa là gì? Tên hàm? Hay một long intnghĩa đen?
Ruslan

2
Thêm vào ở trên, đáng chú ý là trong C, một tên hàm trần có thể hoạt động như một con trỏ tới hàm đó. Điều này cho phép bạn truyền các hàm dưới dạng tham số cho một hàm, lưu trữ các tham chiếu đến chúng trong các biến, v.v. Thường được sử dụng cho các cuộc gọi lại. Điều này trái ngược với tên của hàm theo sau (), có thể có các đối số bên trong, biểu thị một cuộc gọi đến hàm đang được đề cập (và nhận giá trị được trả về bởi hàm được gọi). Vì vậy, nếu bạn có một hàm int f() { return 42; }trong C, fhợp lệ trong ngữ cảnh con trỏ và f()hợp lệ trong ngữ cảnh số nguyên, không con trỏ.
một CVn

13

Đó là một tiêu chuẩn trong nhiều ngôn ngữ để ngăn ngừa sự nhầm lẫn giữa các phép toán và các biến hoặc hàm hoặc phương thức.

Xem xét:

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

Như bạn có thể thấy, nếu các số được cho phép dưới dạng tên biến hoặc hàm, thì việc làm toán sau này trong một chương trình có thể trở nên rất khó hiểu và bạn sẽ phải đưa ra cách giải quyết sáng tạo nếu bạn cần thực sự làm toán với những số đó sau này. Nó cũng có thể tạo ra kết quả bất ngờ trong một số ngôn ngữ. Hãy tưởng tượng bạn đang tăng một số cho một vòng lặp nhưng một trong các chữ số đã là một biến bằng một chuỗi. Nó sẽ ngay lập tức ném một lỗi. Nếu bạn không phải là tác giả gốc của mã, lỗi đó có thể mất khá nhiều thời gian để tìm.

Tóm lại, đây là lý do tại sao hầu hết các ngôn ngữ không cho phép bạn sử dụng một số làm tên của một biến hoặc hàm hoặc phương thức, v.v.


Tôi sẽ bình luận "nhưng các biến trong shell cần được $chuẩn bị cho việc mở rộng" nhưng sau đó một lần nữa nếu shell được lấy cảm hứng từ các ngôn ngữ khác, tôi đoán vậy, cộng với ((các biến mở rộng số học không bắt buộc phải có $. OK, tôi có thể hiểu điều đó
Sergiy Kolodyazhnyy

3
Vâng, đó là một quy ước bởi vì nó sẽ tạo ra kết quả bất ngờ ở hầu hết mọi ngôn ngữ, nhưng, ngay cả trong tình huống nó sẽ hoạt động, nó có thể tạo mã rất khó hiểu cho bất kỳ ai phải làm việc với mã của bạn sau bạn.
Josh

2
@SergiyKolodyazhnyy mở rộng số học cho phép tham chiếu các tên biến mà không có $, vì vậy có. Nhưng đó có lẽ là thứ yếu so với lý do khác của "chỉ theo quy ước chung"
hobbs

@hobbs yep, hoàn toàn đồng ý với điều đó
Sergiy Kolodyazhnyy

1
Giải thích "hầu hết các ngôn ngữ" này không có ý nghĩa gì đối với đạn pháo. Tất cả vỏ Bourne kiểu có thông số có tên giống như chữ số hoặc các nhà khai thác: 0cho tên vỏ hay kịch bản, 1, 2, ..., cho tham số vị trí, *cho họ tham gia, -cho các tùy chọn được kích hoạt, ?cho tình trạng xuất cuối cùng, và !cho Công việc không đồng bộ gần đây nhất của PID. (Do đó, ngay cả trong $(( )), $thường là cần thiết.) Mã được hiển thị ở đây để chứng minh lý do được đề xuất không phải là tập lệnh cho bất kỳ trình bao kiểu Bourne nào, vì không có cách nào để chứng minh điều đó, vì nó không áp dụng cho họ
Eliah Kagan

10

Trong C, hãy xem xét một biểu thức như:

1000l + 2.0f;

1000lmột biến hay một hằng số? Bởi vì tên biến không thể bắt đầu bằng một chữ số, nó phải là một hằng số. Điều này làm cho việc phân tích cú pháp dễ dàng và chặt chẽ hơn (lỗi chính tả 1000kcó thể dễ dàng bắt gặp). Cũng dễ dàng hơn để có một quy tắc duy nhất cho các biến và tên hàm, vì các hàm cũng có thể được coi là biến. Bây giờ tất nhiên, các trình phân tích cú pháp phức tạp và mạnh mẽ hơn nhiều, và chúng ta có những thứ như chữ tùy chỉnh trong C ++. Nhưng trở lại thời xa xưa của thời tiền sử, hy sinh một chút linh hoạt không cần thiết có thể khiến thời gian biên dịch (hoặc diễn giải) của bạn ngắn hơn nhiều (và mọi người vẫn phàn nàn về thời gian biên dịch C ++).

Và bạn có thể thấy tác động của ảnh hưởng C trong ngôn ngữ hệ vỏ, vì vậy không có gì đáng ngạc nhiên khi vỏ Bourne (hoặc vỏ C) và do đó, POSIX, đã giới hạn loại tên được phép giống như của C.


2
Theo giải thích , đây là một trong những chính xác. Không phải các cân nhắc giống nhau áp dụng cho tất cả các ngôn ngữ hoặc các vỏ kiểu Bourne có cú pháp tương tự như của C, nhưng văn hóa liên quan đến C rất mạnh và các nhà thiết kế vỏ phải đưa ra một số đảm bảo về định danh sẽ là gì được phép Tôi nghĩ rằng điều này có thể sử dụng các ví dụ về "bạn có thể thấy tác động của ảnh hưởng C trong ngôn ngữ hệ vỏ", vì sự tương đồng giữa chúng thực sự không vượt trội so với sự khác biệt ( ví dụ, nghĩ về những con số được coi là đúng ). Tuy nhiên, câu trả lời này là chính xác.
Eliah Kagan

@Eliah có thể cho rằng điều số cũng là hậu quả trực tiếp của các trạng thái thoát thành công và thất bại trong C, vì vậy tôi có xu hướng suy nghĩ về mặt thành công và thất bại thay vì đúng và sai khi viết bài kiểm tra vỏ. Bạn đúng với rất nhiều cú pháp shell không giống như C, nhưng các ví dụ bao gồm dấu ngoặc nhọn, dấu chấm phẩy, ngắn mạch &&||, thiếu sự hỗ trợ cho chuỗi ASCII trong chuỗi,
Olorin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.