Какой-либо язык программирования со “странным” вызовом функции?

Я задавался вопросом, там любой язык программирования, где у Вас могут быть вызовы функции как это:

function_name(parameter1)function_name_continued(parameter2);

или

function_name(param1)function_continued(param2)...function_continued(paramN);

Например, у Вас мог быть этот вызов функции:

int dist = distanceFrom(cityA)to(cityB);

если Вы определили distanceFromto функционируйте как это:

int distanceFrom(city A)to(city B)
{
   // find distance between city A and city B
   // ...
   return distance;
}

Насколько я знаю, в C, Java и языках программирования SML, это не может быть сделано.

Вы знаете о каком-либо языке программирования который, позвольте нам, Вы определяете и вызываете функции таким образом?

9
задан 3 August 2010 в 00:11
поделиться

14 ответов

Tcl позволяет делать что-то вроде этого:

proc distance {from cityA to cityB} {...}
set distance [distance from "Chicago IL" to "Tulsa OK"]

Я не уверен, что вы думаете именно об этом.

0
ответ дан 4 December 2019 в 08:14
поделиться

Он очень похож на Objective-C

- (int)distanceFrom:(City *)cityA to:(City *)cityB {
    // woah!
}
6
ответ дан 4 December 2019 в 08:14
поделиться

Вы можете сделать это в Scheme или LISP, используя макросы.

Форма будет примерно такой:

(DISTANCE-FROM city-a TO city-b)

Символы в верхнем регистре обозначают синтаксис.

Можно даже сделать что-то вроде "именованных параметров":

(DISTANCE TO city-a FROM city-b)
(DISTANCE FROM city-a TO city-b)
0
ответ дан 4 December 2019 в 08:14
поделиться

Это похоже на перегрузку функций (C ++ / C #) / параметры по умолчанию (VB).

Параметры по умолчанию позволяют лицу, определяющему функцию, устанавливать значения по умолчанию для последних параметров:

например. Перегрузка c #:

int CalculateDistance(city A, city B, city via1, city via2) 
{....}

int CalculateDistance(city A, city B) 
{
  return CalculateDistance(city A, city B, null, null)
}
0
ответ дан 4 December 2019 в 08:14
поделиться

В SML вы можете просто сделать «to» некоторым значением (например, единицей измерения), а «distanceFrom» - каррированной функцией, которая принимает три параметра. Например:

val to = ()
fun distanceFrom x _ y = (* implementation function body *)

val foo = distanceFrom cityA to cityB

Вы также можете воспользоваться тем фактом, что SML не применяет соглашения об именах для конструкторов типов данных (к большому раздражению многих людей), поэтому, если вы хотите убедиться, что система типов применяет ваш собственный синтаксис:

datatype comp = to

fun distanceFrom x to y = (* implementation *)

val foo = distanceFrom cityA to cityB (* works *)
val foo' = distanceFrom cityA cityB (* whoops, forgot 'to' - type error! *)
0
ответ дан 4 December 2019 в 08:14
поделиться

C# 4.0's Named and Optional Arguments feature allows you to achieve something pretty similar:

public static int Distance(string from, string to, string via = "")
{
   ...
}

public static void Main()
{
   int distance;

   distance = Distance(from: "New York", to: "Tokyo");
   distance = Distance(to: "Tokyo", from: "New York");
   distance = Distance(from: "New York", via: "Athens", to: "Tokyo");
}
2
ответ дан 4 December 2019 в 08:14
поделиться

(см. мою самую любимую личную попытку - окончательный подход на C++ в конце этого ответа)

Язык один

Objective-C, но синтаксис вызова - [сообщение объекта], так что это будет выглядеть так:

int dist = [cities distanceFrom:cityA  to:cityB];

если вы определили distanceFromto функцию вот так, внутри объекта cities:

- (int)distanceFrom:(City *)cityA to:(City *)cityB 
  {
     // find distance between city A and city B
     // ...
     return distance;
  }

Language Two

Я также подозреваю, что вы могли бы достичь чего-то очень близкого к этому в IO Language, но я только сейчас смотрю на это. Вы также можете почитать о нем в сравнении с другими языками в Семь языков за семь недель, где есть бесплатный отрывок о IO.

Язык три

В C++ существует идиома ("chaining"), когда вы возвращаете временные объекты или текущий объект, который используется для замены аргументов ключевых слов, согласно The Design and Evolution of C++ и выглядит следующим образом:

int dist = distanceFrom(cityA).to(cityB);

если вы определили функцию distanceFrom вот так, с небольшим вспомогательным объектом. Обратите внимание, что встроенные функции позволяют компилировать такие вещи в очень эффективный код.

class DistanceCalculator
{
public:
    DistanceCalculator(City* from) : fromCity(from) {}

    int to(City * toCity) 
    {
         // find distance between fromCity and toCity
         // ...
         return distance;
    }

private:
    City* fromCity;
};


inline DistanceCalculator distanceFrom(City* from)
{
    return DistanceCalculator(from);
}

Дааа, я торопился раньше, понял, что могу рефакторить, чтобы просто использовать временный объект, чтобы дать тот же синтаксис:

class distanceFrom
{
public:
    distanceFrom(City* from) : fromCity(from) {}

    int to(City * toCity) 
    {
         // find distance between fromCity and toCity
         // ...
         return distance;
    }

private:
    City* fromCity;
};

МОЙ ЛЮБИМЫЙ , а вот еще более вдохновляющая версия на C++, которая позволяет вам писать

int dist = distanceFrom cityA to cityB;

или даже

int dist = distanceFrom cityA to cityB to cityC;

на основе удивительной для C++ комбинации #define и классов:

#include <vector>
#include <numeric>
class City;
#define distanceFrom DistanceCalculator() <<
#define to <<

class DistanceCalculator
{
public:

    operator int() 
    {
         // find distance between chain of cities
         return std::accumulate(cities.begin(), cities.end(), 0);
    }

    DistanceCalculator& operator<<(City* aCity)
    {
        cities.push_back(aCity);
        return *this;
    }

private:
    std::vector<City*> cities;
};

ПРИМЕЧАНИЕ Это может показаться бесполезным упражнением, но в некоторых контекстах это может быть очень полезно - дать людям специфический язык на C++, который они компилируют вместе с библиотеками. Мы использовали аналогичный подход с Python для ученых, занимающихся геомоделированием в CSIRO.

2
ответ дан 4 December 2019 в 08:14
поделиться

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

>>> l = [3,5,1,2,4]
>>> print l.sort.__doc__
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1
>>> l.sort (reverse=True)
>>> l
[5, 4, 3, 2, 1]

Это очень похоже на то, что делает синтаксис Objective C, помечая каждый аргумент функцией с ее именем.

2
ответ дан 4 December 2019 в 08:14
поделиться
3
ответ дан 4 December 2019 в 08:14
поделиться

Для этого можно использовать функцию-член.

cityA.distance_to(cityB);

Это допустимый код на C ++, C (с небольшой настройкой), C #, Java. Используя цепочки методов, вы можете:

cityA.something(cityB).something(cityC).something(cityD).something(cityE);
0
ответ дан 4 December 2019 в 08:14
поделиться

Для любопытных, Agda2 имеет похожий, очень разрешительный синтаксис. Следующий допустимый код:

data City : Set where
  London : City
  Paris  : City

data Distance : Set where
  _km : ℕ → Distance

from_to_ : City → City → Distance
from London to London = 0 km
from London to Paris  = 342 km
from Paris  to London = 342 km
from Paris  to Paris  = 0 km

Если вычислено

from Paris to London

, результат будет

342 km
4
ответ дан 4 December 2019 в 08:14
поделиться

Похоже на синтаксис Smalltalk (который объясняет синтаксис Objective-C - см. Ответ Куби).

Пример:

dist := metric distanceFrom: cityA to: cityB

где #distanceFrom: to: - это метод некоторого объекта, называемого метрикой.

Итак, у вас есть «вызовы функций» (на самом деле они отправляются сообщениями) вроде

'hello world' indexOf: $o startingAt: 6. "$o means 'the character literal o"

РЕДАКТИРОВАТЬ: Я сказал: «На самом деле, #distanceFrom: to: следует называть #distanceTo: в классе City, но в любом случае. " Судья указывает, что это связывает город с метрикой, что является плохим. Есть веские причины, по которым вы можете захотеть изменить метрику - самолеты могут использовать геодезические, а автомобили могут использовать кратчайший путь, основанный на дорожной сети.)

6
ответ дан 4 December 2019 в 08:14
поделиться

Вы можете сделать это в C, хотя и небезопасно:

struct Arg_s
    {
    int from;
    int to;
    };

int distance_f(struct Arg_s args)
    {
    return args.to - args.from;
    }

#define distance(...) distance_f( ((struct Arg_s){__VA_ARGS__}) )
#define from_ .from =
#define to_ .to =

использует составные литералы и назначенные инициализаторы .

printf("5 to 7 = %i\n",distance(from_ 5, to_ 7));
// 5 to 7 = 2
1
ответ дан 4 December 2019 в 08:14
поделиться

Вы можете сделать это в Java , используйте шаблон Builder , который появляется в книге Effective Java Джошуа Босха (this это второй раз, когда я помещаю эту ссылку в SO, я все еще не использовал этот узор, но выглядит отлично)

0
ответ дан 4 December 2019 в 08:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: