- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
自从我接触到 Scheme 并决定使用 Scheme 实现命令行收入分区器已经有几个月了。
我最初的实现在延续上使用了简单的递归,但我认为延续会更适合这种类型的程序。如果有人(比我更精通 Scheme)可以看看这个并提出改进建议,我将不胜感激。我就是那个倍数(display...
行也是使用宏的理想机会(我还没有接触到宏)。
(define (ab-income)
(call/cc
(lambda (cc)
(let
((out (display "Income: "))
(income (string->number (read-line))))
(cond
((<= income 600)
(display (format "Please enter an amount greater than $600.00~n~n"))
(cc (ab-income)))
(else
(let
((bills (* (/ 30 100) income))
(taxes (* (/ 20 100) income))
(savings (* (/ 10 100) income))
(checking (* (/ 40 100) income)))
(display (format "~nDeduct for bills:---------------------- $~a~n" (real->decimal-string bills 2)))
(display (format "Deduct for taxes:---------------------- $~a~n" (real->decimal-string taxes 2)))
(display (format "Deduct for savings:-------------------- $~a~n" (real->decimal-string savings 2)))
(display (format "Remainder for checking:---------------- $~a~n" (real->decimal-string checking 2))))))))))
(ab-income)
要求输入,如果提供低于 600 的任何值(据我的理解)返回
(ab-income)
在
current-continuation
.我的第一个实现(正如我之前所说的)使用纯简递归。也不错,但我认为每次回电到
(ab-income)
如果该值低于 600,则继续扩展该功能。
最佳答案
首先,你不需要继续。按照标准,Scheme会一直执行tail call optimization .尾调用是一个函数调用,它位于函数的最后位置;运行该调用后,不会发生任何其他事情。在这种情况下,我们不需要保留我们当前所在的激活记录;一旦我们调用的函数返回,我们就会弹出它。因此,尾调用会重用当前的激活记录。例如,考虑一下:
(define (some-function x y)
(preprocess x)
(combine (modified x) y))
(some-function alpha beta)
some-function
,我们为其在栈上的激活记录分配空间:局部变量、参数等。然后我们调用
(preprocess x)
.由于我们需要返回
some-function
并继续处理,我们必须保留
some-function
的激活记录,因此我们为
preprocess
推送新的激活记录.一旦返回,我们弹出
preprocess
的堆栈帧并继续。接下来,我们需要评估
modified
;同样的事情必须发生,当
modified
返回,其结果被传递给
combine
.有人会认为我们需要创建一个新的激活记录,运行
combine
,然后将此返回给
some-function
——但是
some-function
不需要对该结果做任何事情,但返回它!因此,我们覆盖了当前的激活记录,但不理会返回地址;当
combine
返回,然后,它将其值返回到等待它的确切值。在这里,
(combine (modified x) y)
是尾调用,评估它不需要额外的激活记录。
(define (my-while cond body)
(when (cond)
(body)
(my-while cond body)))
(let ((i 0))
(my-while (lambda () (< i 10))
(lambda () (display i) (newline) (set! i (+ i 1)))))
my-while
的调用。 .然而,由于尾调用优化,对
my-while cond body
的递归调用是一个跳转,并且不分配内存,使其与迭代一样高效。
display
block ,你可以用一个普通的函数来做到这一点。宏允许你在某种程度上改变语言的语法——添加你自己的
define
,实现一些不评估其所有分支的类型案例构造,等等。当然,它仍然是 s-expression,但语义不再简单地“评估参数并调用函数”。然而,这里只需要函数调用语义。
(require (lib "string.ss"))
(define (print-report width . nvs)
(if (null? nvs)
(void)
(let ((name (car nvs))
(value (cadr nvs)))
(display (format "~a:~a $~a~n"
name
(make-string (- width (string-length name) 2) #\-)
(real->decimal-string value 2)))
(apply print-report width (cddr nvs)))))
(define (ab-income)
(display "Income: ")
(let ((income (string->number (read-line))))
(if (or (not income) (<= income 600))
(begin (display "Please enter an amount greater than $600.00\n\n")
(ab-income))
(begin (newline)
(print-report 40 "Deduct for bills" (* 3/10 income)
"Deduct for taxes" (* 2/10 income)
"Deduct for savings" (* 1/10 income)
"Remainder for checking" (* 4/10 income))))))
mzscheme
版本中, 我需要一个
(require (lib "string.ss"))
要导入的行
real->decimal-string
.接下来,我抽象出
display
block 你说的。我们看到的是,每一行都想在第 40 列以相同的格式打印钱,打印一个标签名称和前面的一行破折号。因此,我写了
print-report
.第一个参数是初始宽度;在这种情况下,
40
.其余参数是字段值对。每个字段的长度(冒号和空格加上两个)从宽度中减去,我们生成一个由那么多破折号组成的字符串。我们使用
format
以正确的顺序排列字段,
display
打印字符串。该函数对所有对进行递归(使用尾递归,因此我们不会破坏堆栈)。
(display "Income: ")
到
let
之前;你忽略了它的结果,那么为什么将它分配给一个变量呢?然后我增加了
if
测试条件
input
为假,发生在
string->number
无法解析输入。最后,我删除了你的局部变量,因为你所做的只是打印它们,并使用 Scheme 的分数语法而不是除法。 (当然,我使用
print-report
而不是
display
和
format
。)
关于scheme - 实用方案编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2659227/
我应该编写一个函数来打印一组给定的三个数字中两个较大数字的平方和。 我对这种情况的处理相当笨拙。我没有编写返回一组 3 中最大的两个数字的函数,而是编写了函数,以便表达式减少到两个所需的数字。 # S
如果有人可以提供帮助,我将不胜感激。我一直在敲我的头一天试图让这个工作。我已经在互联网上搜索并重新阅读了手册,但我就是不明白。 guile << __EOF__ ( define heading-li
目前我正在处理一个方案问题,其中我们正在使用方案列表表示一个图。我们使用的第一个变体是表示为 的边列表图 '((x y) (y z) (x z)) 我们正在使用的图的第二个变体被称为 x 图,表示为
我正在尝试创建一个函数,该函数将两个函数作为参数并执行它们。 我尝试使用 cond ,但它只执行 action1 . (define seq-action (lambda (action1 act
我提前为我的原始英语道歉;我会尽量避免语法错误等。 两周前,我决定更新我对 Scheme(及其启示)的知识,同时实现我在手上获得的一些数学 Material ,特别是我注册的自动机理论和计算类(cla
Scheme中有没有函数支持分数的“div”操作? 意思是 - 11 格 2.75 = 4。 最佳答案 我认为你的问题的答案是:没有,但你可以定义它: #lang racket (define (di
我在scheme中实现合并排序,我必须通过定义两个辅助方法来实现:merge和split。 Merge 需要两个列表(已经按递增顺序)并将它们合并在一起。我这样做了如下: (define merge
尝试从终端加载方案文件。我创建了一个名为 test.scm 的文件,其中包含以下代码: (define (square x) (* x x)) (define (sum-of-squares x y)
我有以下代码: (define (howMany list) (if (null? list) 0 (+ 1 (howMany (cdr list))))) 如果我们执行以
我有点了解如何将基本函数(例如算术)转换为Scheme中的连续传递样式。 但如果函数涉及递归怎么办?例如, (define funname (lambda (arg0 arg1)
我正在尝试附加两个字符串列表 但我不知道如何在两个单词之间添加空格。 (define (string-concat lst1 lst2) (map string-append lst1
这个问题已经有答案了: How do I pass a list as a list of arguments in racket? (2 个回答) 已关闭 8 年前。 我有一个函数,它需要无限数量的
我对这段代码的工作方式感到困惑: (define m (list 1 2 3 '(5 8))) (let ((l (cdr m))) (set! l '(28 88))) ==>(1 2 3 (5 8
我正在为学校做一项计划作业,有一个问题涉及我们定义记录“类型”(作为列表实现)(代表音乐记录)。 我遇到的问题是我被要求创建一个过程来创建这些记录的列表,然后创建一个将记录添加到该列表的函数。这很简单
我有以下代码: (define (howMany list) (if (null? list) 0 (+ 1 (howMany (cdr list))))) 如果我们执行以
我正在尝试附加两个字符串列表 但我不知道如何在两个单词之间添加空格。 (define (string-concat lst1 lst2) (map string-append lst1
如何使用抽象列表函数(foldr、foldl、map 和 filter 编写函数),无需递归,消耗数字列表 (list a1 a2 a3 ...) 并产生交替和 a1 - a2 + a3 ...? 最
我试图找出在 Scheme 中发生的一些有趣的事情: (define last-pair (lambda (x) (if (null? (cdr x))
这个问题在这里已经有了答案: Count occurrence of element in a list in Scheme? (4 个答案) 关闭 8 年前。 我想实现一个函数来计算列表中元素出现
我正在尝试使用下面的代码获取方案中的导数。谁能告诉我哪里出错了?我已经尝试了一段时间了。 (define d3 (λ (e) (cond ((number? e) 0) ((e
我是一名优秀的程序员,十分优秀!