webdancer's Blog

Scala学习--Program Paradigm

Program Paradigms

  • Imperative Programming: modifying mutable variables, assignments, control structure;
  • Fuctional Programming:
    • Strictly, No mutable variables, No assignments, No loops.
    • Widely, Focusing on functions, function is the first citizens

  

  • logical programming

理解过程抽象

在学习编程的过程中,一个核心的任务是编写可以完成我们任务的函数。不管我们使用的什么语言,做什么开发,函数抽象并不少见。所谓的函数,我认为就是一些语句的集合,完成一个特定的任务。有了函数,我们思维时的操作原子型的层次变的比较高,思维的难度就会降低。但是在不同的编程实践中,为了完成任务需要的编写函数的思维方式也许是不同的,这会受到编程语言或是第三方库的影响。

在面向对象编程中,想得是如何构建类以及如何设计类之间的关系,充分利用对象的特性,例如在使用Java编程中,会想着如何设计Class,使用什么样的设计模式,这时候函数抽象的层次依赖与我们的类设计。在使用C这样的编程语言时,使用面向对象的设计,还是直接使用函数用来模块化,也会带来不同的设计函数的思维方式。使用像Lisp这样的函数式编程语言时,我们的思维与过程式的编程语言的方式可能会有很大的不同,函数就处于核心地位了。编程的思维可能会受到我们学习过的很多东西的影响,正如上面我陈述的。我的经验是学会抽象和使用语言提供的高层抽象,这样会大大的减低我们抽象函数的难度,使我们的注意力集中到解决我们的问题。通过自己的抽象和语言提供的高层抽象来实现层次化。
 
下面我使用不同的编程语言实现了冒泡排序,体会一下编程语言对我们思维的影响。
对冒泡排序,我还是比较熟悉的。算法的基本思想就是:两个指针i,j,i控制每次冒泡一遍的bubble的位置,j控制每一边冒泡时要比较的数的位置,两次循环就行了。
 
C语言实现
#include<stdio.h>

    void swap_int(int * a, int * b){
        int tmp=0;
        tmp=*a;
        *a=*b;
        *b=tmp;
    }

    void bubblesort(int * a,int n){
        int i;
        int j;
        for(i=0;i<n-1;i++){
            for(j=n-1;j>i;j--){
                if (a[j]<a[j-1]){
                    swap_int(&a[j],&a[j-1]);
                }
            }
        }
    }
在写这段代码时,我饭的错误就是给`swap_int`传递实参的时候没有取地址,这就是我对`C`语言的思维的盲区,对于`a[j]`与`a+j`我没有他们不同的认识。
 
python实现
    def bubblesort(l):
        n=len(l)
        for i in range(n-1):
            for j in range(n-1,i,-1):
                if l[j]<l[j-1]:
                    l[j],l[j-1]=l[j-1],l[j]
显然`python`要比C短的多,但这不代表我没有出错,因为有一段时间没写代码了,所以对`range(a,b)`的区间表示方式到底用了`[a,b]`还是`[a,b)`已经有点模糊不清了,所以就出了错。当然这种基本的问题,我们应该很明确的,但是尽管如此,我还是出错了。
 
java实现
    public class BubbleSort{

        public static void sort(int[] l){
            int n=l.length;
            for(int i=0;i<n;i++){
                for(int j=n-1;j>i;j--){
                    if(l[j]<l[j-1]){
                        swap_int(l,j,j-1);
                    }
                }
            }
        }

        private static void swap_int(int[] l,int m,int n){
            int tmp=l[m];
            l[m]=l[n];
            l[n]=tmp;
        }
    }
尽管`java`代码已经很久没写了,但是`java`与`c`的过程太相似了,基本没有费功夫,这里就是感觉java只有传值的参数传递方式的原因,`swap`函数一点也不优雅。
 
scheme实现
    (define (bubblesort l)
     (let ((n (vector-length l)))
     (map (lambda (i)
           (map (lambda (j) 
                 (if (< (vector-ref l j) (vector-ref l (- j 1)))
                  (swap l j (- j 1))))
            (range (- n 1) i -1)))
           (range 0 n 1))))

    (define (swap l a b)
     (let ((tmp (vector-ref l a)))
      (vector-set! l a (vector-ref l b))
      (vector-set! l b tmp)))

    (define (range low high step)
     (if (or (and (> step 0) (> low (- high 1))) (and (< step 0) (< low (+ high 1))))
      ()
      (cons low (range (+ low step) high step))))

    (define l (vector 2 3 1 5 4 7 8 9 1))
    (bubblesort l)
    (display l)
写`scheme`代码,因为最近在看`SICP`,所以代码的错误只是笔误,变量名写错这样的原因,可是我还是没能使用函数式的编程方式来写这段代码,主要就是函数式编程就要使用辅助的空间,所以使用了赋值操作。
 
从上面的过程中我有这么几个总结:
  1. 过程抽象对于我们解决问题,非常有用。使用高级语言提供的机制,可以大大解放我们的编程效率。
  2. 理解问题的时候,通常没法子一下理解的很好,所以在对问题的理解上,要多花功夫。
  3. 在写过程式的语言时,对于一些地方很模糊,这就是我们训练的地方。
  4. 函数式的编程方式,对思维的训练量很大。
思维是一个逐渐完善的过程,我们不能期望它一下子满足期待,要循序渐进的推进。要不断的训练,并且反馈,也许我们才会有一个比较好的抽象函数的能力,不管是面向对象编程还是函数式编程。

 

“代码大全”读后感

“我们的精神品德既非与生俱来,也非逆于天性,...,其发展归因于习惯,...,我们要学的东西都通过实际做的过程学到,...,如果人们建的房子好,他们就成为好的建设者;而造的房子不好时,他们就是差的建设者,...,所以小时候养成怎样的习惯关系很大——正是它会造成天壤之别,或者说就是世上所有差异之源。”       ——亚里士多德

代码大全旧的内容很多,交给了我们许多软件工程中的解决写软件过程中难题的解决办法。因为自己还没有接触过大型的项目,对于其中的一些并没有很强的共鸣,不过我相信在以后的工作中还是很有用的。下面就简单说一下自己的看书感受:

  1. 编程需要经验的传授。就像是武侠小说里面一样,一个大侠要练成绝世武功,要么像张无忌一样,偶然的机会得到了像《九阳真经》这样的武功秘籍,要么像郭靖一样,有洪七公这样的前辈教授。他们无不是从前人那里继承了技能和经验,自己发明一门武功的人真的少之又少,编程和练武也一样,很多良好的编程技巧需要学习,代码大全详细的记录了各种技巧,小到如何定义变量名,大到如何管理一个大型的软件项目,都给出了许多建议,这对我们大学生来说,还是挺有用的,很多东西,老师都没讲过。
  2. 编程是一个渐进的过程。很多时候,我们拿到问题就开始编写代码,这通常并不好。因为一个问题的解决从来都不是那么容易的,而且直接写代码,我们通常需要花费好几倍的时间来调试代码。编程的时候,我们可以先想一下我们要解决的具体问题,首先把问题搞明白,然后再写伪代码,这样我们用自然语言的方式先大体回答了我们要解决的问题(要是在软件工程中,就是一个需求分析,系统设计的过程),然后我们在开始将伪代码转化成代码,这个过程由于前面我们已经解决了很多东西,在这时候我们可以专心写代码。
  3. 编程需要的东西很多,我们需要逐渐积累。就像建筑师,要积累设计经验一样,我们程序员也要注意积累经验。现在由于搜索引擎太好用了,需要的时候可以搜索,对于很多东西缺乏思考。
  4. 编程需要好的编程环境和工具。良好的编程工具会极大的提高编程效率,所以一定要为自己选择一个良好的编程环境。
  5. 这本书是一部大块头,需要的时候翻翻,要一下子消化所有的东西不可能。

 




Host by is-Programmer.com | Power by Chito 1.3.3 beta | © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee