【问题标题】:Making a random list in Scheme在 Scheme 中制作随机列表
【发布时间】:2012-11-25 21:58:30
【问题描述】:

我只是想随机制作一个列表并在更大的函数中使用它。

        (define make-random-list
        (if
          (= (random 2) 0) (list 2 3)
                           (list 3 2)))

这只会产生列表 (2 3),我不知道为什么。发生了什么导致这种情况?

如果我这样写,我可以使函数工作

  (define make-random-list
   (lambda (x)
   (if
    (= (random x) 0) (list 2 3)
                     (list 3 2))))

并调用 (make-random-list 2)

但我不明白为什么这会起作用而另一个不会。不允许第一个函数产生随机结果的方案是怎么回事?

【问题讨论】:

    标签: list random scheme


    【解决方案1】:

    在您的第一个 sn-p 中,您将一次性计算的结果分配给一个变量。您需要在这里定义一个函数,该函数将在每次调用时进行评估。您的第二个 sn-p 正是这样做的,但有一种更短的方式来表达相同的意思:

    (define (make-random-list x)
    (if
      (= (random x) 0) (list 2 3)
                       (list 3 2)))
    

    请注意语法上的区别:函数定义将函数定义连同括号中的形式参数名称一起括起来,而变量名称周围没有括号。

    【讨论】:

    • 我不太明白其中的区别。如果我调用第一个函数 100 次,它每次都会得到相同的结果,但如果我调用 (random 2) 100 次,它不会每次都一样。
    • 第一个没有定义函数。该 sn-p 计算一个随机列表并将其存储在一个名为 make-random-list 的变量中。无论您检索多少次,该变量的值都保持不变。
    • 哦,好吧,我现在明白了,所以如果我按 ctrl-r(运行)然后再次运行代码,它可能会得到不同的结果,因为它是再次计算的?现在我所做的就是让它显示第一个计算,如果我只是继续输入 make-random-list?
    • 是的,我相信重启你的程序会导致值改变。
    • @AlexeyFeldgendler defun 用于 Common Lisp,这个问题被标记为scheme,我们使用define 来定义函数。您对 OP 的回答不正确。
    【解决方案2】:

    在 Scheme 中,函数是通过显式使用 lambda 来定义的,如下所示:

    (define square
      (lambda (x)
        (* x x)))
    

    或者像这样,它是先前语法的简写,并且隐含地使用 lambda 在后台 - 两种过程定义的风格完全等效:

    (define (square x)
      (* x x))
    

    您的代码的第一个版本不起作用,因为这只是将 if 的评估结果分配给名为 make-random-list 的变量:

    (define make-random-list
      (if (= (random 2) 0)
          (list 2 3)
          (list 3 2)))
    

    要在 Scheme 中定义过程,您必须显式或隐式地使用 lambda。因此,您的过程应该使用以下任何一种等效形式来定义:

    (define make-random-list
      (lambda ()
        (if (= (random 2) 0)
            (list 2 3)
            (list 3 2)))
    
    (define (make-random-list)
      (if (= (random 2) 0)
          (list 2 3)
          (list 3 2)))
    

    请注意,如果唯一可能的值是 2,则不必传递 x 参数,只需声明一个不带参数的过程。

    【讨论】:

    • 啊,谢谢,这当然是有道理的。就像一般编码规则一样,如果我只在另一个函数中专门使用这个函数,我应该在内部定义它还是只在其余函数中定义它?
    • @Jordan 我的经验法则是:如果我在多个地方使用相同的 sn-p 代码,请将其打包为单独的过程。如果我只在一个过程中使用它,请将其作为内部定义打包到该过程中 - 这样,如果在某个时候您发现该过程在其他地方有用,则很容易将其提取到外部
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 2019-10-23
    • 1970-01-01
    • 2023-04-04
    • 2012-07-14
    • 2011-03-08
    • 2011-02-26
    相关资源
    最近更新 更多