Scheme之功能分解和封装内部函数/块结构

博客介绍了如何使用Scheme语言解决特定问题,即输出0到x之间3的倍数且包含数字5的数。通过讨论递归和内部函数/块结构的重要性,强调了功能分解在解决复杂问题时的作用,指出在Scheme中使用类似for的结构可能会有所不同,并暗示在处理特定条件(如同时含5和7)时,功能分解能简化问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

待解决的问题:输出0-x之间 3的倍数而且含5的数,如15,54,555等等(或者输出这种数的个数)。

在《编程导论(Java)》中以这个例子介绍结构化分解。所以用Scheme实现一下。

package semantics.method;
public class HelperMethodDemo{
    //简单情况:输出0-x 之间 3的倍数而且含5的数. //
    private static boolean is3X(int n){
        return ( n%3 == 0);
    }
    private static boolean isInclude5(int n){
        while ( n != 0){
            if (n % 10 == 5) return true;
            n /=10;
        }
        return false;
    }

    /**采用功能分解。觉得这个问题有点难,需要分解*/
    static void foo(int x){
        for(int i=0;i < x;i++){
            if( is3X(i) && isInclude5(i) ){
                System.out.print(" "+i);
            }
        }
    }

    /**不需要分解。觉得这个问题较容易。 */    
    static void foo_0(int x){
        for(int i=0;i < x;i++){
            if(i%3== 0){ 
                int m = i; 
                while(m!=0){
                    if(m%10 == 5 ){
                        System.out.print(" "+i);
                        break;
                    }
                    m/=10; 
                }//end while                
            } 
        } 
    }
}
【解】按照功能分解的基本思想:对于较复杂的问题,分解成较简单的小问题,而后通过函数调用解决该问题。上述问题可以分解为:(1)一个数是否3的倍数,由函数is3X?实现;(2)一个数是否包含5,由函数isInclude5?实现;(3) 对于[0,x]中所有符合要求的数,get解决该问题。

(define (is3X? n)
    (= 0 (modulo n 3)))
注:没有%操作符,因为对于complex求余没有意义。参考R5RS,找到modulo 。

(define (isInclude5? n)
  (cond 	( (= 0 n) #f)
                ( (= 5 (modulo n 10)) #t)
                (else (isInclude5? (quotient n 10)) )))

注:递归吧

(define (p n)
   (begin (display n) (newline))
)

注:p这个是标准的助手方法

(define (get n)
(if 	(< 0 n)  
(begin 
(if  (and (is3X? n) ( isInclude5? n))
(p n) 
)
(get (- n 1)) )
(p "over")))

:这个写起来好麻烦。还是不习惯scheme。

关于递归,哼一句:大多数情况下,迭代法和递归法能够相互转化,即能用递归处理的算法可以采用迭代法,反之亦然。如果你愿意,Java的循环也可以全部采用递归。

Scheme,搞个for结构会咋样。

在必须递归情况下,憋的有点难受。

再假定待解决的问题为:输出0-x之间 3的倍数,而且含5并含7的数。编写一个单一方法就比较困难,而功能分解有助于问题的解决。

内部函数/块结构

对于用户而言,他仅仅关心get函数,而出于功能分解目的而得到的方法——称之为助手函数,在Java中常常设定为private方法。Scheme没有private这样的访问修饰符,而解决is3X?等函数名占用名称空间(用户可能也希望定义is3X?函数)、隐藏助手函数的手段是 内部函数——在函数内部定义的函数

(define (get n)
  (define (is3X? n)
    (= 0 (modulo n 3)))
  (define (isInclude5? n)
    (cond 	( (= 0 n) #f)
        ( (= 5 (modulo n 10)) #t)
       (else (isInclude5? (quotient n 10)) )))
  (define (p n)
    (begin (display n) (newline))
  ) 
(if 	(< 0 n)  
(begin 
(if  (and (is3X? n) ( isInclude5? n))
(p n) 
)
(get (- n 1)) )
(p "over")))
另外,get函数的参数n,它的作用域是整个get函数。对于助手函数如is3X?,如果get传递给is3X?的实参是n,则可以省略内部函数is3X?对应的形参名。在Java中,若干助手方法都需要使用的参数,通常提升为类的成员变量,不需要在助手方法中传来传去;Scheme的若干内部函数都需要使用的参数,可以提升为主函数的局部变量或形参。
注意:is3X?的参数可以省略,但是(p "over")说明它需要参数;而(isInclude5? n)说明了参数的可见性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值