 <p>Your intuition is correct, <code>trav t_1</code> gets evaluated first as function arguments are evaluated in left to right order. This might seem a little strange, since <code>@</code> is an infix operator, but <code>[1, 2, 3] @ [4, 5, 6]</code> can actually be rewritten as <code>(op @)([1, 2, 3], [4, 5, 6])</code>. You can verify that <code>@</code> evaluates its left argument first by doing:</p> <pre><code>Standard ML of New Jersey v110.78 [built: Sun Jun 7 20:21:33 2015] - (print "test1\n"; [1, 2, 3]) @ (print "test2\n"; [4, 5, 6]); test1 test2 val it = [1,2,3,4,5,6] : int list - </code></pre> <p>Essentially what you have is equivalent to:</p> <pre><code>fun trav Empty = [] | trav(Node(t_1, x, t_2)) = let val l = trav t_1 val r = trav t_2 in l @ (x::r) end </code></pre>