views:

344

answers:

14

I was wondering, is there any programming language where you can have function calls like this:

function_name(parameter1)function_name_continued(parameter2);

or

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

For example you could have this function call:

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

if you have defined distanceFromto function like this:

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

As far as I know, in C, Java and SML programming languages, this cannot be done.

Are you aware of any programming language that let's you define and call functions in this way?

+5  A: 

It looks an awful lot like Objective-C

- (int)distanceFrom:(City *)cityA to:(City *)cityB {
    // woah!
}
kubi
Thanks for your answer. I guess, the code you wrote is the function definition. Could you also give an example of how this function is called?
Almost identically to Smalltalk: dist = [metric distanceFrom: cityA to: cityB];
Frank Shearar
+6  A: 

Sounds a lot like Smalltalk's syntax, (which would explain Objective-C's syntax - see kubi's answer).

Example:

dist := metric distanceFrom: cityA to: cityB

where #distanceFrom:to: is a method on some object called metric.

So you have "function calls" (they're really message sends) like

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

EDIT: I'd said "Really, #distanceFrom:to: should be called #distanceTo: on a City class, but anyway." Justice points out that this couples a City to a Metric, which is Bad. There are good reasons why you might want to vary the metric - aeroplanes might use a geodesic while cars might use a shortest path based on the road network.)

Frank Shearar
A metric is a `strategy` to measure the distance between two points. There are multiple valid strategies, returning different valid results. `metric#distanceFrom:to` is the right technique; `city#distanceTo` is at best an approximation. What do cities know about distances to other cities?! Cities know their own positions, and metrics know about measuring distances between two positions.
Justice
Justice, you're right. I like `#distanceTo:` because it's short - but that's a tradeoff that's probably not worth making, because it increases coupling (Cities know about non-City things) and it's not THAT much shorter than `#distanceFrom:to:`. Thanks!
Frank Shearar
A: 

This looks similar to function overloading (C++/C#)/default parameters (VB).

Default Parameters allow the person defining the function to set defaults for the latter parameters:

e.g. c# overloading:

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

int CalculateDistance(city A, city B) 
{
  return CalculateDistance(city A, city B, null, null)
}
Shandy
A: 

You can use a member function for this.

cityA.distance_to(cityB);

That's valid code in C++, C(with a little tweaking), C#, Java. Using method chains, you can do:

cityA.something(cityB).something(cityC).something(cityD).something(cityE);
DeadMG
+1  A: 

In Python, you can explicitly pass the name of the arguments you're calling the function with, which lets you pass them in a different order or skip optional arguments:

>>> 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]

This looks a lot like what the Objective C syntax is doing, tagging each argument to a function with its name.

Paul Kuliniewicz
+2  A: 

Language One

Objective-C but the calling syntax is [object message] so would look like:

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

if you have defined distanceFromto function like this, within a cities object:

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

Language Two

I also suspect you could achieve something very close to this in the IO Language but I'm only just looking at it. You may also want to read about it in comparison to other languages in Seven Languages in Seven Weeks which has a free excerpt about IO.

Language Three

There's an idiom in C++ where you return temporary objects or the current object that is used to replace keyword arguments, according to The Design and Evolution of C++ and looks like this:

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

if you have defined distanceFrom function like this, with a little helper object. Note that inline functions make this kind of thing compile to very efficient code.

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);
}

Duhh, I was in a hurry earlier, realised I can refactor to just use a temporary object to give the same syntax:

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

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

private:
    City* fromCity;
};

and here's an even more inspired C++ version that allows you to write

int dist = distanceFrom cityA to cityB;

or even

int dist = distanceFrom cityA to cityB to cityC;

based on a wonderfully C++ ish combination of #define and classes:

#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;
};
Andy Dent
I have no knowledge of C++ but the assignment: `int dist = distanceFrom cityA to cityB;` seems neat! Thank you for taking time to answer at my question.
It's this cleverness about C++ that always makes me smile and cringe simultaneously.
Novelocrat
A: 

In SML you could simply make "to" some value (unit, for example), and "distanceFrom" a curried function that takes three parameters. For example:

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

val foo = distanceFrom cityA to cityB

You could also take advantage of the fact that SML doesn't enforce naming conventions on datataype constructors (much to many peoples' annoyance), so if you want to make sure that the type system enforces your custom syntax:

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! *)
Gian
Although I wasn't looking for a curried function. I really found interesting and nice the trick you did with `datatype comp = to` :) (+1 for this)
+2  A: 

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");
}
Allon Guralnek
That looks so much like Common Lisp's keyword parameters, it's scary: (distance from: "New York" to: "Tokyo")
Frank Shearar
Keywords start with `:`, not end with it, so it'd be `(distance :from "New York" :to "Tokyo")`. But yeah.
Ken
Python has keyword arguments, too.
Novelocrat
+4  A: 

For the curious, Agda2 has a similar, very permissive syntax. The following is valid code:

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

If

from Paris to London

is evaluated, the result is

342 km
fishlips
A: 

You could do this in Scheme or LISP using macros.

The form will be something like:

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

The symbols in uppercase denotes syntax.

You could even do something like 'named parameters':

(DISTANCE TO city-a FROM city-b)
(DISTANCE FROM city-a TO city-b)
leppie
You can also do it with the C preprocessor ...
reinierpost
Frank Shearar
@reinierpost how can this be done with the C preprocessor?
@functional I don't know what I was thinking. You can't do this with the C proprocessor. It must be done at the tokenized level, the level Lisp macros operate on.
reinierpost
@functional,@reinierpost, I'm fairly sure you *can*, using [compound literals](http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Compound-Literals.html) and [designated initializers](http://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Designated-Inits.html).
David X
Ok, fuck trying to type that into a comment box; see [my answer](http://stackoverflow.com/questions/3307946/any-programming-language-with-strange-function-call/3384524#3384524).
David X
+3  A: 

Looks a lot like a fluent interface or method chaining to me.

Richard Ev
A: 

Tcl allows you to do something like this:

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

I'm not sure if that's quite what you are thinking of though.

Bryan Oakley
+1  A: 

You can do this in C, albeit unsafely:

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 =

uses compound literals and designated initializers.

printf("5 to 7 = %i\n",distance(from_ 5, to_ 7));
// 5 to 7 = 2
David X
+1 for being way to complicated
It is like the saying goes: just because you can, doesn't mean you should.
David X
A: 

You can do it in Java, Use Builder pattern that appears in the book Effective Java by Joshua Bosch (this is second time I put this link in SO, I still didn't use that patern, but looks great)

Hernán Eche