My Idea of Project

1. My responsibility:

I will be an implantation team leader who has the duty not only to carry out the most important part of coding job of project, but also actively participate in the design stage to make sure the design is suitable for our capacity of coding team and the time limit of project. What’s more important is that a team leader should try all way to make every member of team to be actively involved in development. And co-ordinate the relations between members and relations between coding team and design, specification team. I should discover the capacity of each member of coding team and try to make good use of it. Besides that I need to use my experience to foresee all possible problem in each implementation phases. For example, at this starting stage I need to enlighten members to be not too ambitious to develop a complicated game with perfect ideal operations which is very common problem for less-experienced programmers who underestimate the difficulty simply because they never have the developing experience. On the other hand, I should always try not to discourage them too much because the motivation for developing an interesting game is sometimes more important than their coding ability and experiences.

I will need fully support from design and specification team who will clarify the idea and procedure of game and give out detailed blueprint of project. However, when I study carefully of their design, it will be surely for me to have various questions to feed back to them. And their modification or explanations will lead to more mature idea of development. I need to share these idea entirely with my coding team. During developing, the coding team will have various problems. Some of them may be technical ones which I am supposed to give technical support. Some of them may be related with specifications and designs. These questions need my validation and communication with design, specification team.

I also need to fully control the progress of development to ensure our project delivery in time. And check from time to time the quality of coding even we will surely have a member specialized in testing. Because the combination of codes from different programmer will involve complicated debugging technique which is by all means to be my duty.

2. The technique we will use::

1) Uniformed coding styles: In order to ease job of combination of source code from different programmer, it is preferably to set up standard coding style from very first beginning, such as naming of variables, constants, classes. Position of curly brackets etc.

2) Purely object-oriented programming: Try to make all closely related functions to become a class. Make sure all repeated code to become a function, because forgetting updating “copy-paste” code is one of biggest resource of bugs. In order to avoid different team coding similar functions, try to assign closely-related functionality job to sub-teams.

3) Another way to avoid repeating coding is to use inheritance in C++. i.e. Both letters and cards need to have a display method and the method is much similar. Then make letter class and card class both inherited from same base class, say token class which implements the display method. Therefore, whenever find out some common functionality in both card and letter class, place it into base class token.

4) In order to prevent global variable be accidentally modified, make sure all global variable become only available by method instead of direct access. It will also be easier for adding extra “validating” method when setting or “constraint” method when getting.

5) Version control: In order to avoid chaos in versions, each member should periodically backup. The total combination version of each team member should also be backed up whenever debugging finished. Since we are not using any version control tools like “cvs”, “source safe”, it will need the team leader to keep backing up combination version individually. I have setup a free news group in “Yahoo Group” which supplies free service of news group---for group communication, web storage----for uploading maximum 20M files for version control.

3. The development model we will use:

I will suggest that our team apply “incremental model” which builds one bigger build based on previous build. For example, we will try first build a “naked” game displaying program for purely displaying boards, rackets, score bars etc. After this, we will build a simple “scrabble” game which will use the displaying module. Then add a “rummy” game into project. Then develop the score-calculating system and combine both “scrabble” and “rummy”. Finally if time permits, we may upgrade our text-mode display interface to a graphic interface. Therefore, at each stage we will clearly see the result. It not only ease the job of debugging, but also the team members will see our progresses and have more interest and confidence in further development.

4. Possible technique will be used in graphic interface:

1) We will probably use different language to develop graphic input-output interface, such as Delphi, VB, Java etc.

2) The graphic interface is involving as less programming control part as possible because we need to finish all our control code in c++. Therefore the front end is purely a dummy program for purely transfer users' input and display the calculated result from back-end.

3) All program written in C++ will be made a "DLL" (dynamic linking library) with all public methods to be exported in "dll".

4) The game control algorithm must reside within C++ DLL.

5) The following is a simple demo of how to call DLL from C++.

a) To make a dll in c++:

First choose "new" from Visual C++, choose the project of "win32 dynamic library". Compile by press "F7".

file name: dlltest.cpp

extern "C" __declspec(dllexport) int ADDNUM(int num1, int num2);

int ADDNUM(int num1, int num2)
{
return num1+num2;
}

b) To make a call in other program in c++:

setup a project and copy the compiled file from a) into directory of your setup work space (folder that contain your source file). Compile the following

program and run it.

    #include <iostream>
    #include <windows.h>

    //extern "C" __declspec( dllexport ) int ADDNUM(int num1, int num2);

    using namespace std;

    typedef int (*MyProc)(int, int);

    MyProc fun;

    int main()
    {
    	int num1=5, num2=10;
    	HINSTANCE handle;
    	handle = LoadLibrary("dlltest.dll");
    	if (handle!=NULL)
    	{
    		fun = (MyProc)GetProcAddress(handle, "ADDNUM");
    		if (fun!=NULL)
    		{
    			cout<<fun(num1, num2)<<endl;
    		}
    	}
    	FreeLibrary(handle);
    	return 0;
    }

God Speed Us...

    From:  "nickhuang99" <nickhuang99@hotmail.com>
    Date:  Tue Mar 16, 2004  2:41 am
    Subject:  To: All programmers

    Hi all,

    1. I think we MUST finish our project this week or we may have no
    time for thorough testing. So, everyone must speed up now!
    2. Charles: Can you finish your scoreboard by friday?
    3. David: Can you set up all message showing mechnism at "working
    area"? If you like, you can use my simple "background" class to make
    the message-displaying area looks better.
    4. Mr. Liu and Zhang Hong An: have you started testing of all visual
    components? How about the the DFA control diagram?
    5. My plan is by end of this week, our game can run, at least for
    some functions of game-playing.

    have a nice day,

    nick

    Working Schedule

    From:  "hotmail" <nickhuang99@hotmail.com>
    Date:  Thu Mar 18, 2004  4:08 am
    Subject:  To:About working schedule

    Hi all,

The following is my plan for working schedule in this week:

1. Charles: I suggest you write the frame to be a "CFrame" class because David can also use it for message showing. As for the layout job, I think Mr. ZhangHongAn can do it, so, you just concentrate on your scoreboard and frame class.

2. Mr. Zhang Hong An: try to position all components to a better way and write down all those coordinates. Don't forget there is scoreboard from Charles and message from David.

3. David: Please organize all "prompting messages" and make all them to be an array with some meaning index. i.e. enum values( see the rovertype.h).

4. Mr. LiuXiangqun: continue testing and don't forget the color questions, save all your tests and prepare to demo them at end of this week during meeting. We need to vote for colors.

5. Mr. HuQiHui: concentrate on the report, we all rely on you! And I am sure you will not be short of real bug reports. :)

6. Angel and all design team, and all programmers: I suggest we meet at weekend:

a) evaluate the our program demo.

b) discuss what to improve and possibly decide some game rule changes.

c) Any suggestion of better game start and end graphic idea?

d) decide all color combination of all visual parts.

....

see you all tomorrow,

Nick Huang/Qingzhe Huang

Bug Report

    From:  "nickhuang99" <nickhuang99@hotmail.com>
    Date:  Thu Mar 18, 2004  1:15 pm
    Subject:  Re: bug report

    Hi all,

    Usually in software company they have a format to report bugs. So,
    let's do it this way:
    1. I create a folder named "BugReport" in our "yahoogroup". So,
    whoever find a bug just post his report under that folder.
    Preferably each one create a subfolder to contain his report file.
    The folder name can be date or simply serial no., say bug001.
    bug002...

    2. The format of bug report must contain following:
    a) The name who find it.
    b) Category of bug: such as logical, display error, calculation
    error, or serious bug like crashed.
    c) Description of bug: Under what circumstance the bug appears.
    Should include a senario description. Sometimes a picture is the
    best to do this job. So, usually you need to make a bug-picture.
    d) Bug picture: To make a bug picture, when the bug happens,
    press "print screen" key on your keyboard. (it ususally locates at
    upper-right of your keyboard with abbreviation like "prt sc" or
    something".) Open your windows "paint" from your "accessories".
    Click "paste" from menu then you got the screen snapshot on
    your "paint". You can even draw some marks on the picture by
    choosing tools in "paint". Save the picture as "jpeg" format instead
    of "bmp". And name it properly then upload to your bug report folder.

    3. Mr. HuQiHui: I think maybe the third report does need some "bug
    report". If yes, why don't you design some "word template" and
    upload the template to group so that everyone can download?

    4. Angel: can you do a demo of report by reporting the bug you find
    while forming word?

    have a nice day,

    nick

    About Game Playing

From: "hotmail" <nickhuang99@hotmail.com>

Date: Thu Mar 18, 2004 11:17 am

Subject: Re: [comp-354] Re: about play game

to form a word, you need to select letters first and then press "form word", then you are asked to input x, y and direction . Key in x and y required to press enter, and direction means "v" or "h". Tell me how you do it to make program crash.

Nick Huang/Qingzhe Huang

From: "hotmail" <nickhuang99@hotmail.com>

Date: Thu Mar 18, 2004 3:56 am

Subject: Re: about play game

hi,

1. The idea of game playing is that you have to choose an action once a

time, or menu. For example, if you want to choose index of letter rack of

3, 5, 6, you have to press menu3(select letter) 3 times and after each time

you press 3, you enter the index:

The sequence of entered: 3(this for menu) 3 (for index 3) 3 (menu)

5(index) 3(menu) 6(index).

2. It is a good question! Do we allow player to form words more than once

during one round? (Angel, what do you think?) And the placed words on board

can be removed by choosing menu "cancel".

3. see no. 1

4. I will try to see if it is possible to use function key. but first I

need to rush to finish algorith.

have nice day,

Nick Huang/Qingzhe Huang

Concordia University

Department of Computer Science

# Individual Project Report

COMP 354 --- Software Engineering I

NAME : | Qingzhe huang
STUDENT ID : | 5037735

General instructions and information:

· You must use this template to submit this assignment.

· All your discussions must relate to software process aspects, e.g. the different phases of the project, the use of templates, project management, etc.

· This is not an open whining session on your team mates, the course, or the project. I want to know what you have learned from the experience of this project from the perspective of applying a software process.

· All your answers must explicitly refer to your experience in this project.

· This is an individual report. Plagiarism will not be tolerated.

· Clarity of answers will be graded.

· Provide a clearly different answer in each box.

· Answers specifically realted to document templates must be discussed in section III.

Grades distribution

###### Section

###### Grading

###### I. Positive aspects of applying a software process

###### 40%

###### II. Negative aspects of the software process we used in the project

###### 30%

###### III. Positive and negative aspects of using document templates

###### 30%

###### Total

###### 100%

######

I. Positive aspects of applying a software process [40 points]

Based on your experience in this project, give two definite advantages of using a software process. Explain your answer.

1． Planning more helps more.

This is not a trivial programming assignment and it is quite a project. You see the final program includes 20 classes, roughly 3000 lines of code. So, I would say the implementation really benefits from detailed planning. At the requirement stage, we thoroughly discussed every aspect of game and had a rather vivid view of whole game. It surely provides a lot of help for following design phase because our whole team had been familiar with the game running and had a common view of the game. During design phase, I strongly urged all programmers to join the discussion of design even it was the job of design group. It not only gave a more specific idea how it should work, but also I have to think for each functionality how it should be done. This proved to be really helpful. As leader of implementation, I could add my opinion into design so that some unimportant or too-difficult functionalities had been adjusted. What’s more, their analysis gave me a more specific view of each part of game. It finally helped me to design all visual components in an hierarchical way, combined with object-oriented style. I realized that since we were going to program in a “console” we can put all display-related details into the smallest unit----tile, which is actually one character. Then all other components would use this atomic unit as building blocks. It also eased frustration of other programmers as they are not familiar with windows API’s. During building program, we used many inheritance and composition idea to try not to write too much code within one single class so that not only cooperation between programmers but also maintenance in future would become easier. By careful design, I had a clear view of all parts of game. It help me to decide the functionalities to be implemented within each class. This effort reduced coupling between classes and made our programming team possible to do on a contract basis, or interface-basis.

All in one word, without preparation of requirement and design phase, implementation would be able to go such smoothly.

2. Design not only guide implementation but also contribute to part of coding It maybe trivial to other people but I do think it is one of positive part of design. As I mentioned in above design did give me a clear and specific view of game and helped me to decide which functionality should be implemented in which class. Besides this the design group also physically helped implementation by writing down those basic function prototypes and named all interfaces of each class. This is actually a part of coding! For some programmers naming classes and functions is a fun, but for others it maybe a headache. Sometimes I am the second kind of people. More over the design group had provided all those game data’s. For example, each letter has a point value to be associated. This table of points is directly borrowed into my code. Another example is that all system messages is based on design and all these routine job was already done by design group. It more or less released me from those headaches of typing. So, in my point of view good design is integrally a part of implementation.

II. Negative aspects of the software process we used in the project [30 points]

Explain how you think this project should have been managed in a more efficient and effective manner by using a different software engineering approach, either by having a different overall process approach, or a different approach in a particular phase of the project. Give two different improvements. Note that your propositions must still fall under proper software engineering, e.g. « we should not have used a process at all » is not an acceptable answer.

1. The earlier we reach implementation, the better we can make it!

In my point of view, all documents have only two solely purpose in software engineering process: a) to help better understanding and eventually to help implementation; b) to help possible future maintenance.

But during our game project, there are just too many useless documents. Or at least I consider them to be low efficiency. We wasted a lot of time to produce some useless documents when we were still not clear about our project. During the implementation phase there are so many changes that nobody would ever bother to update those documents! Then the documents lost their purpose of existence! Why should we spend so much time on them if they are not quite useful or so easily to be modified?

So, in my opinion, instead of spending so much time staying at stage of requirement and design, it is preferable for programmers to quickly jump to the stage of implementation and get some immediate feedback to design group. This situation is exactly described as drawback of waterfall model. However, even we understand this in lecture, we still make the same mistake in action. My experience in this project tells me that the earlier the implementation feedback we get, the less useless requirement and design job we would waste on. If I was given one chance to re-do this project, I would ask all my team to quickly program some basic frame work or prototype of game to let us have some idea of how many hours we may take to finish one single functionality. Then we would be naïve to waste our energy on designing impractical options which turns out to be greatly time-consuming and beyond our capability.

2. Success due to heroic efforts is a disaster to a team

I was particular touched by this sentence when professor gave lecture on CMM. The programming power of our team is in great variance and this prevents me from implementing many requirements. And consequently I had to reduce many features of game in view of slow progress in coding. Playing hero is a pride of a person but a failure of a team. So, I am not sure if my claim to have done the 95% of coding alone is a showing off of personal programming ability or a proof of failed leadership.

Software engineering resembles a lot in organization management. Resources should be used more properly. If I was given another chance to re-do this project, I may carefully choose my partner. It is not the reason that I don’t like to co-operate with them. On the contrary, they are all my best friends and we really enjoyed working with each other. The only problem is that many of them are lack of basic experience, even though it is the purpose of this course to expose to them. However, from pure software engineering perspective, a good composition of team is sometimes the only guarantee of success of a project. Appropriate allocation of various resources of software engineering is the best lesson I learned in this project.

III. Positive and negative aspects of using document templates [20 points]

Based on your experience in this project, explain the advantages of using document templates. Explain your answer.

Document template is actually a guide of action. It is something like what is said in lecture of CMM level 3. All procedures in software engineering have been formulated by a series of documents. These document templates reflect the previous experience of others. It surely reduces our efforts to figure out what should be done and how should be done. The contents force us to think and understand the whole process of software engineering.

Based on your experience in this project, explain the potential problems related to the use of document templates. Explain your answer.

The documents are too many! We spent more time in writing than coding! And many of documents are so easily becoming useless when implementation changes requirements. And documents without updating is in my opinion a garbage because it is quite often misleading!

The purpose of document is two: a) to help understanding and eventually all to help implementation. Otherwise we are not programming but publishing documents! b) to help future maintenance.

However, it seems that our documentation failed in both two aspects! First of all, I admit requirement and design phase did help us understand the problem. But nevertheless too much documents were written when we still had little idea about what we should do. The contents of many documents were either empty or impractical. In my opinion, if we use these documentation time more wisely, we should try to implement for a while and come back to write some documents. Then we may do better by acquire more specific idea of what we can do and cannot do. Second, as I said documents without updating is not only useless but quite often harmful because of misleading. There are so many changes in our implementation and soon we don’t bother to update those changes in documents especially programmers are coding in a short of time manner. Then what is purpose to give wrong information to those possible maintenance programmers?

Dependency

I spent almost one whole day to re-check our dependency because I believe our project cannot compete with other groups either in splendid graphic interface or in data constraint functions. The only thing we can make sure and we must make sure is the database design is in 3rd normal form.
Among all dependency, the most tricky one is about the "schedule" which I try to assert as following. Please check if I am wrong or I missed anything:
1. The schedule conceptually involved following 5 abstract objects:
employee, car, order, servicetype, date&time.
2. I observed that date and time is rather one object because we never use them separately. Do you agree? And service type in short is "type".
3. The following is my assertion:
a) For any employee in a particular datetime, he can only do one type of service, for a specific car, under a specific order.
That is :
employee+datetime -> car, order, type;
b) For any particular car at any particular datetime, it must be under a specific order, if it is repaired by one or more employee.
That is:
car+ datetime -> order;
c) For any car which is under a specific order for a specific type of service, it must be done by a specific employee at a specific datetime. That is:
car + type + order -> employee, datetime;
4. These are all dependencies I discovered for these particular objects. I changed my program a little bit and the result is worth observing:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
decomposition #1:{employee_sin,car_plate_number,service_type,service_time,service_date}
dependency is:
employee_sin service_time service_date -> car_plate_number service_type ;
decomposition #2:{car_plate_number,service_time,service_date,order_id}
dependency is:
car_plate_number service_time service_date -> order_id ;
decomposition #3:{employee_sin,car_plate_number,service_type,service_time,service_date,order_id}
dependency is:
employee_sin service_time service_date -> car_plate_number service_type ;
car_plate_number service_time service_date -> order_id ;
car_plate_number service_type order_id -> employee_sin service_time service_date ;
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
From above I observed that we made a serious mistakes: The primary key should be only "car_plate_number service_type order_id". In our database, I include employee_sin as part of primary key which will lead to a situation that "for a particular order which has only one car with "oil change" service type, our SUPERMAN employee brothers "Khalid" and "Jabobo" tried to repair it at two different date time---June 11, 5:00PM and June11 3:00PM". This is because our key include "employee". So, we allow two employee to repair same car with same problem under same order as long as they repair it at different time or date.
The second point I observed is that our database is 3NF instead of BCNF. You see, "car_plate_number service_time service_date -> order_id ;" is BCNF violation but it fits 3NF because our candidate key is {employee_sin service_time service_date} and {car_plate_number service_type order_id}. The LHS of 2nd dependency "car_plate_number service_time service_date" is not a superkey, but the RHS "order_id" is prime member of key.
To: Jean, I hope you can include above argument into our report which I think the tutor will concentrate on Dependency and 3NF.
So, I will modify our table structure again and insert data automatically.
Speed up!
nick

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

The link for downloading the dependency tool program, input file and result.

triggers

I add a new trigger for our replacement of employee. The policy is like this:
1. Actaully we DON'T DELETE an employee, instead we set its quit date to current date.
2. If we DO allow manager to delete the employee, then all data related to that employee will be automatically deleted.
3. When the Quit_date of employee is reset, all the schedules related to that employee will be modified ONLY IF the service date is AFTER his quit date. I do this with "trigger6".
4. I tested this function as following example script:
insert into employee values (678912345, 'nick', 'monk'
, '514-762-9189', '05-may-04', 2,'31-may-04');
insert into schedule
values(678912345,'62KH88',2,0,'13-may-04',992);
select * from schedule where employee_sin=678912345 and
service_date='13-may-04';
--delete from employee where employee_sin=678912345;
update employee set quit_date='10-may-04' where
employee_sin=678912345;
select * from employee where employee_sin=678912345;
select * from schedule where employee_sin=678912345 and
service_date='13-may-04';
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
a) inserting a new employee to test.
b) insert a new schedule record into schedule.
c) update his quit date to BEFORE the schedule date.
d) You can observe that schedule record is gone after quit_date is modified.
e) The following is the running result:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
SQL> @test
1 row created.
1 row created.
EMPLOYEE_SIN CAR_PL SERVICE_TYPE SERVICE_TIME SERVICE_D ORDER_ID
------------ ------ ------------ ------------ --------- ----------
678912345 62KH88 2 0 13-MAY-04 992
1 row updated.
EMPLOYEE_SIN EMPLOYEE_NAME EMPLOYEE_ADDRESS EMPLOYEE_PHO EMPLOYEE_ E
------------ --------------- -------------------- ------------ --------- -
QUIT_DATE
---------
678912345 nick monk 514-762-9189 05-MAY-04 2
10-MAY-04
no rows selected
SQL>
++++++++++++++++++++++++++++++++++++++++++++++++++++
Jean: I think this is a good example to be included in our report.
Vincent: I did try very hard to protect employee's benefit by creating triggers to PREVENT them from firing. But I failed. :-)
see you,
BTW, I changed the triggers' output to give some meaningful information when exception happens. Try to see if you like the message.
Nick Huang/Qingzhe Huang

Our Assumption

1. We assume that our schedule is always fulfilled unless it is cancelled by customer.
2. We assume that when an employee is deleted, it means all data related with him is no long needed. They will all be removed by "foreign key" constraint at "on delete cascade".
3. We assume that when an employee quits, all his job after his quit date will be removed and this is done by a trigger. It will delete only those schedules after his quit date.
4. We assume that when searching for two earliest available time slots, the earliest two available time slots may be at same time, but with different employee. so, customer may choose the time slots according to worker's employee type class.
5. We assume that when searching for two earliest available time slots, the searching will only trace the current day and two following day.
6. We assume that any employee can quit at any working day and the salary must be calculated immediately. The working salary is calculated on working days. The wage for white collar employee is for two weeks and for blue collars is for one week.
7. We assume that customer can split his payment and the payment method for each splitted part should be different.
8. We assume that when order_id and payment_id is not specified, the system will automatically assign a maximum number for inserted order or payment.
9. We assume that when payment_amount is not specified, the customer intends to pay full order amount. It is done by a trigger.
10. We assume that when customer licence in service order is updated, this implies that user are trying to correcting a mistake in customer licence. We update both customer and car table. A new customer is inserted into customer table and old one is deleted. The customer licence in car table is modified accordingly. This is done by a trigger.
11. For all function dependency, we try to implenment it by either constraint or triggers.
For example, in table schedule there are three distinct unreducable dependency:
a) For each employee, at any certain date and time, he can only work on a certain car which is under a certain order.
employee_sin, service_date, service_time -> service_type, car_plate_number
b) For any service type scheduled on any car which is under a certain order will always be carried by a certain worker at a certain date, and time.
service_type, car_plate_number, order_id -> employee_sin, service_date, service_time.
c) For any car at any certain date and time under repairing, it must be under a specific order, though may be under repairing by many workers on different problem at same time.
car_plate_number, service_date, service_time -> order_id.
Observing: a) and b) are both keys. One of them, say a, is implemented as a primary key. And b is constraint by unique constraint. For c) there is no obvious way except trigger.
And c) is a violation of BCNF format, but it follows 3nf: The LHS is not key and RHK is part of key.
12. The payment amount in table payment is the face value of tuition.
Nick Huang/Qingzhe Huang

有朋自远方来，不亦乐乎？

`类C编译器是用PCYacc做的，DSP汇编译器是用BISON做的。因为生成的代码实现递归调用太难了，所以一直想手工实现。
当然，词法部分用ＤＦＡ，语法分析用递归预测分析（表达式例外），从空间占用和运行时间考虑，这样可行吗？还有在表达式分析时用算符优先分析，可是对负号怎么处理比较好呢？还有"/"，有时作选项用，有时作除号用，能实现吗？
我刚看过你的scanner，不知为什么不用状态表来实现呢？如果代码这样做，直接函数调用而无须函数指针数组也可以呀？当然，理解上，就是在函数中实现状态转移了。
结合scanner和parser是很好的，如果时间不够而且愿意，我想可以我可以试下，可以吗？
我认为，LL(1）算法还是比较好的，利于语义处理，时空比也因该比LR(1)强一些吧。当然，在文法定义上，后者稍占优势。
请版主指点。
`

hi,
首先非常高兴接到你的mail，我非常高兴又一个同好可以商讨我喜爱的compiler的问题，得一个知己同好真不容易啊。我叫黄清浙，厦门人，年龄应该比你痴长几岁，不过学计算机的时间未必比你久，我们就兄弟相称吧。
1。因为我在国内没有学过计算机，所有的知识几乎都来自于游戏，因此有很多名词和这里的英文名词不一定对得上，请原谅。
2。我有一些问题不很明白：
a) 为什么你在语法分析的时候用“递归预测分析”（应该就是recursive-descent，我记得以前国内友人来信说的是“递归下降”，不知道是不是一样。）而表达式却用“算符优先分析”（应该就是operator precedence analysis吧？我不确定这就是英文的真正term，我记得我在学“系统软件”的时候，教授将编译器原理简单地提过这种方法，在我读“编译原理”的时候，教授没有提，我就专门去问过他，他向我解释了一点，我唯一听明白的就是这是一种比较古老的parsing的方法。）我不明白棋中的好处，我只能谈一谈我自己的想法。我做得PROJECT里算符优先是靠语法来实现的，比如乘法比加法优先级高，在语法就直接体现出来了，所以，不存在这个问题了。如下，乘除法会比加减法优先分析，我想你如果表达式都用同样的语法分析，应该是没有问题的。我对算符优先没有什么概念，只是猜想假如“减号”与“负号”应该有不同的优先级吧？事实上我想这里的优先级应该都是两两算符之间的相对优先级。不知道对不对。
。。。
M0 ==> + F M0 |e | - F M0
F ==> R M3
M3 ==> * R M3 | e | / R M3
。。。
b) yacc,bison我听说过没有用过，不是很明白，为什么递归调用很困难？难道生成的compiler不支持递归吗？
3。以下是我对你的问题的一些解释，首先声明有些问题我理解不是很确切，并且有些问题我自己也没有答案，我们可以互相切磋探讨。
a) 语法分析用递归下降是比较容易实现的，因为，手工写编译器，最大的困难都在代码生成部分，按照我们老师的说法，工作量90%是code generation。而recursive descent因为很大程度上是符合人的思维习惯，所以好实现一些。我觉得效率问题要看辩证地看，比如，如果因为要提高编译速度，就采用table-driven，但是代码实现部分耗费的精力太多在某些小工程上是得不偿失的，这一点我想你学了软件工程会理解得更深。我不知道你的编译器的应用是个人兴趣还是有具体的应用，因此，效率对不同的应用是有不同的内涵的。扯远了，抱歉。
b) 我在学compiler design的时候，是逐渐才明白很多问题的。（就像我们老师说的，只有自己写一个编译器才能真正理解编译原理。）在写scanner的时候，对于状态表还没有想得很明白，（我的语法阅读器是scanner之后慢慢开始自己摸索着写的，还没有听说过所谓yacc，bison这类compiler-compiler，后来才慢慢明白的。）
scanner用table-driven有着最高的效率，但是，建立这个table确实是很繁琐的，你看到我专门用一个initialize的模块去把表的空格一个个填满是不是很笨拙啊？
你所说的函数指针方法，指的是这个简单的scanner吗？http://staroceans.com/simpleScanner.htm
这种方法简洁明了，不过不论怎样你只要用到“函数”调用，从效率的角度来看就低了，因为，c里面的函数要先保存栈，在作function call，这些都是很昂贵的，而table-driven里的数组作用就是代替function call,因为函数就是你输入什么我就返回一个什么，表就是一个函数的等价的存储实体。
c) 把parser,scanner 结合是我的心愿，我一直没有开始是对这个工程没有信心，如果，你有兴趣，请大胆地尝试，我一定全力支持你。先谢谢了。
d) LL(1)最大的问题是你必须对语法做一些调整，而这是一个非常痛苦的事情，因为，compiler-compiler调整语法我不知道是否一定可以成功，因为，LL(1)的语法是有一定的限制的，这样就对用户自定义的语法有了一些约束，这是很头痛的事情，至少我当时是认为人力无法做到的。我记得当时我发现我的程序无论是先去处“left-recursive”然后再去除“common-left-factor”，或者反过来顺序，又一条语法始终没有正确，最后只有认为的那条语法的次序提前了，（我记得大概是这样。总之，你很难去检验用户定义的语法是否符合ll(1))。 而LR(1)不存才这个问题，至少你不需要把用户的语法改的面目全非。并且，我当时模模糊糊的猜想，LR(1)里面的状态一定对于“代码产生”有很大帮助。这也就是我一直想改造成LR(1)的原因，另外，我记得所有的compiler-compiler，如yacc,bison都是LR的，对吗？
如果，你有兴趣开始编译器的项目，我非常高兴，我们可以好好合作，共同切磋。
祝好
Nick Huang/Qingzhe Huang

compiler-talk

明友老弟， 你好！
我非常高兴你和我有着相似的理想---让计算机理解自然语言！我始终认为恩格斯所说的：“语言是思想的工具与产物”有着惊人的准确与深刻的内涵，所有的人工智能问题最终都必须解决语言问题，没有语言我们甚至无法和计算机有基本的交流。
我记日记也有迫不得已的地方，人的记忆力非常的有限，尤其我自认为从前的记忆力很好，现在感觉衰退就非常明显，同时，很多东西在纪录的过程就是一个自我验证的过程，有些疑问在整理成问题的过程中就自然力清头绪甚至解决了。像你刚才提到的scannerpro，我自己看了后很吃惊，因为，我自己印象中没有写过“表驱动”以外的scanner，当然，重新审视自己从前的代码，记忆也像链表一样一节一节慢慢找回来了：
1。 所谓预测分析，我不记得是不是我的教授说的，还是我自己想出来的：基本上计算机语言的编译器都是一种“可预测”的分析，只有自然语言的parser才是无法预测的，因为太多了。我想所谓“预测分析”这几个字的英文字是“predictive parsing”，对吧？国内应该是把parsing翻译成分析。
(写完上述文字，我又翻了一下课本，更正：top-down有两种parsing:backtracking, predictive。backtracking很少被使用，除了近年来被一些functional programming language,such as "haskell"所使用，而其他实际的算法基本上都可以称之为PREDICTIVE，因为，无论是recurrsive descent还是LL(1)你都是知道你在期待什么，所以是predictive。）
2。对于算符优先我没有学过，紧紧相谈一下我的想法，可能是错的，请原谅。我想算符除了优先级(precedence)，还有一个特性就是操作数(operand)，比如“!”就是只需要一个operand的operator，你的表达式“A－－B－Ｃ＝”至少有几个问题需要考虑：
a)负号是只带一个operand的算符，减号是两个operand的算符,你不能撇开operand仅仅把算符放进stack里面去分析，（我这时瞎猜）。
b)我模糊记得算符优先是包含了operand与operator之间的两两相对precedence。对于单一operand的operator对于双operand的operator来说，它对于operand的相对优先级要高于双operand的operator。不知道对不对？
c)还有一个话外题就是你应该没有c++里面的"--"，即双减操作符。
因此，如果负号对于operand "B"有较高的优先级的话，应该就不会有ambiguity？
3。yacc一直想去玩玩，可惜没有机会，听了让人很神往。
4。去处“left-recursive”还是先去除“common-left-factor”的问题，我同意你的看法，很有可能是语法中的问题，这一点，我的老师也提过，这正是LL(1)的致命弱点：因为，很难保证语法是正确的！所以，我的观点是尽量不要用LL(1),因为，对于复杂语法来说，编译器的设计很可能是正确与法的设计，在这方面花的时间可能是不值得，因为考虑到将来的语言是要发展的，（这是我的想象，计算机语言也要进步，比如Vc++就是从c进化来的，比如模板又是在c++基础上增加的，无论你当初的语法再怎么正确，后来添加的新语法很可能让你从前的工作化为乌有。）我个人对语法是比较敬畏的，当时在学自动机原理的时候，很多语法的作业想破了头，所以，我总是倾向于认为，人工调整语法是一件很费力的事情，好像有些证明题目，你需要逻辑推理以外的灵感，这是计算机所无法做到的，也就是不能自动化的一件工作，因此也就不是发展的方向。这是个人的理解了，仅供参考。
5。LR的确是靠了牺牲时间与空间来换取对语法的宽松，不过，考虑到将来要解决的问题很有可能不是严格的计算机语言，这种牺牲是值得的，比如自然语言的parser听说就是用LR(k)来解决的，我想这是唯一的途径吧。
6。startComment,endComment是否可以合并，我从直觉上看是不可以的，这两个状态时有区别的，前者准备接受除去comment结束标志以外的任何字符，后者则是有些像回到了ready的状态。总的来说，我的做法就是先画出DFA，然后尽可能化简他，然后就是简单地照着图来实现了，所以，要合并只能在DFA阶段就做了，很可惜，我当时没有把DFA扫描下来，不然可以准确地解释给你。至于checkChar的应用，我不太明白你的问题。我印象中这个函数，是把很多的字符进行分组，以便简化代码，在我后来的table-driven版本里也有类似的做法：比如256个字符中，有很多字符分成一个组，如所有不可见的ASCII字符，如1，2，3。。。都是一种字符，这样你的表就小多了，不用直接使用一个256x?的表，当然这里的“？”代表状态，所以，我才说我的table-drive是一个32x78的表，其中32就是32种不同字符。因此，这个checkChar仅仅是过滤了一下字符，并没有更多的用途。
7。词法的语法原则上说和文法分析的语法没有区别，都可以用context-free-grammar或者EBNF,BNF来表示，这个也正是我的遗憾，因为我写CFG-reader是在作scanner之后，否则，也许可以当时就把scanner自动产生。（不过，这不是真实的，因为，我想我是不可能在两个星期里完成的，所以，这是自欺欺人的说法。：））因为，词法可以是regular expression,所以，是可以用DFA实现的。因为，DFA与regular expression是一一对应的，所以，实际上你并没有绝对的必要一定要写出语法，除非你画DFA喜欢从语法开始，但是对于lex之类的scanner-generator来说却是绝对必要的。这就是我的理解。
8。没有关系，你尽管放手去做，我想这个工作是要花很多时间的，至少我现在是有一点点胆怯开始他，你的行动也许对我是一种鼓励。你打算怎样维护版本？
祝好。
Nick Huang/Qingzhe Huang
我的征尘是星辰大海。。。(Chinese)
http://www.staroceans.com/
The dirt and dust from my pilgrimage become oceans of stars...(English)
http://www.staroceans.com/english.htm
----- Original Message -----
From: "mylee" <lemyu@163.net>
To: <nickhuang99@staroceans.com>
Sent: Wednesday, July 28, 2004 12:27 AM
Subject: Re: 你好，我叫黄清浙

> 　　黄兄你好！非常高兴你将我引为知己同好，诚如你所说，我对编译甚至于计算语言学都非常感兴趣，希望自己能看到自然语言被计算机理解的那一天，说远了。
> 　　如果觉得有利，我同意将通信整理后贴在网页上，只是有些想法比较仓促，远远不够成熟，黄兄见笑了。
> 　　非常佩服你的认真，想自己工作也有四年了，可是由于很少写日记，加上前两年做的又是数据库系统，学校里接受的知识大多还给老师了，所以积累知识有限，如有些地方不妥，望黄史指正。针对你的疑问，我的看法是这样的：
> 　　一、关于有些术语可能由于中英译文问题，有些走样，以后我尽力将相关英语也写出来，这样也许会好些。你说的很对，“算符优先分析”就是operator precedence analysis的意思，而“递归预测分析”在我手中的编译书籍上称呼是“预测分析”，不过我觉得它既然是递归下降（recursive-descent）的改进——利用First set 与 Follow set预先读取一个字符或Token结合当前规则进行分析，就私自加上了“递归”。
> 二、之所以在分析表达式时利用算符优先分析，是因为它相对而言容易实现而且直观。方法就是你说的那样，利用两两算符之间的优先等级进行分析。“减号”与“负号”会有不同的优先级，不过在“A－－B－Ｃ＝"的情况下，可能会出现岐义吧。另外一个疑惑我已知道答案了，就是利用关键字可识别不同情况下的“／”。
> 　　三、因为用YACC或其它工具生成的代码全局变量和静态变量太多，而且由于考虑不同操作系统下的编译用了太多的宏，所以阅读起来麻烦，修改代码比较困难。当然，完全可以写自己的主驱动代码。
> 　　四、同意黄兄你的看法，用表驱动（table-driven）是为了提高编译速度，我提出来只是想和你讨论另一种方法而已，没其它意思。而且你的这种实现方法也是很好的，因为利用状态表会影响代码的阅读理解，如果不考虑这层因素那完全可以在一个函数里去实现了（平衡函数调用开销与阅读理解）。
> 　　五、至于先去处“left-recursive”还是先去除“common-left-factor”都会遇到问题，我想会不会是你的文法定义中出现了一个大的回路，这种情况在现在的程序语言的文法定义中还是很少见的，如果是这样现在已经有了解决此问题的算法，不过可能比较难找（我也只知道有这种算法，可是名称和出处就不知道了，报歉）。
> 　　六、YACC及其变种只是至顶向下分析（ＬＬ）的一种应用，LLgen及其它则是至底向上（ＬＲ）的应用，当然还有很多。我所以看好至顶向下分析，是因为文法中出现的问题可以手工消除，而且ＬＲ能解决文法中的左递归、和共公因子也是有牺牲时空比的代价的。
> 　　我所做的两种编译器是针对项目的。
> 　　看过ScannerPro，我想对于字符跳转是可以直接转移状态的，所以是否可以合并ＳtartComment、EndComment？还有CheckChar在其它-Check函数里还没有充利用，不知是不是？另外，词法扫描的文法定义是怎样的，用于什么场合，我也很想知道。
> 　　因为最近电脑刚被借走，我只有利用（周一至周五）晚上的时间来做词法分析和语法分析的结合，所以时间可能比较慢。黄兄得有心理准备啊，呵呵！
>
>
>

S/R, R/R conflict

> 　　时间过得好快。
> 　　其实，YACC作为自动化生成工具，确实有很多值得为人称道的地方。可惜对它本
身的代码我试过想去读懂却一直没有做到，也许是自己太懒——下的功夫还不够吧，
Sign！如果纯属使用它，那也太简单了，还没有WORD复杂呢，真的。
> 　　近来对ＦＰＬ产生了兴趣，在学习HASKELL语言，对其中的Monads和闭包
(closure)很不明白，若黄兄清楚，还望指点迷津！
> 　　和黄兄通的交流，使我感到自己对编译理论欠缺很多，看来得下功夫恶补了。算
符优先分析在以前学Ｃ语言时接触过表达式分析，可是现在对这种算法竟没有多少印象
！
> 　　至于ＬＬ与ＬＲ，黄兄分析得很清楚了，但是我在用ＬＲ时，也经常遇到Ｓ／Ｓ
与Ｓ／Ｒ冲突，不知ＬＬ在解决左递归与公共因子后会不会出现类似的问题？
> 　　版本维护我用的是SourceSafe，ＣＶＳ还玩不转。

hi,
Yacc尽管使用起来如你所说的简单，我还是从来没有用过，哈哈。我比你还懒呢。我不知道他是否有源代码？
Haskell我只是在一门课里学了一个月，学的实在是稀里糊涂，因为那门课的目的是介绍计算机语言的一些principle，并不是以学习某种语言本身为目的，所以接触的成分比较多，我只是模糊记得有Monads和closure的概念名字，好像是类似于LIsp里面一样的一种所谓环境吧？比如，lisp里面外界加入的对象是一个动态的list，有先后顺序。抱歉，我实在是不记得了，胡说两句。
LR我实际上仅仅开了个头，只是把语法中的handle分成了一个个的小的集合来表示，还没有到达栈的阶段就停下来了，因为当时demo的时间要到了。关于s/s,s/r的冲突，我想你说的是不是shift-reduce(s/r)和reduce-reduce(r/r)？对于LR(0), SLR(1),LALR(k)我想这个问题是始终有可能发生的，原因就是我们计算机语言的parser就是一个可以预测的parser，他总是要找到唯一性--deterministic，即便不是DFA的问题，也要如处理DFA那样没有ambiguity。那么，s/r,r/r分别遇到的就是LR类的parser得两个最基本的operation: shift还是reduce?因为这一类的parser有另一个名字:shift-reduce parser.所谓的s/r,r/r就是在这两个基本动作上的amibiguity。语言的ambiguity始终是存在于自然语言的，计算机语言是人为创造的，我们为了我们的parser没有conflict，我们可以人为的修改语法以便消除s/r,r/r。当然，我们也可以采用更加强大的parsing algorithm，比如SLR(1)就是在LR(0)基础上加上了一个token得lookahead以便检查first,follow set莱为parser提供一些reduce,shift的线索来消除ambiguity，但是，单单一个token德lookahead还不是能够总是消除ambiguity，那么，就在SLR(1）德follow,first set基础上找出一些更小得更确切的子集，这就是YACC的做法，LALR(1)。核心还是用一个lookahead token来多提供一些究竟是shift还是reduce的信息。（我这样讲是很泛泛的，但是我认为这就是核心，我喜欢简单，不然我记不住。）
实际上，LL和LR是很不一样的想法，简单地说，LL是一种人为地要求语法一定要符合没有“左递归与公共因子”，这个条件本身既是很苛刻，一旦满足，就没有任何问题啦。问题是要满足的话，你必须手动修改语法，这也是我非常讨厌的，往往把语法改的面目全非，我想这也是为什么LL一般用于语法较简单的语言，如pascal之类。
以上都是自己的一点体会不一定对，如有不同看法，还望一定指出。
你是否开始scanner,parser的整合工作了？
你现在研究这个纯粹是业余时间吗？
我对于这个领域的研究动态没有概念，感觉是说好像很成熟的样子，不知道国内这方面发展方向如何？
其实，我自己sourceSafe是前几天才看看了而已，尝试着用了用，我写的都是小东西居多，个人用sourceSafe的理由也不是很明显，以前在软件公司带过半年，稀里糊涂地用CVS，觉得挺好用的，但是一点都不明白怎么回事。哈哈。不知道CVS能不能架设在我的这个小网站上供大家团体共享代码的时候用？sourceSafe可以网络用吗？
Nick Huang/Qingzhe Huang

算法是可以“设计”的，至少是可以“猜”出来的

比如我们都知道n个元素全排列的个数是n!=nx(n-1)x(n-2)x...2x1，那么这个数列乘积是不是告诉我们迪归的时候每个迪归方程的作的“工作”？假如我们用最简单的“size”来迪归，每次减一个，那么递归方程的参数就是size，这个大家都很好理解，关键是我要做的工作或者说当前这个level我要产生的排列数也应该是这个数目，所以，我就应该寻找一个size=k where k=n, n-1, n-2, ... 2,1这样的排列发生方法。非常naive地，我们知道我可以任意选择这k个元素中的一个，不妨就是第一个，让他与所有k个元素交换一下位置，这样会产生k个不同的结果，（记得他和她自己交换位置也算一次。）这样，我们就设计出了一个全排列的算法（如下）。由此推广，假如我们知道某种结果的个数是一系列的等差数列的乘积（或者是某种有规律的数列的乘积）也许我们可以用递归的方式设计出一种算法，当然我想算法是一种操作所固有的，所谓“造物本天成，妙手偶得之”，谈不上“设计”，但是，至少帮助我们发现她吧？God, enlighten me!

    #include <stdio.h>
    #include <stdlib.h>

    const int ArraySize=4;
    char buffer[ArraySize+1];
    int counter=0;

    void permutation(int start);
    void swap(int i, int j);
    void initialize();

    int main()
    {
    	initialize();
    	//printf("%s\n", buffer);
    	permutation(0);
    	return 0;
    }

    void initialize()
    {
    	for (int i=0; i<ArraySize; i++)
    	{
    		buffer[i]='0'+i;
    	}
    	buffer[ArraySize]='\0';
    }

    void swap(int i, int j)
    {
    	char temp;
    	temp=buffer[i];
    	buffer[i]=buffer[j];
    	buffer[j]=temp;
    }

    void permutation(int start)
    {
    	if (start==ArraySize-1)
    	{
    		printf("%d:%s\n", ++counter, buffer);
    	}
    	for (int i=start; i<ArraySize; i++)
    	{
    		swap(start, i);
    		permutation(start+1);
    		swap(start, i);
    	}
    }

    1:0123
    2:0132
    3:0213
    4:0231
    5:0321
    6:0312
    7:1023
    8:1032
    9:1203
    10:1230
    11:1320
    12:1302
    13:2103
    14:2130
    15:2013
    16:2031
    17:2301
    18:2310
    19:3120
    20:3102
    21:3210
    22:3201
    23:3021
    24:3012
    Press any key to continue

    			吃饱了撑得了

非常感谢你收集的资料。
看到那些定理的名字我是有些印象学过，可是我整个大学生涯可以说除了扑克牌，下棋，等等什么都没有学到。（事实上，打牌下棋也没有学好。实在是虚度了光阴。）
也许是现在有时间去问个为什么，从前学这些东西纯无兴趣，脑子里问号太多，也没有机会去问，因为国内的教学体制，学生上课不鼓励问问题，大家都是一个班级的，总有人要笑话你问的问题愚蠢，这实在是一个灾难。这里的一个好处就是宣布“没有愚蠢的问题”。学生鼓励问问题，鼓励纠正老师的非常微小的错误，教授是真心诚意地说谢谢，当你指出它的非常简单易见的小错误，学生与老师的关系不是垂直的灌输，师道尊严不是靠伪善的遮羞布掩盖人的普遍的软点，即便圣贤亦有过错，本身中华文化传统里“崇古”的思想本身就是对科学思想发展的滞箍，每当我想起这些，我就禁不住要对中华文化传统作再一次的否定。
非常可惜的是在大学里，人类数学发展里面有划时代意义的“微积分”的概念始终没有被我接受过，我不瞒你说，我一直就没有真的相信过“微积分”的正确性，我头脑里面一直顽固地认为那是一种“经验主义的近似”。想来这也是我们大学教育的一个问题，就是假定学生都是对老师的话确信不异的，假如这个学生不相信老师的传授，老师自然可以在考试中加以惩罚，我说的不是私人恩怨，我指的是“传道授业解惑”中中国现代教育是否重视解惑。
“微积分”的思想决不是自然而然建立的，从传统的离散数学到连续函数本来就是一种质的飞跃，历史上无数的人对此产生过怀疑，对一个像我这样的普通学生产生怀疑是绝对正常的，而中国式的教学是从不考虑学生的想法，这总让我想到世界上只有一种学问可以和这种教学思想橡比拟，那就是宗教。宗教绝对是一种感性的东西，完全只有两个选择，信或者不信，相信的途径也大多是靠旁人的传授，好比“belief”的传递，你相信这个人，便自然相信他所说的话，无需证明，也无法证明。圣经里的“神迹”也只能由圣经里的其他神迹来证明，你相信了其中一个"miracle"，自然也就相信了其他的神话。这种可怕的结果在中国一次次地重演，毛泽东思想经常被用来证明毛泽东思想的正确性。邓小平的讲话被用来证明邓小平理论的前瞻性。
中国的问题应该不是仅仅的技术引进就可以解决的，“西学为用，中学为体”的思想根深而地固，孔孟之道不除，难有新科学思想生根发芽的空间。
晚上炒了一个大茄子，放了太多的油，做出来还是被公认非常的难吃，我气愤至于把整锅的茄子炒肉沫都吃了，撑得厉害不禁又发了这么一大堆牢骚。不过我会记得主席的教导：“牢骚太盛防肠断，风物长宜放眼光”，中国的事情没有人能管，也管不好的，我就在加拿大安心地种我的小自留地吧。
Nick Huang/Qingzhe Huang

线性代数的老师很有意思，他同时也在教数学分析，不过我是在另一个长着山羊胡子的老头子的section里面。他曾经说过这门课不是宗教课，不是讲感觉，不是说一种belief可以随随便便地传递给别人。凡事都须证明，我在中国的时候，至少在高中期间数学孩子认为是学得不错的，可是这个不错也是有前提的，就是中国的数学教育是一种机械模仿，我有的时候生起气来，会过激地认为这种模式甚至可以训练猴子成为数学老师，因为，不断的机械模仿与反馈和巴普罗夫的条件反射没有本质的区别，（当然人这种动物从条件反射的角度看和狗也没有区别。）比如，我以前看到lim(f(x)+g(x))=lim(f(x)) + lim(g(x))会情不自禁地干及上帝让小学学的“分配律”又回到了高等数学。这么去看待问题以便理解记忆本来无可厚非，只是太无中生有了。学习c++操作符重载之后才意识到数学符号作为数学思想的表达的工具大大方便了交流，同时也如c++被某些人滥用后的操作符重载，变得面目全非，我从前在解数学题的时候，其实只是在不断地套用一个个“已知的模板”，进行“有一定深度限制的深度搜索”，也就是“极尽变换计算之能事”看是否和目标一致，如果经过若干步变换还是不行的话，或者达到尽头的话，就另辟新路。（不过，就是现在我难道不是这样吗？或者大多数人不是这样的？？）有时候，所谓套用的摸板实在是似是而非，也就是，类似于c++函数里参数类型错误，我现在在向那一定是因为，我们人类有了“摸板”的思想，知道有很多操作室与类型无关的，于是想当然地套用了未经验证的操作。像前面所说的函数和的极限等于函数极限的和，这根本就是函数的某个性质，和操作符号+无关，怎么能谈得上什么分配律呢？可是我却可以硬生生地把lim当作一个操作符号来看待，除非我们把操作符当作二元函数来担待，否则是无意义的。

向量空间的概念实在是伟大，他一下子把我头脑中的很多不相关的东西穿了起来，作为一个知识结构非常的深刻。可以说所有的数学，甚至自然现象都可以用向量空间的概念来理解。

我模模糊糊地想，每个子空间都有一个basis可以span出整个子空间，也就是subspace is closed in all linear combination of a certain set of vector which may be linearly independent. 我在学自动机原理的时候也总是在用到某种语言可以使用某些最基本的alphabet来得到的，难道说这些个alphabet就是这个语言的basis？

不过最近学了线性变换对这个问题有了一点点新的认识，那就是实数与这个函数在某一点的极限存在着一个线性变换，他们本来是在不同的向量空间，因为满足线性变换导致我们可以这样看待：A linear transformation F: U-->V exists between real number and the limit of some function at some point such that they satisfy two properties:

1) F(u+v)=F(u)+F(v)

2) F(kv)=kF(v)

where u,v in U.

So, that is it, as simple as that.

这其间的差别岂止十几公里？

教授讲了一个简单的矩阵应用“高斯销元法”的小的技巧，本身是为了引出"topological sort"的算法找出graph中"strongly-connected-component"的一个应用，这个冗长的话题不提，只是其中一个老外同学让他交换“列”让我糊涂了好久，下课一位仁兄指出教授错了，我听他解释了半天还是似懂非懂，地铁做到家门口才恍然大悟，可是地铁已经走出了十几公里了，想起三国演义里面曹操和杨修同时猜“绝妙好辞”的谜语时候，杨修当场想出来了，曹操骑马走出五里路才想出来，曹操夸奖杨修说自己比杨修的才智差了五里路，我想我至少比那位仁兄差了十几公里以上了。

问题是这样的：

A B C D E (1)

F G (2)

H I (3)

J K (4)

L M (5)

这样一个SPARSE的MATRIX，除了字母以外，其他的ENTRY都是0。要进行“高斯销元法”的话，怎样才好呢？首先，你知道直接作的话会在“下半个三角形”填充一队的非零数。所以，聪明的办法是（1）和（5）交换，（如下）

L M (5)

F G (2)

H I (3)

J K (4)

A B C D E (1)

然后，用（5）总共5次逐次销掉第一列，（2）总共1次销掉（1）的第二列，（3）总共1次销掉（1）的第三列。。。

L M (5)

N O P Q (2)

R S T (3)

U V (4)

W (1)

这些新的字母代表产生的新的非零数。这本来很清晰的，可是又一位外国仁兄在第二步时候将第一列于第五列交换，这简直是无稽之谈，首先，线性代数里面这一系列的操作时ROW-SPACE-EQUIVALENT的操作，做列交换纯粹无意义。其次，就算交换了，还是无法销元，这就是我上课听得稀里糊涂的地方。一个非常NICE的小的技巧被弄得无法理解。如果不做这种变幻，按部就班的销元的话操作次数是4+3+2+1=10也就是（N-1)*N/2，而现在变成了4+4=8也就是(N-1)+(N-1)，这其中的差别的确是巨大。