【问题标题】:I am trying to sum each parameter with a value, what is wrong with my code?我正在尝试将每个参数与一个值相加,我的代码有什么问题?
【发布时间】:2015-05-07 05:05:52
【问题描述】:

我基本上是Scheme的新手,这是我第二次尝试解决某个问题。

所以我要做的基本上是将我们传递给函数的每个参数与一个适当的值相加 例如:

 (sum 3 1 2 0 2) ;would return 228

这是我的代码:

(define  (sum one five ten twenty fifty hundred)
    (+ (* 1 one)(* 5 five) (* 10 ten) (* twenty 20) (* 50 fifty) (* 100 hundred)) 

我认为一个可能的解决方案是使用 lambda 函数,但我不知道如何实现它。

【问题讨论】:

  • 1.不要使用逗号分隔函数调用的参数。你使用空格。 2. 您缺少twentyfifty 参数。因此,您的函数调用应该是(sum 3 1 2 0 0 2)
  • @ChrisJester-Young 已编辑和更正。
  • 我的第二点还没有更正。你的函数有 6 个参数,但你只传递了 5 个参数。
  • @ChrisJester-Young 我可以跳过我不想使用的参数吗?有什么方法可以传递 5 个参数而不是像我一样传递 6 个参数?
  • 在您的具体情况下,您确实应该让您的函数采用关键字(命名)参数。让我写一个答案来演示这个概念。

标签: function lambda functional-programming scheme


【解决方案1】:

这是一种计算数字的方法,只需发送 5 个参数而不是 6 个:

(define sum
    (lambda (L skip) ;stores yourList and the number you want to skip
       (define loop
          (lambda (L L2 total) ;yourList, (1,5,10...) list, running total
             (cond
               ((null? L) (list total)) ;print the total when finish yourList

               ;if the next number is the skip number, just move on to next value
               ((= (car L2) skip) (loop L (cdr L2) total)) 

               ;otherwise, increase total and send in both lists, minus the head, to the loop
               (else (loop (cdr L) (cdr L2) (+ total (* (car L) (car L2)) ))) 
              )
           )
        )(loop L (list 1 5 10 20 50 100) 0) ;initial values of loop
    )
)

;send in your list of numbers, plus the value place you want to skip
(sum (list 3 1 2 0 2) 20) ; ==> 228

不过,我会更容易用 0 填写所有你不想要的地方。一旦你有 6 个参数,下面的代码就可以工作了。

(define sum
    (lambda (one five ten twenty fifty hundred)
        (+ (* 1 one) (* 5 five) (* 10 ten) (* 20 twenty) (* 50 fifty) (* 100 hundred) )
    )
)

(sum 3 1 2 0 0 2)

【讨论】:

  • 不是最简单的解决方案,但绝对解决了我的问题。谢谢
【解决方案2】:

OP 希望能够传递比参数少的参数。在这种特定情况下,最好使用关键字(命名)参数。以下是你可以这样做的方法(在 Racket 语法中):

(define (total-bills #:ones (ones 0)
                     #:fives (fives 0)
                     #:tens (tens 0)
                     #:twenties (twenties 0)
                     #:fifties (fifties 0)
                     #:hundreds (hundreds 0))
  (+ ones (* fives 5) (* tens 10) (* twenties 20) (* fifties 50) (* hundreds 100)))

(每个变量名后面的0是默认值,也就是不指定它的值。)

示例用法:

> (total-bills #:ones 3 #:fives 1 #:tens 2 #:hundreds 2)
228

【讨论】:

  • 谢谢你的想法,但是我们如何用普通的旧方案来写呢?
  • 标准方案没有可选参数。
  • 可选参数呢?这是一个例子:docs.racket-lang.org/guide/lambda.html
  • 您可以使用点尾表示法使用可选参数:(define (sum . args) (apply + (map * args '(1 5 10 20 50 100))))。在某些方案中,您可能需要加载 SRFI-1,以便 map 在其参数列表中最短时停止。
  • @chris-jester-young 你当然是对的。但是,我在回答如何使用可选参数来做到这一点,这本质上不允许在中间省略参数。最后只能省略参数。没有标准化的方式来命名参数(尽管有一些 SRFI 和 DSSSL,CHICKEN 实现了)
【解决方案3】:

如果您想在普通旧方案中使用与Chris' answer 类似方案的标准方案,您需要计划如何识别您的号码使用的货币。也许通过成对发送它们既更容易实现又更简单使用:

#!r6rs
(import (rnrs))

(define (total-bills . args)
  (fold-left (lambda (acc x)
               (+ acc (apply * x)))
             0
             args))

(total-bills '(5 1) '(2 10) '(3 100)) ; ==> 325
(apply total-bills '((1 3) (5 1) (10 1) (20 2))) ; ==> 58

您可以创建一个程序,根据您传递给它的货币创建一个专门的程序:

#!r6rs
(import (rnrs))

(define (make-currency-procedure . currencies)
  (lambda amounts
    (fold-left (lambda (acc currency amount)
                 (+ acc (* currency amount)))
               0
               currencies
               amounts)))

(define small-bills (make-currency-procedure 1 5 10 20))
(define large-bills (make-currency-procedure 10 100 1000 10000))

(small-bills 3 1 1 2) ; ==> 58
(small-bills 0 1 0 1) ; ==> 25
(large-bills 3 1 1 2) ; ==> 21130
(large-bills 0 1 0 1) ; ==> 10100

【讨论】:

  • 但是为什么我们会有小额钞票和大额钞票呢?我们不能将它们组合成一个函数吗?
  • @Predator44 是的。您可以使用任意组合创建一个程序,但是您在其中定义的所有货币都将按照您定义它们的顺序成为必需的。要获得类似于 Chris 的可选输入的内容,第一个示例是一种更好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-03
  • 2012-06-25
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 2015-12-23
  • 2022-11-28
相关资源
最近更新 更多