Я пишу про синтаксис мови. Чи існує там мова, параметри якої розміщені всередині назви методу?


29

у JavaScript:

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

в C #:

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

в PHP:

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

Чи є там мова, яка підтримує цей синтаксис:

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

Хіба це не більш семантична, більш читана форма написання функції?

Оновлення: Причиною цього запитання є те, що я пишу статтю про новий синтаксис для нової мови. Однак я подумав, що наявність такого синтаксису для способів оголошення може бути приємнішим та привітнішим для розробників і зменшить криву навчання мови через те, що вона наближається до природної мови. Мені просто хотілося дізнатись, чи вже про цю особливість було задумано чи ні.


12
Це може бути легше читати, як тільки ти звикнеш до ідіоми, але мені здається, було б складно написати правильний парсер для цього.
Мейсон Уілер

2
Що ви маєте на увазі під "заповнювачами"? Це питання важко зрозуміти як поставлене, хоча останній приклад коду нагадує Objective-C та SmallTalk.
greyfade

3
AFAIK Smalltalk була першою мовою, яка використовувала цей синтаксис виключно як 'hello world' indexOf: $o startingAt: 6або Rectangle width: 100 height: 200. До речі, що з цим питанням не так?
maaartinus

8
Якщо ви перемістите дужки, ви отримаєте: returnValue = GetTop(50, CustomersOfTheYear(2010))що на мене виглядає однаково читабельним, а насправді більш гнучким / ортогональним. ... і так, це звичайний звичайний синтаксис.
dagnelies

2
@arnaud: Я повністю згоден. Запропонований синтаксис є лише вирішенням для відсутності розкладання.
back2dos

Відповіді:


41

Так, і так. Так, така мова є, і так, багато людей вважають її більш читаною, коли звикають до неї.

У Objective-C методом буде:

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

Це насправді досить надуманий приклад, який читається не дуже добре, тому ось кращий з фактичного коду:

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

Це прототип методу, який повертає новий екземпляр UIColor, використовуючи значення червоного, зеленого, синього та альфа. Ви б назвали це так:

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

Детальніше про імена повідомлень з перемежованими параметрами читайте в Мові програмування Objective-C .


16
Перший раз, коли я читав про це в Objective CI, думав, що це розумно, але насправді названі параметри робляться більш жорсткими та складними в управлінні. Крім того, хороша відповідь.
ZJR

2
Приклад того, як викликається метод, не лишився б даремним.
greyfade

3
@ZJR, незважаючи на думку Вікіпедії про протилежне , стиль Obj-C схожий на названі параметри, але інший. У наведеному вище прикладі, метод назву: +colorWithRed:blue:green:alpha:. Я випадково використовувати імена параметрів , які відповідають методу, але я міг би так само легко використовував r, b, gі a. З названими параметрами, такими як пропозиції JavaScript, ви будете використовувати фактичні імена, вказані для доступу до значень. Параметри істинних імен також зазвичай можуть бути задані в будь-якому порядку, а параметри можуть бути необов’язковими. Так схоже, так, але принципово інше.
Калеб

2
Я думав про пітона: color(r=0xFF,g=0xFF,b=0x55)чи color(b=0x32,r=0x7F,a=.5,g=0xFF)так далі. Давайте тоді назвемо ці дуже названі параметри . :)
ZJR

3
@ZJR, ваш приклад python увімкнено - саме так я б назвав "названі параметри". Я просто кажу, що Obj-C насправді взагалі не дає вам цього. Синтаксис виглядає дуже схоже іменованих параметрів в JavaScript , так як метод розбитий на частини, і кожна частина має двокрапка, але це на самому справі НЕ то, що на всіх . Імена в Obj-C є частиною імені методу, а не іменами, які можна використовувати для посилання на параметри в реалізації; питання порядку; параметри необов’язкові. Я підозрюю, що ми, мабуть, згодні.
Калеб

25

Відповідь: мала розмова

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

'hello world' indexOf: $o startingAt: 6 як у Java "hello world".indexOfStartingAt(o, 6)

Rectangle width: 100 height: 200 як у Java new Rectangle(100, 200)

Синтаксис є ... expression word1: parm1 word2: parm2 word3: parm3 ...Назва названого методу - це з'єднання всіх слів.


17

Я вважаю, ви шукаєте абстракцію під назвою " вільний інтерфейс (я піднімаю коментар, спочатку зроблений @Jesper, до" відповіді ")." Ця поширена нині модель була успішно реалізована у багатьох мовах, з яких Objective-C - лише одна.

Ось досить чистий приклад:

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

Ви можете бачити, як щось подібне може бути реалізовано в ренді Паттерсона " Як створити вільний інтерфейс .

Andre Vianna дає коротку історію, а потім обговорює можливі втілення у ще двох частинах статті, включаючи безліч корисної інформації. Vianna вказує на стару ідею, з якою я вперше зіткнувся в Smalltalk 80 під назвою " каскад ", яка дозволила надсилати кілька повідомлень одному і тому ж об'єкту. Виглядало так:

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

Згодом каскад перетворився на " метод ланцюжків ", де ми " Зробити методи модифікаторів повернути хост-об'єкт, так що кілька модифікаторів можна викликати в одному виразі ". Спосіб ланцюжка пізніше виріс, щоб стати ідеальною концепцією інтерфейсу, яку ми часто знаємо і використовуємо сьогодні . Те, що ви плануєте зробити, виглядає дуже схоже.

Ейенде Рахієн розповідає про те, як "вільний інтерфейс" може досить істотно відрізнятися від "методу ланцюга", щоб заслужити своє ім'я .

Вільні інтерфейси часто зустрічаються в деяких нових інструментах, що використовуються в розвитку, керованому поведінкою (BDD) і навіть знайшли свій шлях до NUnit , основного інструменту тестування .NET-одиниць, у своїй новій моделі оцінювання на основі обмежень .

Ці основні підходи згодом були реалізовані в інших мовах, включаючи Ruby, Python, C #, Objective-C та Java . Щоб реалізувати щось подібне, вам захочеться вивчити ідею " закриття ", що є вкрай важливим для ланцюга та вільного володіння.

Можливо, ви можете покращити ці моделі; ось так ми отримуємо чудові нові мови. І все-таки я вважаю, що повне розуміння методу ланцюга та вільних інтерфейсів дасть вам прекрасну вихідну точку, з якої можна розвивати свої ідеї!


2
+1 для більшості досліджених відповідей поки що, хоча додавання прикладів та переформулювання читабельності може допомогти.
haylem

@haylem, дякую, що змусили мене повернутися назад і додати приклади та трохи детальніше!
Джон Тоблер

3
Запропоновано, оскільки це хороший опис вільного стилю, але зауважте, що це дійсно не те, про що задається ОП. Коли я читав, питання стосується перехресних параметрів з частинами назви однієї функції чи методу . Зверніть увагу на пропоновану декларацію функції: function GetTop(x)CustomersOfTheYear(y). Це одна функція, а не ланцюгові дзвінки до двох різних функцій.
Калеб

@Caleb Я думаю, що тут він намагається вказати, що ці параметри інфікування - це негнучкий спосіб зробити або вільний інтерфейс (ця відповідь), або названі параметри (інша відповідь). Поки що я не бачив жодної переваги для них у тому, що вільний інтерфейс / названі параметри не можуть зробити кращого.
Ізката

16

Objective-C робить це. Ось типовий прототип:

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

Ось як ви називаєте такий метод:

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

Objective-C в основному використовується для Cocoa для Mac OS X та Cocoa Touch для iOS, але gcc створить код Objective-C майже на кожній платформі, на якій працює gcc.


Вибачте, що куля повинна була бути дефісом. Я думаю, що дефіси у тексті відповідей приймаються як розмітка. Дефіси в Objective-C використовуються для оголошення методів, що належать об'єкту - [foo bar: x], де foo - це об'єкт або екземпляр класу - в той час як знаки плюс використовуються для методів класу, що C ++ позначає як статичні функції членів.
Майк Кроуфорд

13

У Common lisp ви можете визначити аргументи ключових слів для такої функції:

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

Функція називається так:

(area :width 2 :height 3)

В Ada вам не потрібно спеціальної декларації - ви можете зателефонувати в будь-яку процедуру чи функцію, перераховуючи аргументи в порядку, або назвавши такі аргументи:

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

Нарешті, бібліотека boost включає шар хаків, щоб додати функцію до C ++: http://www.boost.org/doc/libs/release/libs/parameter/doc/html/index.html


5

Я не зміг знайти його ім'я, але існує схема дизайну, щоб виконати щось подібне, коли виклик функції повертає новий об'єкт, змінений як описано. Наприклад:

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

Він використовується не дуже часто, оскільки ваші дані повинні бути дуже ортогональними, щоб уникнути некерованої складності під кришкою, але можуть бути корисними в правильних обставинах.


6
Це називається вільним стилем дизайну інтерфейсу .
Jesper

@Jesper, те, що я бачу, дуже схоже на ланцюжок jQuery. Чи правий я?
Саїд Неаматі

Так, @Saeed, jQuery використовує цей стиль.
Карл Білефельдт

5

У Python є параметри ключових слів. Приклад визначення функції

def getTopCustomers(count,year):
...

Приклад виклику функції

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

(Я розумію, що це не зовсім в дусі оригінального питання, але якщо параметри ключових слів у Lisp кваліфікуються, то це робіть. Однак у Smalltalk та Objective-C ключові слова між аргументами дійсно є частиною назви функції / пошуку .)


Мені особисто це більше подобається, адже це дає вам можливість викликати функцію без імен параметрів, якщо ви знаєте порядок параметрів
Pablo Mescher

4

У Agda є позначення mixfix

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

 if cond then x else y

Кожен раз, коли функція буде названа підкресленням, її можна розділити на дві частини з аргументом між ними


4

Хоча це не мова програмування сам по собі , огірка приймає параметри в середині імен функцій, які можуть включати в себе прогалини і призначені , щоб виглядати як англійська мова.

Однак "функції" визначені в Ruby

# 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

У TeX ви можете визначити макроси, що мають "шаблон аргументу", що в основному означає, що ваш протокол виклику вільний. Для вашого конкретного прикладу ви можете використовувати

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

Зауважте, що також можна позбутися від ; якщо ви погодилися грати з регістрами:

\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 дозволяє переконфігурувати його лексеми і завдяки \afterassignment макросу, який я використовував вище, ви можете використовувати вбудовані процедури для лексування чисел. Дуже корисно визначити дуже лаконічні протоколи викликів. Наприклад, дуже правдоподібно написати макроси TeX, розуміючи позначення Markdown для таблиць.

Тепер ви запитуєте "як мені отримати доступ до моєї бази даних, де зберігаються клієнти з TeX?", Але це вже інше питання. :)

У Common lisp це, безумовно, можливо визначити queryмакрос, що дозволяє писати

(query getTopCustomers 50 OfTheYear 2010)

де getCustomers та OfTheYear інтерпретуються як символи. Тоді це завдання макросу зрозуміти це. Звичайний Lisp є чудовим у галузі читабельності коду (так, я маю на увазі!), Оскільки макросистема дозволяє легко створювати псевдо-мови, налаштовані для вашої програми. (Я думаю, вони називаються мовами додатків.)

PS: Схоже, ніхто не цитував C ++. Найближчий, який ви можете отримати (без препроцесора), - це

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

хитрість полягає в тому, щоб дозволити getTopCustomersповертати посилання на query(або що-небудь інше), яке також реалізується OfTheYear. Ви можете побудувати цей приклад до невеликої мови запитів, але тоді вам доведеться визначити кінцеві властивості (повернути значення) або додати finaliseметод (виконання пошуку та повернення значення). Якщо вам це подобається, ви також можете імітувати потокові контролери STL та мати можливість записувати подібні речі

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

але це знову йде в бік мов додатків.

Редагувати: Я не помітив відповіді @han, які також цитують загальні Lisp та C ++ (але не TeX!).


2

В JavaScript або будь-якому іншому мовою , який підтримує закриття, ви можете здобути таку функцію:

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, оскільки це цікаво, але пам’ятайте, що '20' у top20Func - це вже не параметр, а частина назви, яка нагадує вам параметр. Ви можете так само легко сказати: var top5Func = getTopCustomersFunc(37);. Значення "5" вводить в оману, але код працює точно так само, як якщо б була названа змінна top37Func.
Калеб

1

Це залежить від вашого визначення поняття "мова", але рамка тестування роботфрагментів дозволяє визначати ключові слова таким чином. З їх документації на вбудовані аргументи :

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

Вище описано нове ключове слово (по суті функція) під назвою "select $ {animal} зі списку", де "$ {animal}" є параметром. Ви називаєте це як "вибрати кота зі списку"


Мені це здається висловлюванням SQL. +1
Saeed Neamati

1

Інформуйте 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.

І так далі.


3
Це не точно пояснює, як працює синтаксис мови. Багато людей не знайомі з мовою Inform і не можуть відрізнити параметри від дзвінка або його використання в інших областях коду.

Мене якось заінтригує ця мова. Відповідь була досить короткою лише з не розробленим зразком коду, але так само були і зразки, надані ОП (хоча з більш звичайними мовами). У Wiki є чудова стаття, щоб прочитати про це.
YoYo

0

Загальні ключові слова Lisp вже були згадані, але макроси звичайного Lisp також дозволяють це досить легко:

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

Потім це можна назвати так:

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

Одна річ , щоб відзначити, однак, полягає в тому , що умови fromі atне виконуються. Там має бути щось , пропуск їх цілком є ​​помилкою, але оскільки макрос просто закінчує їх відкидання, це не має великого значення, що вони є поза читабельністю (що важливо):

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

-2

У Clojure звичайно використовувати аргументи ключових слів для таких ситуацій, наприклад:

(get-customers :top 50 :year 2010)

Аргументи ключових слів досить гнучкі, вони можуть бути необов’язковими та матимуть за замовчуванням тощо.


-4

Ви можете імітувати це в python. Наприклад,

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

print GetTop(customers=50 ofYear=2010)

або навіть

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

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

1
Синтаксис у вашому другому прикладі неправильний. Також це вже хтось опублікував.
Вінстон Еверт

це просто повторює пункт, зроблений (і набагато краще пояснений) у цій попередній відповіді, що була розміщена 3 роками раніше
gnat
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.