'Is it possible to define an infix function?

Is it possible to define my own infix function/operator in CoffeeScript (or in pure JavaScript)? e.g. I want to call

a foo b

or

a `foo` b

instead of

a.foo b

or, when foo is global function,

foo a, b

Is there any way to do this?



Solution 1:[1]

ES6 enables a very Haskell/Lambda calculus way of doing things.

Given a multiplication function:

const multiply = a => b => (a * b)

You can define a doubling function using partial application (you leave out one parameter):

const double = multiply (2)

And you can compose the double function with itself, creating a quadruple function:

const compose = (f, g) => x => f(g(x))
const quadruple = compose (double, double)

But indeed, what if you would prefer an infix notation? As Steve Ladavich noted, you do need to extend a prototype.

But I think it can be done a bit more elegant using array notation instead of dot notation.

Lets use the official symbol for function composition "?":

Function.prototype['?'] = function(f){
  return x => this(f(x))
}

const multiply = a => b => (a * b)
const double = multiply (2)
const doublethreetimes = (double) ['?'] (double) ['?'] (double)

console.log(doublethreetimes(3));

Solution 2:[2]

Actually adding this as an answer: no, this is not possible.

It's not possible in vanilla JS.

It's not possible in CoffeeScript.

Solution 3:[3]

You can with sweet.js. See:

  1. http://sweetjs.org/doc/main/sweet.html#infix-macros
  2. http://sweetjs.org/doc/main/sweet.html#custom-operators

Sweet.js extends Javascript with macros.

It acts like a preprocessor.

Solution 4:[4]

This is definitely not infix notation but it's kinda close : /

let plus = function(a,b){return a+b};

let a = 3;
let b = 5;
let c = a._(plus).b // 8

I don't think anyone would actually want to use this "notation" since it's pretty ugly, but I think there are probably some tweaks that can be made to make it look different or nicer (possibly using this answer here to "call a function" without parentheses).

Infix function

// Add to prototype so that it's always there for you
Object.prototype._ = function(binaryOperator){

  // The first operand is captured in the this keyword
  let operand1 = this; 

  // Use a proxy to capture the second operand with "get"
  // Note that the first operand and the applied function
  //   are stored in the get function's closure, since operand2
  //   is just a string, for eval(operand2) to be in scope,
  //   the value for operand2 must be defined globally
  return new Proxy({},{
    get: function(obj, operand2){
        return binaryOperator(operand1, eval(operand2))
    }
  })
}

Also note that the second operand is passed as a string and evaluated with eval to get its value. Because of this, I think the code will break anytime the value of operand (aka "b") is not defined globally.

Solution 5:[5]

Javascript doesn't include an infix notation for functions or sections for partial application. But it ships with higher order functions, which allow us to do almost everything:

// applicator for infix notation
const $ = (x, f, y) => f(x) (y);

// for left section
const $_ = (x, f) => f(x);

// for right section
const _$ = (f, y) => x => f(x) (y);

// non-commutative operator function
const sub = x => y => x - y;


// application

console.log(
  $(2, sub, 3),   // -1
  $_(2, sub) (3), // -1
  _$(sub, 3) (2)  // -1
);

As you can see I prefer visual names $, $_ and _$ to textual ones in this case. This is the best you can get - at least with pure Javascript/ES2015.

Solution 6:[6]

You can get close by function currying:

const $ = (a) => (f) => f(a);
const plus = (a) => (b) => (a+b);
const twoPlusThree = $ (2) (plus) (3);

But I still haven't figured out a neat way to compose this construction.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Community
Solution 3 CMCDragonkai
Solution 4 Community
Solution 5
Solution 6 thesame