Multi-Part Method Names

Driven by the goal to fit in well with the API conventions on the Cocoa platform, Elements has added support for multi-part method names to all languages, and for all platforms.

Multi-part method names are essentially the ability for a method's name to be split into separate parts, each followed by a distinct parameter. This is "required" on the Cocoa platform because all the platform's APIs follow this convention, and we wanted all Elements languages to be able to both consume and implement methods alongside those conventions without resorting to awkward attributes or other adornments, and to feel at home on the Cocoa platform.

But since multi-part method names are not intrinsically tied to the Cocoa platform, we have made them available as an option for all platfroms, and encourage their use.

A multi-part method has separate name parts for each parameter (or, rarely, group of parameters).

In Oxygene, C# and Java, each parameter is a combination of a (partial) name, and its own set of parenthesis declaring that parameters internal name and type.

In Swift and Mercury, the first part of the method name is followed by a single set of parenthesis enclosing all parameters; each parameter can (optionally) declare an external name that becomes part of the method signature.

Unique to Swift and Mercury, the first parameter can declare an outer name in addition to the first part of the method name (e.g. "Run(command)" in the Swift samle below. To Oxygene, C# and Java, a method declared as such will appear as if the two parts have been concatenated and camel-cased (e.g. "RunCommand").

Note: methods can be overloaded on parts of their name, even if all versions acept the same kind of types.

Declarations

A multi-part method declaration looks like this:

method RunCommand(aCommand: String) Arguments(params aArguments: array of String): Boolean;
bool RunCommand(string Command) Arguments(string[] arguments)
func Run(Command: String, Arguments: [String]) -> Bool
Boolean RunCommand(String Command) Arguments(String[] arguments)
Function RunCommand(Command As String, Arguments arguments as String[])

Note that in Swift, all parameters are assumed to have an outer name, by default; if none is provided explicitly then the internal name of the parameter is used externally as well. To declare a parameter without an external name, prefix it with an underscore:

func RunCommandWithArguments(_ Command: String, _ Arguments: [String]) -> Bool

By contrast, Mercury will only associate an external name with a parameter if one is explicitly provided, so – in line with traditional Visual Basic declaration syntax – a regular parameter with just name and type will have no external name.

Calling Multi-Part Methods

When calling a multi-part method, a similar syntax is used, providing separate sets of names and parenthesis for Oxygene C# and Java, and a single set for Swift and Mercury:

x.RunCommand("ebuild") Arguments('MyProject.sln', '--configuration:Debug');
x.RunCommand("ebuild") Arguments(new string[] {"MyProject.sln", "--configuration:Debug"});
x.Run(Command: "ebuild", Arguments: ["MyProject.sln", "--configuration:Debug"])
x.RunCommand("ebuild") Arguments(new String[] {"MyProject.sln", "--configuration:Debug"});
x.RunCommand("ebuild", Arguments: {"MyProject.sln", "--configuration:Debug"})

Multi-Part and Named Constructors

Constructors can also optional be named and have multi-part names. For simplicity, lets look at a constructor for a Process class with a signature similar to the above method:

constructor withCommand(aCommand: String) Arguments(params aArguments: array of String)
this withCommand(string Command) Arguments(string[] arguments)
init(Command: String, Arguments: [String]) -> Bool
this withCommand(String Command) Arguments(String[] arguments)
Sub New(Command command As String, Arguments arguments as String[])

Note that by convention, constructor names start with the word with and (usually) a noun describing the forst parameter. For Swift and Mercury, this is omitted, but is implicitly added by the compiler (e.g. when creating a class declared in Swift or Mercury from the other languages.

Also note that in C# and Java, the this keyword is used instead of the class name, to avoid ambiguity with a regular method syntax. We recommend using this for all constructors, named or not.

On Cocoa, a named constructor maps to the corresponding initWith* method on Objective-C level. That name is derived by uppercasing the "W" (or the first letter of the name, regardless of what it is, and prefixing it with init.

Creating an instance looks similar:

x := new Process withCommand('ebuild') Arguments('MyProject.sln', '--configuration:Debug');
var x = new Proces withCommand("ebuild") Arguments(new string[] {"MyProject.sln", "--configuration:Debug"});
let x = Process(Command: "ebuild", Arguments: ["MyProject.sln", "--configuration:Debug"])
var x = new Process withCommand("ebuild") Arguments(new String[] {"MyProject.sln", "--configuration:Debug"});
Dim x = New Process(Command "ebuild", Arguments: {"MyProject.sln", "--configuration:Debug"})

Available on All Platforms

While the feature was created for Cocoa, multi-part method names are supported on all platforms, and considered a regular feature of the languages. We encourage to use and embrace them, as they are a great tool to make code more readable and understandable.

See Also