When I first came across ESpec, I was perplexed by syntax like

expect ( pet ) . to be ( "Cat" )

That doesn't look like Elixir!

It is in fact a controversial feature of Erlang, that may be removed in future versions of Elixir. So you probably shouldn't use it, but it can still be interesting to know how it works.

ESpec's expect function returns a tuple like {Expect, pet} , containing a module name and the argument. So we effectively have

{ Expect , pet } . to be ( "Cat" )

This, in turn, is interpreted as an Expect.to function call, with the tuple itself as the last argument:

Expect . to ( be ( "Cat" ) , { Expect , pet } )

This applies to any number of arguments. If we had done

{ Expect , 1 , 2 , 3 } . to ( 4 , 5 , 6 )

then it would be interpreted as

Expect . to ( 4 , 5 , 6 , { Expect , 1 , 2 , 3 } )

and so on.

How it all fits together

This is how you might implement a minimal version of expect(…).to :

defmodule Expect do

def to ( { :be , value } , { Expect , value } ) do

IO . puts ( "Hooray, they're both ' #{ value } '!" )

end



def to ( { :be , expected } , { Expect , actual } ) do

IO . puts ( "Nay! Expected ' #{ expected } ' but got ' #{ actual } ' :(" )

end

end



defmodule Example do

def run do

expect ( "Cat" ) . to be ( "Cat" )

expect ( "Cat" ) . to be ( "Dog" )

end



defp expect ( actual ) do

{ Expect , actual }

end



defp be ( expected ) do

{ :be , expected }

end

end



Example . run

Output:

Hooray, they're both 'Cat'! Nay! Expected 'Dog' but got 'Cat' :(

If you want another example of how this might be used, see my ExMachina.with sketch.

What is this syntax?

This is Erlang tuple modules.

They are controversial in Erlang and Elixir both, and José Valim wants them gone in Elixir 2.0. Problems include hard-to-read stacktraces, slower dispatch, and that they can encourage writing code in an object-oriented style, with "methods" on "instances".