3
$\begingroup$

In my language, I intend to have infix methods. The utility of this syntax feature is to express methods with the semantics of taking two objects, probably of the same type, in semantically equivalent positions. The examples include dot and cross product for vectors, string concatenation, and so on. Conventional method invocation syntax puts the right operand in a more nested position, and function invocation places the function in a prefix position, so both of these approaches fare poorly in nested cases in terms of visually asserting semantics. My question is, what syntax options are used for infix methods in established languages?

I've already considered user-defined operators as a potential solution: instead of allowing for a special kind of methods, the language could allow its users to define new operators consisting of arbitrary punctuation symbols. However, I fear this could easily lead to confusion, especially in large code bases, as well as wouldn't convey the meaning of the operation easily.

Preferably, I'd like to avoid introducing conflicting or confusing cases into my grammar. However, I'm interested in all answers for the sake of completeness.

$\endgroup$

3 Answers 3

6
$\begingroup$

Kotlin-style

Simply placing the name of the method inbetween two operands (a dot b).

I'm giving this answer myself because I've already considered this approach, and it seems viable at first glance. I'm still interested in alternatives.

$\endgroup$
3
  • 2
    $\begingroup$ This was and is the APL-style too, used by APL and its derivatives long before Kotlin's parents. $\endgroup$
    – Adám
    May 30, 2023 at 3:19
  • $\begingroup$ @Adám note that Kotlin's parent does not use this (or do you mean the people who designed Kotlin?) $\endgroup$
    – Seggan
    May 30, 2023 at 17:45
  • $\begingroup$ @Seggan Right, I didn't mean to imply that, only give some perspective on the time scales. $\endgroup$
    – Adám
    May 30, 2023 at 17:50
5
$\begingroup$

Smalltalk methods

Smalltalk and Objective-C use mixfix syntax for multi-argument methods, e.g. foo doSomethingWithFirstArg:1 secondArg:2 thirdArg:3 where C++ would have foo.doSomething(1, 2, 3). Each part of the method name must end in a colon, and in Objective-C the entire expression must be wrapped in square brackets.

Swift custom operators

Swift allows users to define custom operators, but places some restrictions on what characters may occur in them. The rules are:

  • Operators must consist of only the ASCII characters ./=-+!*%<>&|^?~, or certain non-ASCII characters listed in the Lexical Structure chapter of The Swift Programming Language.
  • If an operator does not begin with a ., it may not contain one. .* is a legal operator, but *. isn't.
  • Postfix operators may not begin with ? or !, though prefix and infix operators can.
  • The following sequences aren't allowed as custom operators, though may exist as a subsequence of a longer operator:
    • =, /*, */, //, ->, ., and ?
    • < and & as prefix operators (fine as infix or postfix operators)
    • > and ! as postfix operators (fine as prefix or infix operators)
$\endgroup$
5
$\begingroup$

Haskell's operators are just functions with non-alphanumeric names and called in infix position.
Alternatively, you can wrap an operator in parenthesis and use it as an identifier in prefix position, and you can wrap a non-operator function name in backticks and use in infix position.

Eg. x + y is the same as (+) x y, and f x y is the same as x `f` y.

Ante uses the dot . operator for that, where x .f y is the same as f x y (it calls it the OO-friendly dot operator).
That said, in the presence of currying, you do not actually need builtin support for infix non-operator function calls! Such a . operator can be defined as simply as

(.): a -> (a -> b) -> b
x . f = f x

which, with the same precedence as the function call, can be used as

double x = x * 2
times = (*)

ten = 5 .double
answer = 10.5 .times 4

since for ten, (.) has type Int -> (Int -> Int) -> Int, and for answer, the expression is interpreted as (10.5 .times) 4, and it has type Rat -> (Rat -> (Int -> Rat)) -> (Int -> Rat).

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .