Tôi đang viết về cú pháp ngôn ngữ. Có một ngôn ngữ ngoài đó trong đó các tham số được đặt bên trong tên phương thức?


29

trong JavaScript:

function getTopCustomersOfTheYear(howManyCustomers, whichYear) {
   // Some code here.
}
getTopCustomersOfTheYear(50, 2010);

trong C #:

public List<Customer> GetTopCustomersOfTheYear(int howManyCustomers, 
 int whichYear)
{
   // Some code here
}
List<Customer> customers = GetTopCustomersOfTheYear(50, 2010);

trong PHP:

public function getTopCustomersOfTheYear($howManyCustomers, $whichYear)
{
   // Some code here
}
$customers = getTopCustomersOfTheYear(50, 2010);

Có ngôn ngữ nào ngoài đó hỗ trợ cú pháp này không:

function GetTop(x)CustomersOfTheYear(y)
{
    // Some code here
}
returnValue = GetTop(50)CustomersOfTheYear(2010);

Nó không phải là hình thức văn bản hơn, dễ đọc hơn để viết một chức năng?

Cập nhật: Lý do tôi hỏi câu hỏi này là vì tôi đang viết một bài viết về một cú pháp mới cho một ngôn ngữ mới. Tuy nhiên, tôi nghĩ rằng việc có cú pháp như vậy để khai báo các phương thức có thể đẹp hơn và thân thiện hơn với các nhà phát triển và sẽ làm giảm quá trình học ngôn ngữ, vì gần gũi hơn với ngôn ngữ tự nhiên. Tôi chỉ muốn biết liệu tính năng này đã được dự tính hay chưa.


12
Nó có thể dễ đọc hơn, một khi bạn đã quen với thành ngữ này, nhưng dường như với tôi, thật khó để viết một trình phân tích cú pháp chính xác cho điều đó.
Mason Wheeler

2
Bạn có ý nghĩa gì bởi "giữ chỗ?" Câu hỏi này khó hiểu như được đặt ra, mặc dù ví dụ mã cuối cùng gợi nhớ đến Objective-C và SmallTalk.
greyfade

3
AFAIK Smalltalk là ngôn ngữ đầu tiên sử dụng cú pháp này hoàn toàn thích 'hello world' indexOf: $o startingAt: 6hoặc Rectangle width: 100 height: 200. Btw., Có gì sai với câu hỏi này?
maaartinus

8
Nếu bạn di chuyển dấu ngoặc đơn, bạn sẽ nhận được: returnValue = GetTop(50, CustomersOfTheYear(2010))có vẻ như tôi có thể đọc được và thực sự linh hoạt / trực giao hơn. ... Và vâng, đó là cú pháp bình thường.
dagnelies

2
@arnaud: Tôi hoàn toàn đồng ý. Cú pháp đề xuất chỉ là một cách giải quyết cho việc thiếu phân tách.
back2dos

Câu trả lời:


41

Vâng, và vâng. Vâng, có một ngôn ngữ như vậy, và vâng, nhiều người thấy nó dễ đọc hơn một khi họ đã quen với nó.

Trong Objective-C, phương thức sẽ là:

- (NSArray*)getTop:(int)count customersOfTheYear:(Year)year;

Đó thực sự là một ví dụ khá giả tạo mà không đọc rất tốt, vì vậy đây là một ví dụ tốt hơn từ mã thực tế:

+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;

Đó là nguyên mẫu cho một phương thức trả về một thể hiện UIColor mới bằng cách sử dụng các giá trị đỏ, lục, lam và alpha. Bạn sẽ gọi nó như thế này:

UIColor *violet = [UIColor colorWithRed:0.8 green:0.0 blue:0.7 alpha:1.0];

Đọc thêm về tên thông báo với các tham số xen kẽ trong Ngôn ngữ lập trình Objective-C .


16
Lần đầu tiên tôi đọc về nó trong Objective CI nghĩ rằng nó rất thông minh, nhưng thực tế nó được đặt tên là các tham số trở nên cứng hơn và khó quản lý hơn. Ngoài ra, câu trả lời tốt.
ZJR

2
Một ví dụ về cách phương thức được gọi sẽ không đi được.
greyfade

3
@ZJR, mặc dù ý kiến ​​của Wikipedia ngược lại , phong cách của Obj-C giống như các tham số được đặt tên, nhưng khác nhau. Trong ví dụ trên, tên phương thức là : +colorWithRed:blue:green:alpha:. Tôi tình cờ sử dụng tên cho các thông số phù hợp với phương pháp này, nhưng tôi có thể dễ dàng đã sử dụng r, b, g, và a. Với các tham số được đặt tên như ưu đãi JavaScript, bạn sẽ sử dụng tên thực tế được cung cấp để truy cập các giá trị. Các tham số tên thật cũng thường có thể được cung cấp theo bất kỳ thứ tự nào và các tham số có thể là tùy chọn. Tương tự như vậy, có, nhưng về cơ bản là khác nhau.
Caleb

2
Tôi đã suy nghĩ python: color(r=0xFF,g=0xFF,b=0x55)hoặc color(b=0x32,r=0x7F,a=.5,g=0xFF)như vậy. Chúng ta hãy gọi những tham số rất được đặt tên , sau đó. :)
ZJR

3
@ZJR, ví dụ về con trăn của bạn là đúng - đó chính xác là những gì tôi gọi là "tham số được đặt tên." Tôi chỉ nói rằng Obj-C thực sự không cung cấp cho bạn điều đó. Cú pháp trông rất giống các tham số có tên của JavaScript vì phương thức được chia thành các phần và mỗi phần có dấu hai chấm, nhưng thực sự không phải vậy . Các tên trong Obj-C là một phần của tên phương thức, không phải là tên có thể được sử dụng để chỉ các tham số trong quá trình thực hiện; vấn đề trật tự; tham số không tùy chọn. Tôi nghi ngờ có lẽ chúng ta đồng ý nhiều hơn không.
Caleb

25

Trả lời: smalltalk

http://en.wikipedia.org/wiki/Smalltalk

'hello world' indexOf: $o startingAt: 6 giống như của Java "hello world".indexOfStartingAt(o, 6)

Rectangle width: 100 height: 200 giống như của Java new Rectangle(100, 200)

Cú pháp là ... expression word1: parm1 word2: parm2 word3: parm3 ...Tên của phương thức được gọi là nối của tất cả các từ.


17

Tôi tin rằng bạn đang tìm kiếm sự trừu tượng có tên là " giao diện lưu loát (Tôi xin đưa ra một nhận xét, ban đầu được thực hiện bởi @Jesper, để" trả lời ")." Mô hình phổ biến hiện nay đã được triển khai thành công ở nhiều ngôn ngữ, trong đó Objective-C chỉ là một ngôn ngữ.

Đây là một ví dụ khá sạch sẽ:

Person bo = new Person();
bo.Set.FirstName("Bo").LastName("Peep").Age(16).Size("Little").LostHerSheep();

Bạn có thể thấy một cái gì đó như thế này có thể được thực hiện trong Randy PattersonLàm thế nào để thiết kế một giao diện thông thạo .

Andre Vianna đưa ra một lịch sử ngắn gọn và sau đó thảo luận về các triển khai có thể có trong hai phần bài viết khác, bao gồm nhiều thông tin hữu ích. Vianna chỉ lại ý tưởng cũ mà tôi gặp lần đầu tiên trong Smalltalk 80 được gọi là " xếp tầng ", cho phép gửi nhiều tin nhắn đến cùng một đối tượng. Nó trông như thế này:

aThing one: 'one';
  two: 'two';
  other.

Cascading sau đó đã phát triển thành " chuỗi phương thức ", trong đó chúng tôi " Tạo các phương thức sửa đổi trả về đối tượng máy chủ, để nhiều bộ sửa đổi có thể được gọi trong một biểu thức. " Phương thức chuỗi sau này lớn lên để trở thành khái niệm giao diện trôi chảy mà chúng ta biết và sử dụng thường xuyên ngày nay . Những gì bạn dự định làm trông rất giống nhau.

Ayende Rahien thảo luận về việc "giao diện lưu loát" có thể khác biệt đáng kể so với "chuỗi phương thức" để xứng đáng với tên riêng của nó .

Giao diện lưu loát thường thấy trong một số công cụ mới được sử dụng trong phát triển theo hướng hành vi (BDD) và thậm chí đã tìm được đường đến NUnit , một công cụ kiểm tra đơn vị .NET chính, trong Mô hình khẳng định dựa trên ràng buộc mới của nó .

Các cách tiếp cận cơ bản này sau đó đã được triển khai bằng các ngôn ngữ khác, bao gồm Ruby, Python, C #, Objective-C và Java . Để thực hiện một cái gì đó tương tự, bạn sẽ muốn nghiên cứu về ý tưởng " đóng cửa ", điều này khá cơ bản đối với chuỗi và sự trôi chảy.

Có lẽ bạn có thể cải thiện các mô hình này; đó là cách chúng tôi có được những ngôn ngữ mới tuyệt vời. Tuy nhiên, tôi tin rằng sự hiểu biết đầy đủ về phương pháp kết nối và giao tiếp trôi chảy sẽ cho bạn một điểm khởi đầu tuyệt vời để từ đó phát triển ý tưởng của bạn!


2
+1 cho hầu hết câu trả lời được nghiên cứu cho đến nay, mặc dù việc thêm các ví dụ và từ ngữ lại cho khả năng đọc có thể giúp ích.
haylem

@haylem, cảm ơn bạn đã khiến tôi quay lại và thêm ví dụ và chi tiết hơn một chút!
John Tobler

3
Được nâng cấp bởi vì đó là một mô tả hay về phong cách trôi chảy, nhưng xin lưu ý rằng đây thực sự không phải là những gì OP đang hỏi về. Khi tôi đọc nó, câu hỏi liên quan đến các tham số xen kẽ với các phần của tên của một chức năng hoặc phương thức duy nhất . Lưu ý khai báo hàm đề xuất : function GetTop(x)CustomersOfTheYear(y). Đây là một chức năng duy nhất, không xâu chuỗi các cuộc gọi đến hai chức năng khác nhau.
Caleb

@Caleb Tôi nghĩ rằng ở đây anh ấy đang cố gắng chỉ ra rằng các tham số infix này là một cách không linh hoạt để thực hiện giao diện trôi chảy (câu trả lời này) hoặc tham số được đặt tên (câu trả lời khác). Cho đến nay tôi chưa thấy bất kỳ lợi thế nào cho họ rằng giao diện trôi chảy / tham số được đặt tên không thể làm tốt hơn.
Izkata

16

Mục tiêu-C làm điều đó. Đây là một nguyên mẫu điển hình:

- (void) areaWithHeight: (float) height andWidth: (float) width;

Đây là cách bạn gọi một phương thức như vậy:

float area = [self areaWithHeight: 75 andWidth: 20];

Objective-C chủ yếu được sử dụng với Cốc Cốc cho Mac OS X và Cốc Cốc cảm ứng cho iOS, nhưng gcc sẽ xây dựng mã Objective-C trên mọi nền tảng mà gcc hoạt động.


Xin lỗi viên đạn đó nên là một dấu gạch nối. Tôi đoán dấu gạch nối trong văn bản trả lời được lấy làm đánh dấu. Các dấu gạch ngang trong Objective-C được sử dụng để khai báo các phương thức thuộc về một đối tượng - [foo bar: x] trong đó foo là một đối tượng hoặc thể hiện lớp - trong khi các dấu cộng được sử dụng cho các phương thức lớp, C ++ gọi là các hàm thành viên tĩnh.
Mike Crawford

13

Trong Common lisp, bạn có thể xác định đối số từ khóa cho một hàm như thế này:

(defun area (&key width height)
    (* width height))

Hàm được gọi như thế này:

(area :width 2 :height 3)

Trong Ada, bạn không cần một tuyên bố đặc biệt - bạn có thể gọi bất kỳ thủ tục hoặc hàm thay thế bằng cách liệt kê các đối số theo thứ tự hoặc bằng cách đặt tên các đối số như thế này:

a := area(width => 2, height => 3);

Cuối cùng, thư viện boost bao gồm một lớp hack để thêm tính năng vào C ++: http://www.boost.org/doc/libs/release/libs/parameter/doc/html/index.html


5

Tôi không thể tìm thấy tên của nó, nhưng có một mẫu thiết kế để thực hiện một cái gì đó tương tự, trong đó một lệnh gọi hàm trả về một đối tượng mới được sửa đổi như mô tả. Ví dụ:

query = db.getTopCustomers(50).forYear(2010);

Nó không được sử dụng rất thường xuyên vì dữ liệu của bạn phải rất trực giao để tránh sự phức tạp không thể quản lý được dưới mui xe, nhưng có thể hữu ích trong trường hợp phù hợp.


6
Đây được gọi là phong cách thiết kế giao diện trôi chảy .
Jesper

@Jesper, những gì tôi thấy rất giống với chuỗi xích jQuery. Tôi có đúng không
Saeed Neamati

Có, @Saeed, jQuery sử dụng phong cách này.
Karl Bielefeldt

5

Python có các tham số từ khóa. Ví dụ định nghĩa hàm

def getTopCustomers(count,year):
...

Ví dụ gọi hàm

x = getTopCustomers(year=1990, count=50)

(Tôi hiểu rằng điều này không hoàn toàn theo tinh thần của câu hỏi ban đầu, nhưng nếu các tham số từ khóa không đủ điều kiện, thì hãy làm điều này. Tuy nhiên, trong Smalltalk và Objective-C .)


Cá nhân tôi thích điều này hơn, vì điều này cho bạn tùy chọn gọi hàm mà không có tên tham số nếu bạn biết thứ tự của các tham số
Pablo Mescher

4

Agda có ký hiệu mixfix

if_then_else x y z = case x of
                     True -> y
                     False -> z

 if cond then x else y

Bất cứ khi nào hàm được đặt tên với dấu gạch dưới, nó có thể được chia thành hai phần với một đối số ở giữa


4

Mặc dù không phải là ngôn ngữ lập trình mỗi se , Cucumber lấy tham số ở giữa tên hàm, có thể bao gồm khoảng trắng và có nghĩa là trông giống tiếng Anh.

Các 'hàm' được định nghĩa trong Ruby tuy nhiên

# definition
Given /^I calculate (.*) times (.*)$/ do |x, y|
    @result = x.to_i * y.to_i
end

Then /^the result should be (.*)$/ do |v|
    @result.should == v.to_i
end

# usage
Scenario:
    Given I calculate 6 times 9
    Then the result should be 42

4

Trong TeX, bạn có thể xác định các macro có mẫu đối số của người dùng, điều đó có nghĩa là giao thức gọi của bạn là miễn phí. Ví dụ cụ thể của bạn, bạn có thể sử dụng

\def\getTopCustomers#1OfTheYear#2;{%
  The #1 top customers of the year #2.
}
\getTopCustomers 50 OfTheYear 2010;

Lưu ý rằng cũng có thể thoát khỏi ;nếu bạn đồng ý chơi với các thanh ghi:

\newcount\customers
\newcount\year
\def\getTopCustomers#1OfTheYear{%
  \customers#1\relax
  \afterassignment\reallyGetTopCustomersOfTheYear
  \year
}
\def\reallyGetTopCustomersOfTheYear{%
  The {\the\customers} top customers of the year {\the\year}.
}
\getTopCustomers 50 OfTheYear 2010

TeX cho phép bạn cấu hình lại từ vựng của nó và nhờ vào \afterassignmentmacro tôi đã sử dụng ở trên, bạn có thể sử dụng các quy trình tích hợp để lex số. Nó rất hữu ích để xác định các giao thức gọi rất ngắn gọn . Ví dụ, rất hợp lý khi viết các macro TeX hiểu ký hiệu Markdown cho các bảng.

Bây giờ bạn hỏi làm thế nào để tôi truy cập cơ sở dữ liệu của mình, nơi khách hàng được lưu trữ từ TeX?, Nhưng đây là một câu hỏi khác. :)

Trong Common lisp, điều này chắc chắn có thể xác định một querymacro cho phép bạn viết

(query getTopCustomers 50 OfTheYear 2010)

trong đó getCustomers và OfTheYear được hiểu là các biểu tượng. Đó là công việc của vĩ mô để làm cho ý nghĩa của nó. Common lisp là tuyệt vời trong lĩnh vực dễ đọc mã (vâng, ý tôi là vậy!) Bởi vì hệ thống macro cho phép dễ dàng tạo các ngôn ngữ giả được điều chỉnh cho ứng dụng của bạn. (Tôi nghĩ chúng được gọi là ngôn ngữ ứng dụng.)

PS: Có vẻ như không ai trích dẫn C ++. Gần nhất bạn có thể nhận được (không có bộ xử lý trước) là

query.getTopCustomers(50).OfTheYear(2010):

mẹo là để getTopCustomerstrả về một tham chiếu trên query(hoặc bất cứ điều gì khác) cũng thực hiện OfTheYear. Bạn có thể xây dựng ví dụ này lên đến một ngôn ngữ truy vấn nhỏ nhưng sau đó bạn phải xác định các thuộc tính cuối cùng (trả về một giá trị) hoặc thêm một finalisephương thức (thực hiện tra cứu và trả về giá trị). Nếu bạn cảm thấy thích nó, bạn cũng có thể bắt chước các bộ điều khiển luồng của STL và có thể viết những thứ như

query << getTopCustomers(50) << OfTheYear(2010) << flush;

nhưng điều này một lần nữa đi theo hướng của ngôn ngữ ứng dụng.

Chỉnh sửa: Tôi bỏ qua câu trả lời @han, cũng trích dẫn Lisp và C ++ thông thường (nhưng không phải TeX!).


2

Trong JavaScript hoặc bất kỳ ngôn ngữ khác mà hỗ trợ đóng cửa, bạn có thể cà ri một chức năng như thế này:

function getTopCustomersFunc(count) {
    return function(year) {
       // run some query, return count customers from year
    }
}
var top20Func = getTopCustomersFunc(20);
var top20Customers2005 = top20Func(2005);
var top20Customers2008 = top20Func(2008);

1
+1 vì điều này rất thú vị, nhưng hãy nhớ rằng '20' trong top20Func không còn là một tham số mà là một phần của tên nhắc nhở bạn về tham số. Bạn có thể nói một cách dễ dàng : var top5Func = getTopCustomersFunc(37);. '5' là sai lệch ở đây, nhưng mã hoạt động chính xác giống như nếu biến đã được đặt tên top37Func.
Caleb

1

Điều này phụ thuộc vào định nghĩa của bạn về "ngôn ngữ", nhưng khung thử nghiệm robotframework cho phép bạn xác định từ khóa theo cách này. Từ tài liệu của họ về các đối số nhúng :

Select ${animal} from list | Open page | pet selection
                            | Select item from list | animal_list | ${amimal}

Ở trên tuyên bố một từ khóa mới (về cơ bản là một hàm) có tên "select $ {động vật} từ danh sách" trong đó '$ {động vật}' là một tham số. Bạn gọi nó là "chọn mèo từ danh sách"


Điều này đối với tôi giống như các câu lệnh SQL. +1
Saeed Neamati

1

Thông báo 7.

To create (employee - a person) being paid (salary - a number):
    say "Welcome to your new job, [name of employee]!";
    choose a blank row from the table of employees;
    now the paid entry is the salary;
    now the name entry is the name of the employee.

Và như vậy.


3
Điều này không giải thích chính xác cách thức hoạt động của cú pháp. Nhiều người không quen thuộc với ngôn ngữ Thông tin và không thể phân biệt các tham số với cuộc gọi hoặc việc sử dụng nó trong các khu vực khác của mã.

Tôi thuộc loại hấp dẫn bởi ngôn ngữ này. Câu trả lời khá ngắn gọn chỉ với một mẫu mã chưa được xây dựng, nhưng các mẫu được đưa ra bởi OP (mặc dù với các ngôn ngữ thông thường hơn). Wiki có một bài viết hay để đọc về nó.
YoYo

0

Các từ khóa chung của Lisp đã được đề cập, nhưng các macro của Lisp chung cũng cho phép điều này khá dễ dàng:

(defmacro get-my-element (from list at index)
  `(nth ,index ,list))

Điều này sau đó có thể được gọi như vậy:

(get-my-element from '(a b c) at 1) ;returns B

Một điều cần lưu ý, tuy nhiên, là các điều khoản fromatkhông có hiệu lực. Phải có một cái gì đó ở đó, bỏ qua chúng hoàn toàn là một lỗi, nhưng vì macro cuối cùng đã loại bỏ chúng, nên chúng không vượt quá khả năng đọc (điều quan trọng):

(get-my-element from '(a b c) 3 1) ;also returns B

-2

Trong Clojure, người ta thường sử dụng các đối số từ khóa cho các tình huống như thế này, ví dụ:

(get-customers :top 50 :year 2010)

Đối số từ khóa khá linh hoạt, chúng có thể là tùy chọn và có mặc định được chỉ định, v.v.


-4

Bạn có thể mô phỏng điều này trong python. Ví dụ,

def GetTop(customers, ofYear):
  #write some code here to get the customers

print GetTop(customers=50 ofYear=2010)

hoặc thậm chí

def GetTop(**args):
  #write some code here using the same parameter names as above

print GetTop({customers: 50, ofYear: 2010})

1
Cú pháp trong ví dụ thứ hai của bạn là sai. Ngoài ra, ai đó đã đăng này.
Winston Ewert

điều này chỉ lặp đi lặp lại điểm được thực hiện (và giải thích rõ hơn nhiều) trong câu trả lời trước đó đã được đăng 3 năm trước
gnat
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.