lists优化,尾递归的重要一点

lists优化,尾递归的重要一点

lists:flatten/1 builds an entirely new list. Therefore, it is expensive, and even more expensive than the ++ (which copies its left argument, but not its right argument).

In the following situations, you can easily avoid calling lists:flatten/1:

  • When sending data to a port. Ports understand deep lists so there is no reason to flatten the list before sending it to the port.
  • When calling BIFs that accept deep lists, such as list_to_binary/1 or iolist_to_binary/1.
  • When you know that your list is only one level deep, you can can use lists:append/1.

Port example

DO

      ...
      port_command(Port, DeepList)
      ...

DO NOT

      ...
      port_command(Port, lists:flatten(DeepList))
      ...

A common way to send a zero-terminated string to a port is the following:

DO NOT

      ...
      TerminatedStr = String ++ [0], % String="foo" => [$f, $o, $o, 0]
      port_command(Port, TerminatedStr)
      ...

Instead do like this:

DO

      ...
      TerminatedStr = [String, 0], % String="foo" => [[$f, $o, $o], 0]
      port_command(Port, TerminatedStr) 
      ...

Append example

DO

      > lists:append([[1], [2], [3]]).
      [1,2,3]
      >

DO NOT

      > lists:flatten([[1], [2], [3]]).
      [1,2,3]
      >
 
  

 

In the performance myth chapter, the following myth was exposed: Tail-recursive functions are MUCH faster than recursive functions.

To summarize, in R12B there is usually not much difference between a body-recursive list function and tail-recursive function that reverses the list at the end. Therefore, concentrate on writing beautiful code and forget about the performance of your list functions. In the time-critical parts of your code (and only there), measure before rewriting your code.

Important note: This section talks about lists functions that construct lists. A tail-recursive function that does not construct a list runs in constant space, while the corresponding body-recursive function uses stack space proportional to the length of the list. For instance, a function that sums a list of integers, should not be written like this

DO NOT

recursive_sum([H|T]) -> H+recursive_sum(T);
recursive_sum([])    -> 0.

but like this

DO

sum(L) -> sum(L, 0).

sum([H|T], Sum) -> sum(T, Sum + H);
sum([], Sum)    -> Sum.

猜你喜欢

转载自blog.csdn.net/boiled_water123/article/details/80879313
今日推荐