Ruby Quick Start (2) -- Objects in Ruby

《Ruby语言入门教程v1.0》笔记(2)


第四章 Ruby面向对象初探

1. 封装

让我们来定义一个类, 类名是 Person类名首字母要大写
属性有姓名@name、年龄@age、国籍@motherland,实例变量用@开头;
方法有一个,叫 talk, 方法名和参数名应该用一个小写字母开头或者用一个下划线开头。

Person.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Person
def initialize(name, age = 18)
@name = name
@age = age
@motherland = "China"
end # 初始化方法结束
def talk
puts "my name is " + @name + ", age is " + @age.to_s
if @motherland == "China"
puts "I am a Chinese."
else
puts "I am a foreigner."
end
end # talk方法结束
attr_writer :motherland # @motherland的setter
end
p1 = Person.new("Yilin", 23)
p1.talk
p2 = Person.new("Ben")
p2.motherland = "ABC"
p2.talk

initialize 是初始化方法,相当于构造函数。
参数 age 有一个缺省值 18,可以在任何方法内使用缺省参数,而不仅仅是 initialize
如果有缺省参数, 参数表必须以有缺省值的参数结尾。

注意我们定义了@motherland成员变量的setter:

Ruby Quick Start (1) -- A Glimpse of Syntax

学习Ruby时在网上找到了一本小册子《Ruby语言入门教程v1.0》,虽然是07年的东西了,但是作为快速熟悉Ruby基本语法还是很有帮助的,做一下笔记。

开始前先问下自己两个问题。

(1) 我为什么要学习Ruby?

为了Web开发。

(2) 为什么选择Ruby,而不是Python,PHP?

看了知乎上的这个答案

  • 假如你想帮他尽快找个活儿, 赚到钱, 推荐 PHP
  • 假如你想让他成为一个高效工程师, 推荐 Python
  • 假如你想让他爱上他的工作, 推荐 Ruby

无论如何,别人的答案只能作为参考,自己尝试过后才有资格评价,所以最好的方法就是亲自动手学习下Ruby。

《编写高质量代码:改善C++程序的150个建议》读书笔记(2)

《编写高质量代码——改善C++程序的150个建议》读书笔记(1)



第二部分 编码习惯和规范篇

建议81:避免无意中的内部数据裸露

对于const成员函数,不要返回内部数据的句柄,因为它会破坏封装性,违反抽象性,造成内部数据无意中的裸露,这会出现很多“不可思议”的情形,比如const对象的非常量性。

建议82:积极使用const为函数保驾护航

const的真正威力体现在几个方面:

  1. 修饰函数形式的参数:const只能修饰输入参数,对于内置数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”;
  2. 修饰函数返回值;
  3. 修饰成员函数:用const修饰成员函数的目的是提高程序的健壮性。const成员函数不允许对数据成员进行任何修改。

关于const成员函数,须遵循几个规则:

  1. const对象只能访问const成员函数,而非const对象可以访问任意的成员函数;
  2. const对象的成员是不可修改的,然而const对象通过指针维护的对象却是可以修改的;
  3. const成员函数不可以修改对象的数据,不管对象是否具有const性质。

建议83:不要返回局部变量的引用

局部变量的引用是一件不太靠谱的事儿,所以尽量避免让函数返回局部变量的引用。同时也不要返回new生成对象的引用,因为这样会让代码层次混乱,让使用者苦不堪言。

建议84:切忌过度使用传引用代替传对象

相较于传对象,传引用的优点:它减少了临时对象的构造与析构,所以更具效率。但须审慎地使用传引用替代传对象,必须传回内部对象时,就传对象,勿传引用。

建议85:了解指针参数传递内存中的玄机

用指针参数传回一块动态申请的内存,是很常见的一种需求。然而如果不甚小心,就很容易造成严重错误:程序崩溃+内存泄露,解决之道就是用指针的指针来传递,或者换种内存传递方式,用返回值来传递。

1
2
3
4
5
// 指针型变量在函数体中需要改变的写法
void f(int *&x) // 使用指针变量的引用
{
++x;
}



《编写高质量代码:改善C++程序的150个建议》读书笔记(1)

前一段时间看了这本《编写高质量代码——改善C++程序的150个建议》,感觉和Effective C++有点类似。看完还是有不少收获的,在此整理、记录一下。



第一部分 语法篇

建议1:区分0的4种面孔

  1. 整型0,32位(4个字节);
  2. 空指针NULL,指针与int类型所占空间是一样的,都是32位;
  3. 字符串结束标志’\0’,8位,一个字节,与’0’有区别;
  4. 逻辑FALSE/falseFALSE/TRUEint类型,而false/truebool类型。

建议5:不要忘记指针变量的初始化

  1. 可以将其初始化为空指针0(NULL);
  2. 对于全局变量来说,在声明的同时,编译器会悄悄完成对变量的初始化。

建议6:明晰逗号分隔表达式的奇怪之处

  1. 在使用逗号分隔表达式时,C++会确保每个表达式都被执行,而整个表达式的值则是最右边表达式的结果
  2. 在C++中,逗号分隔表达式既可以用作左值,也可以用作右值

建议9:防止重复包含头文件

注意在大型项目中的形式应类似下面:

1
2
3
4
#ifndef _PROJECT_PATH_FILE_H
#define _PROJECT_PATH_FILE_H
// ...
#endif


建议10:优化结构体中元素的布局

把结构体中的变量按照类型大小从小到大依次声明,尽量减少中间的填充字节


Notes of Scala course on Coursera -- Week 2 (2)

Here are my notes for the week 2’s lecture of Functional Programming Principles in Scala on Coursera.





4. Example: Finding Fixed Points

4.1 Finding a fixed point of a function

A number x is called a fixed point of a function f if

For some functions f we can locate the fixed points by starting with an initial estimate and then by applying f in a repetitive way.

until the value does not vary anymore (or the change is sufficiently small).

Notes of Scala course on Coursera -- Week 2 (1)

Here are my notes for the week 2’s lecture of Functional Programming Principles in Scala on Coursera.




1. Recursion and Tail Recursion

1.1 Examples of Recursion

1
2
3
/* Euclid's Algorithm */
def gcd(a: Int, b: Int): Int =
if (b == 0) a else gcd(b, a % b)

gcd(14, 21) is evaluated as follows:

1
2
3
4
5
6
7
8
9
10
gcd(14, 21)
--> if (21 == 0) 14 else gcd(21, 14 % 21)
--> if (false) 14 else gcd(21, 14 % 21)
--> gcd(21, 14 % 21)
--> gcd(21, 14)
--> if (14 == 0) 21 else gcd(14, 21 % 14)
-->> gcd(14, 7)
-->> gcd(7, 0)
--> if (0 == 0) 7 else gcd(0, 7 % 0)
--> 7

Another example:

1
2
def factorial(n: Int): Int =
if (n == 0) 1 else n * factorial(n - 1)

factorial(4) is evaluated as follows:

1
2
3
4
5
6
7
factorial(4)
--> if (4 == 0) 1 else 4 * factorial(4 - 1)
-->> 4 * factorial(3)
-->> 4 * (3 * factorial(2))
-->> 4 * (3 * (2 * factorial(1)))
-->> 4 * (3 * (2 * (1 * factorial(0))))
-->> 4 * (3 * (2 * (1 * 1)))



1.2 Tail Recursion

Implementation Consideration:

If a function calls itself as its last action, the function’s stack frame can be reused. This is called tail recursion.

Tail recursive functions are iterative processes.

In general, if the last action of a function consists of calling a function (which may be the same), one stack frame would be sufficient for both functions. Such calls are called tail-calls.

Notes of Scala course on Coursera -- Week 1

Here are my notes for the week 1’s lecture of Functional Programming Principles in Scala on Coursera.

Evaluation of Programming

Every non-trivial programming language provides:

  • primitive expressions representing the simplest elements
  • ways to combine expressions
  • ways to abstract expressions, which introduces a name for an expression by which it can be referred to

A non-primitive expression is evaluated as follows:

  1. Take the leftmost operator
  2. Evaluate its operands (left before right)
  3. Apply the operator to the operands

A name is evaluated by replacing it with the right hand side of its definition.

Example:

1
2
3
4
(2 * pi) * radius
(2 * 3.14159) * radius
6.28318 * radius
6.28318 * 10

Definition can have parameters:

1
def square(x: Double) = x * x

Parameter and Return Types:

1
def power(x: Double, y: Int): Double = ...

Evaluation of Function Applications

  1. Evaluate all function arguments, from left to right.
  2. Replace the function application by the function’s right-hand side, and, at the same time,
  3. Replace the formal parameters of the function by the actual arguments.

Example:

1
2
3
4
5
6
7
8
sumOfSquares(3, 2+2)
sumOfSquares(3, 4)
square(3) + square(4)
3 * 3 + square(4)
9 + square(4)
9 + 4 * 4
9 + 16
25

The substitution model

The scheme of expression evaluation is called the substitution model.

The idea is that all evaluation dose is reduce an expression to a value.

It can be applied to all expressions, as long as they have no side effects.

The substitution model is formalized in the λ-calculus, which gives a
foundation for functional programming.

Start Learning Scala

还记得大三时候室友打印了一本厚厚的SICP来读,当时我还不以为意。不过读了Paul Graham《黑客与画家》后我也想亲自尝试一下,领略下Functional Programming(函数式编程)的威力。

于是选了Coursera上的函数式编程课程Functional Programming Principles in Scala,老师是欧洲名校EPFL(洛桑联邦理工学院)的教授,Scala语言的发明人Martin Odersky。目前我刚刚完成前两周的课程,这里从第一周的第一个Lecture里摘选一点内容,简单介绍一下函数式编程。


在说“函数式”之前,先要知道它是一种编程范式(Programming paradigm)

Wikipedia上指出:

编程范式是一类典型的编程风格,是指从事软件工程的一类典型的风格(可以对照方法学)。
编程范式提供了(同时决定了)程序员对程序执行的看法。

常见的编程范式有:

  • imperative programming(命令式编程)
  • functional programming(函数式编程)
  • logic programming(逻辑式编程)
  • object-oriented programming(面向对象编程)

F**k me on GitHub