When your language is lazy by default, is it really a trick to take advantage of that?
Do you consider this a trick?
take 1 [5..]
How about this Fibonacci definition?
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
What about this extensible fizzbuzz example?
fizzBuzz i = if null desc then show i else desc
where desc = concat [label | (j,label) <- tags, 0 == rem i j]
tags = [ (3,"Fizz"), (5,"Buzz"), (7,"Baz") ]
main = mapM_ (putStrLn . fizzBuzz) [1..120]
Focus on why you are trying to accomplish something, not how you are accomplishing it.
Yes, these are tricks, because "lazy" means you're storing thunks and significant partial results with no outward indication of such. Just because you don't see it, doesn't mean it's not there. I could say the same about C's allowance of global state, or spurious use of recursion without a depth guard.
To your examples:
A trick, because who would ask for a constant from an infinite list that could be generated numerically in a fraction of the time?
A trick, because for random queries of large n, this is not the optimal way to compute it (the optimal way is more complex). It also entangles memory allocation and the computation. Note how haskell is "side-effect free" for fibs, yet somehow memory allocation or the time required for allocation is not considered a side-effect when I ask for "fibs !! 2000000". The C iterative solution is trivial, and will execute faster.
A trick, because no one cares about fizz-buzz being extensible, and this is not particularly clear to the reader compared to an ordinary if/switch/case expression.
When your language is lazy by default, is it really a trick to take advantage of that?
Do you consider this a trick?
How about this Fibonacci definition? What about this extensible fizzbuzz example?