【问题标题】:how to efficiently build erlang lists in natural order?如何以自然顺序有效地构建 erlang 列表?
【发布时间】:2016-08-20 07:29:17
【问题描述】:

在Programming Erlang 书中,有一些示例伪代码显示了一种有效地将元素添加到列表头部的模式:

some_function([H|T], ..., Result, ...) ->
    H1 = ... H ...,
    some_function(T, ..., [H1|Result], ...);
some_function([H|T], ..., Result, ...) ->
    {..., Result, ...}.

我还在习惯函数式编程,所以上面的例子对我来说有点太抽象了。

我认为如果有我可以剖析的模式的具体实现会更容易理解。

问题:有人可以提供这种模式的简单具体实现吗?

【问题讨论】:

  • 您能否发布关于伪代码应该做什么的确切报价,您确定这是确切的伪代码吗?我本来想买那本书,但现在有点怀疑。
  • @7stud - 我不会仅仅根据那个例子来判断这本书。总的来说,这本书真的很好。

标签: erlang


【解决方案1】:

假设我们想要一个行为类似于uniq 命令的函数。 该函数接受一个元素列表并返回一个列表,其中一个元素的所有连续出现都替换为该元素的单个出现。 下面介绍了一种可能的方法:

uniq(L) ->
    uniq(L, []).

uniq([], Acc) ->
    lists:reverse(Acc);
uniq([H, H | T], Acc) ->
    uniq([H | T], Acc);
uniq([H | T], Acc) ->
    uniq(T, [H | Acc]).

我们构建了一个累加器,通过在 Acc 列表的头部插入新元素(插入成本最低),一旦我们完成,我们反转整个列表以恢复元素的初始顺序。

我们两次“访问”初始列表的某些元素,但总成本仍然是线性的,即仅取决于初始列表的元素数量。

【讨论】:

  • 你能得到实际的模式来做一些有用的事情吗?如果第二个子句在上面,那就更容易了。
【解决方案2】:

这需要一个分解列表,即

[[],[2],[3],[2,2],[5],[2,3],[7],[2,2,2],etc...]

并删除所有素数。

remove_primes([HD|TL], Results) -> 

    case length(HD) of
           0 -> % You're at 1
                  remove_primes (TL , Results);
           1 -> % Its a prime, remove it, and keep going
                  remove_primes( TL , Results) ;
           _ -> % its not prime, leave it in and keep going.  
                  remove_primes(TL, [ HD | Results]) 
    end;

remove_primes([], Result) -> 
                 {Result}.

Joe Armstrong 也提到了这种结构,它是遍历列表并将函数应用于列表中每个元素的标准结构。在这种情况下,我希望根据其内容对每个元素进行不同的处理。

在实践中,使用地图、过滤器等要容易得多,所以我相信您会更频繁地看到这些 - 但您似乎知道,了解基础知识对于成为一名熟练的函数式程序员至关重要。

希望集中与“按自然顺序构建列表”有关的信息,有谁知道为什么函数级别的模式匹配有效,但“解包”变量不起作用? (比较一下)(不行)

remove_primes(Factorized_List, Results) -> 
    [HD|TL] = Factorized_List, % unpack the list   <-------------

        case length(HD) of
               0 -> % You're at 1
                  remove_primes (TL , Results);
           1 -> % Its a prime, remove it, and keep going
                  remove_primes( TL , Results) ;
           _ -> % its not prime, leave it in and keep going.  
                  remove_primes(TL, [HD|Results]) 
        end;

remove_primes([], Result) -> 
                 {Result}.

我相信这会导致代码更具可读性,但它似乎不起作用。

-rC

【讨论】:

    【解决方案3】:

    这是我可以让你的模式执行的唯一方法:

    some_func([H|T], 4, Result, 4) -> 
        H1 = H * 2,
        some_func(T, 3, [H1|Result], 4); 
    some_func([H|T], 3, Result, _) ->
        {H, Result, T}.
    
    --output:--
    
    25> a:some_func([1, 2, 3], 4, [], 4).  
    {2,[2],[3]}
    

    ...没有任何用处。

    伪代码中的模式对我来说毫无意义,所以我会加入你的困惑。

    这是另一个尝试:

    some_func([H|T], [_|T2], Result, Y) -> 
        H1 = H * Y,
        some_func(T, T2, [H1|Result], Y); 
    some_func([H|T], [], Result, _) ->
        {H, Result, T}.
    
    
    --output:--
    34> a:some_func([1, 2, 3, 4], [one, two, three], [], 2).
    {4,[6,4,2],[]}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      相关资源
      最近更新 更多