将元素添加到Racket中新定义的列表中

时间:2017-01-20 18:31:05

标签: functional-programming scheme racket dot-product

我是Racket和一般功能语言的新手。现在我只想尝试将项目添加到列表中。这些概念有点混乱,不确定为什么我的代码不起作用。

我正在尝试进行点积计算。

我有一个名为" dProduct"它采用2个列表(A和B)并将其中的每个对应元素相乘。

    ;function takes dot product
    (define (dProduct A B)

      (define C '()) ; define list to store the multiplied elements

      ;multiply ea lists elements
      (for ([i A] [j B])
        (display (* i j))   ;THIS WORKS
        (cons (* i j) C)    ;APPARENTLY DOESN'T WORK
      )

      ;THIS FOR LOOP DISPLAYS NOTHING
      ;display the new list "C"
      (for ([k C])
        (display k)
      )

    )

我不明白为什么我不能使用缺点将新的乘法元素添加到我的新列表中#C;#34;。我错过了什么?一切都很好。想想这个,所以我可以完成这个功能:)任何帮助都会很棒。谢谢!

2 个答案:

答案 0 :(得分:4)

列表是不可变的,cons 将元素添加到现有列表中。相反,它会生成一个包含前置元素的新列表:

> (define x '(2 3))
> (cons 1 x)
'(1 2 3)
> x
'(2 3)

由于您的问题被标记为,我将假设您可能想知道如何在功能上执行此操作,并且函数式编程通常不会改变值或绑定。

您应该在功能上构建新的结构,而不是改变绑定。最简单的方法是将for的使用更改为for/list,这会生成一个返回值列表:

(define C
  (for/list ([i A] [j B])
    (* i j)))

对于这个程序,你可以使用高阶函数map使它更简单,当提供多个列表参数时,它就像一个“zip”:

(define C (map * A B))

由于for始终返回#<void>,因此它仅对产生副作用有用,而在函数式编程中,您通常会尝试将副作用降至最低。出于这个原因,您可能会发现for/listfor/fold在惯用的Racket中实际上比普通的for更常用。

答案 1 :(得分:-1)

当前C列表必须为(cons (* i j) C)赋予新值,这可以使用set!完成:

(define (dProduct A B)

  (define C '()) 

  (for ([i A] [j B])
    (displayln (* i j))          
    (set! C (cons (* i j) C)))   ; NOTE set! HERE.

  (for ([k C])
    (displayln k)))

请注意,强烈建议不要使用set!for/list是获得预期结果的更好方法。