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

待解决的问题:输出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)说明了参数的可见性。

时间: 2024-10-31 00:31:31

Scheme之功能分解和封装内部函数/块结构的相关文章

脚本免杀概述

手机打字实在在麻烦,所以一些比较简单或太复杂的代码我就不直接提供实例了. 1.不是方法的方法--加注释 加一些规则无用不含特征码的注释.代码略 2.大小写混编 利用VBS忽略大小写 3. 分行与同行混用 利用冒号(:)连接多行代码为一行 4.一行分多行 使用续行符(_)将一行分多行写 5.利用execute函数 复制代码 代码如下: Execute("createobject("&chr(34)&"wscript.shell"&chr(34)

PHP|开发必知的良好实践

过滤.验证.转义 所有这些外部资源都不能完全相信 $_GET $_POST $_REQUEST $_COOKIE $argv php://stdin php://input file_get_contents() 远程数据库 远程API 客户端的数据 过滤 使用htmlentities()过滤HTML,将特殊字符转换为HTML实体,转义输出,第二个参数使用ENT_QUOTES. 使用PDO预处理语句过滤SQL注入. 使用filter_var() & filter_input()函数来过滤和验证不

Scheme 4 Javaer-2.功能抽象

<编程导论(Java)?第3章功能抽象>按照功能抽象的逻辑发展,介绍在Java语言环境中的三种流程.子程序和结构化分解.接口与实现相分离以及抽象方法--功能抽象的最高形式.而把操作/表达式是Java编程中最原始和起步级别的功能抽象. SICP中,作为函数式编程语言的Scheme,它以表达式为基本单元,其功能抽象/函数抽象更为直接:按照丘奇的λ演算,完成对函数抽象的基本描述: W是参数为变量x的λ表达式,则λx . W是λ表达式,如λx.( x+1).这种表达式λx . W给出了一个函数的定义:

开始学习Scheme

开始学习Scheme 函数式编程(Functional Programming)是在MIT研究人工智能(Artificial Intelligence)时发明的,其编程语言为Lisp.确切地说,Lisp是一个语言家族,包括无数的方言如:Scheme.Common Lisp.Haskell--等等. 最后一次学习Scheme已经是去年7月份的事情了.本来只是出于兴趣,以及拓宽自己思路的目的来学习.未曾想,由于工作需要,Scheme编程已经成为一个必备的技能了.其实这里面也由办公室政治的原因,因为我

《javascript设计模式》读书笔记二(封装和隐藏信息)

1.为什么要封装和信息隐藏 做过编程的朋友们知道"耦合"这个词,其实封装的效果就是为了解耦,让类和类之间没有太多的联系,防止某一天修改某一类的时候,产生"多米骨诺牌效应". 我们可以把信息隐藏看成目的,把封装看成达到信息隐藏的技术.通过封装就可以把对象的内部数据表现形式和实现细节进行隐藏.就好比你会看电视,但是你不知道电视的内部结构一样.但是在javascript中没有任何内置的机制,所以我们还需做些处理,同样来模仿封装. 2.创建对象的方法 1)最简单的一种方法就

封装自己的framework静态库

ios中我们写的代码有时不愿意让别人看到,可能对它进行封装,生成一个静态库如典型的.a,还有一种就是和 苹果自带的库一样的后缀名为.framework的库,个人推荐使用.framework,因为.a不仅要装其添加进去,还要 将对应的头文件添加到项目中. 1.新建一个静态库工程.file--new--project,弹出框中选择Ios--framework&library中的cocoa touch static library.点击NEXT.输入product name,这里为libZW. 2.删

[Scheme入门]3 高阶函数

 1.高阶函数的介绍 高阶函数的英文名称是Higher Order Function,它们是以函数为参数的函数.主要用于映射(mapping).过滤(filtering).归档(folding)和排序(sorting)表.高阶函数让程序更具模块性,让函数更加通用. 函数sort具有2个参数,一个是需要排序的表,另一个是定序(Ordering)函数.下面展示了按照大小将一个整数表正序排序.而<函数就是本例中函数的定序函数. (sort'(420 -130 138 983 0 298 783 -

Scheme中lambda表达式与函数指针小例

SICP/Chapter2/Exercise-2.4 Lambda表达式语法 (lambda kw-formals body) 题目描述 用过程性表示方式重写序对的cons.car.cdr Scheme代码 (define (cons-24 x y) (lambda (m) (m x y))) (define (car-24 z) (z (lambda (p q) p))) 这段代码只有4行,但是逻辑关系并不好理解. 原因在于函数式语言的自顶向下实现方式不符合一般的逻辑习惯. lambda以类似

[爬虫学习笔记]ScrapySharp简单封装为Requester

为了便于使用及日后的扩展,将Scrapy简单封装为了Requester,具体代码如下: using System; using System.Collections.Generic; using Crawler.Common; namespace Crawler.Protocol { public class Requester { private Uri Url { get; set; } private Browser Browser { get; set; } public Request