文档库 最新最全的文档下载
当前位置:文档库 › Refactorings that Split and Merge Programs

Refactorings that Split and Merge Programs

Refactorings that Split and Merge Programs

Christopher Brown1and Simon Thompson2

1University of Kent,Canterbury,Kent,UK.

cmb21@https://www.wendangku.net/doc/e79042622.html,

2University of Kent,Canterbury,Kent,UK.

S.J.Thompson@https://www.wendangku.net/doc/e79042622.html,

Abstract.Program slicing is a well understood concept in the impera-

tive paradigm,but so far there has been little work on program slicing

in the context of functional languages.This paper describes a program

slicing technique for Haskell that takes tuple-returning functions apart

(called splitting);the converse of this is also described(called merging).

The slicer is implemented as a transformation for the Haskell Refac-

torer,HaRe.Splitting functions is a useful transformation to allow the

programmer to extract a particular subset of the functionality of a tuple-

returning function into a new de?nition.Merging is a useful transforma-

tion because it allows many de?nitions to be merged together,thus elimi-

nating duplicate code and encouraging code reuse.Splitting and merging

can help to reduce dead code and increase program productivity and can

be also used for debugging purposes.

1Introduction

Refactoring was?rst introduced by Opdyke in his PhD.thesis in1992[10]. Refactoring is the process of changing the internal structure and organization of a program,while preserving its semantics.The key aspect of refactoring—in con-trast to general program transformations,such as genetic programming[4]—is the focus on purely structural changes rather than changes in program function-ality.Refactoring also contrasts with other meaning-preserving transformations which emphasize a change in e?ciency or other non-functional aspects.Refac-toring is aimed at improving code quality,increasing programming productivity and increasing the ability for code to be reused.This functionality-preservation is crucial so that refactorings do not introduce,or remove,any bugs.

This paper is concerned with the investigation of a number of refactorings for Haskell.We start with dead code elimination and based upon that the process is extended to introduce a notion of function splitting and merging.As an example of merging and splitting,consider the following Haskell library functions,take and drop:

take::Int->[a]->[a]

take0_=[]

take_[]=[]

take n(x:xs)

|n>0=x:take(n-1)xs

take__=error"PreludeList.take:negative argument"

drop::Int->[a]->[a]

drop0xs=xs

drop_[]=[]

drop n(x:xs)

|n>0=drop(n-1)xs

drop__=error"PreludeList.drop:negative argument"

As a concrete example of the usage of take and drop,consider:

>(take10"hello world",drop10"hello world")

>("hello worl","d")

A merge refactoring allows the creation of a function which provides both results using only one list traversal rather than one traversal for each of take and drop. In the following example,splitAt is the result of merging take and drop: splitAt0xs=([],xs)

splitAt_[]=([],[])

splitAt n(x:xs)

|n>0=(x:ys,zs)

where

(ys,zs)=splitAt(n-1)xs

splitAt__=(error"PreludeList.take:negative argument",

error"PreludeList.drop:negative argument")

The following is an example of the usage of splitAt:

>splitAt10"hello world"

>("hello worl","d")

Splitting is the converse of merging,for example,the extraction of the de?nitions of take and drop from splitAt.Although splitAt is a prede?ned Haskell function,it serves as a useful example to illustrate splitting and merging.The process of these refactorings is described in section3.1.

The refactorings are implemented in the Haskell Refactorer,HaRe.HaRe is the result of the combined e?ort of the Refactoring Functional Programs project at the University of Kent[7].HaRe provides refactorings for the full Haskell98 standard,and is integrated with the two most popular development environments for Haskell programs:Vim and(X)Emacs.HaRe refactorings can be applied to both single-and multi-module programs;HaRe is itself implemented in Haskell, and is built upon the Programatica[11]compiler front-end,and the Strafunski[6] library for generic tree traversal.The HaRe programmers’API provides the user with an abstract syntax tree(AST)together with utility functions(for example, tree traversal and tree transforming functions)to assist with the implementation of refactorings.

Pure functional programs are referentially transparent[14],therefore the op-portunities for refactoring are much greater than for imperative programs.The classical example of this,of course,is that in a functional language it is always possible to transform f x+g x into g x+f x(assuming,of course,that+is a binary commutative operator).This is not possible for an imperative language because either f or g may change the value of the parameter x and therefore the result will depend on execution order.This is not,of course,the case in a functional language.In addition to this,in a functional language duplicated occurrences of an expression(within the same scope)will have identical values, and so could be replaced with a shred computation;this is also not the case for imperative programs.

The following sections?rst introduce the idea of eliminating code within a function that is not needed;this has two?avours:unused code elimination and irrelevant code elimination.A notion of program slicing in Haskell is then outlined.A backwards,static program slicing technique that takes apart tuple-returning functions is de?ned.Following this the converse of the splitting opera-tion,namely merging is also de?ned.The paper concludes by looking at possible future developments in program slicing for Haskell.

2Code Elimination

Dead code elimination[3]is a compiler optimization used to reduce a program size by removing the parts of the program which are not needed.In Haskell dead code contains code that is unreachable by evaluating the main function.

This section introduces two?avours of code elimination:dead code elimina-tion and irrelevant code elimination.Dead code elimination is concerned with taking a particular top-level function of interest,and removing any nested decla-rations within that function that are not needed.Irrelevant code elimination is a generalization of the former.Irrelevant code elimination focuses upon removing nested declarations that are not needed to compute a particular sub-expression within the top-level declaration.Irrelevant code elimination is used to aid the programmer in debugging code.

2.1Dead Code Elimination

Often programmers write a?rst version of a program without paying full at-tention to programming style or design principles[5].Often,having written a program,the programmer will realise that a di?erent approach would have been much better.Refactoring tools provide software support for modifying the origi-nal program into a better written program thus avoiding the expense of starting from scratch.

Programming“rapidly and badly”can cause lots of unnecessary declarations in the program;declarations that are never called and are hence“dead”.For example,the code below takes a list of type variables and produces a data structure containing the list of type variables:

createApp[var]

=(Typ(HsTyVar(nameToTypePNT var)))

createApp(v:vars)

=Typ(HsTyVar(nameToTypePNT(v++

(concatMap("->"++)vars)))) where

myConcat::[String]->String

myConcat[]=[]

myConcat(x:xs)=(x++"->")++(myConcat xs)

The function createApp contains one declaration that is not needed:myConcat can be removed,as it is not needed to evaluate the result.Dead code can make a function look particularly messy and depending on the particular compiler used may actually consume memory and slow execution.Dead Code Elimination is a refactoring implemented in HaRe that searches the AST for the de?nition of a particular function(supplied as a location in the original code),removing any declarations contained within that particular function that are not needed.The examples provided in this section present only a where clause;a similar technique is used to cope with lambda de?nitions and let clauses.

There are two stages to the refactoring.An analysis stage that collects all the information required to do the modi?cation,and a modi?cation stage that actually performs the modi?cation on the AST with the information provided by the analysis stage.Currently the refactoring only removes dead code from within one function.However,it could easily be expanded to take a whole module of functions(or,indeed,a set of modules)into consideration.

The main algorithm is as follows:

1.The particular function clause in question is extracted from the AST.

2.The right-hand-side is traversed until the result is found.

3.A list of free identi?ers(identi?ers that are declared at another point in the

program)are calculated from the expression.Identi?ers that are declared outside of the scope of the function clause are removed from the list.

4.There are three main stages to the removal of dead code:

(a)declarations that are used on the right-hand-side are then also traversed

to determine free variables contained therein.

(b)steps3-4are repeated for each declaration appearing in the list of free

variables(this checks to see whether some declarations depend on other declarations in scope).Nested declarations are also considered.

(c)the where clause is then traversed.Steps3-4is repeated for each decla-

ration in the where clause.This takes into account nested where clauses.

5.For mutually referential declarations the algorithm traverses the AST for

all declarations to ensure that all free variables in those declarations are retained.

6.Any declarations remaining are removed from the AST.

In order to use this tool,?rstly the user selects a function from the editor window.The user then selects dead code elimination from the HaRe drop-down

menu.To capture the entire namespace,the whole program is parsed into an AST and token stream.The AST is then traversed using Strafunski to?nd the particular function clause in question.This traversal is performed by using the location information in the AST;it is possible to traverse into any functions corresponding to the selection region in the editor.Once the function is found the function’s where clause and right-hand-side is retrieved.The function’s right-hand-side is then traversed until the result is reached.For example the result of createApp is:

Typ(HsTyVar(nameToTypePNT(v++(concatMap("->"++)vars)))) Declarations declared in the scope of createApp must be analysed to check whether they are dead;these declarations can appear within let clauses and lamdba expressions within the right-hand-side of the function.The refactoring takes into consideration nested declarations;for example:where/let clauses. Once the returning subexpression is reached,the free and bound names within the subexpression are calculated.The list of free names is then used to remove those declarations residing on the right-hand-side that do not appear within the list of free names.For example:

f x=z+res

where

res=f(x-1)

res2=f(x+1)

y=x+1

z=46f x=z+res

where

res=f(x-1)

z=46

The result expression is z+res and the only free variables are z and res; therefore,y can be removed from the right-hand-side of f as it is not used within z+res.

Any mutually referential declarations must be taken care of by ensuring that all free variables in those declarations are retained.For example in the code below it can clearly be observed that the declaration z depends on the declaration y.

Once the right-hand-side has been modi?ed to remove the declarations that are not used,the where clause of the function in question is then analysed.This time the free variables are calculated for each sub-expression within the modi?ed right-hand-side;each member of the where clause that appears in the list of free variables is then analysed for its free variables.All the declarations in the where clause that are not needed by the right-hand-side of the function in question,and

do not appear in the dependancy graph of any needed declaration,are removed:

f x=z+res

where

res=f(x-1)

res2=f(x+1)

y=x+1

z=46+y f x=z+res

where

res=f(x-1)

y=x+1

z=46+y

After the AST has been modi?ed,the source code is also modi?ed to mirror the changes of the refactoring.

A popular technique in abstract interpretation[2]is strictness analysis[8]. Dead code elimination is related to strictness analysis in that strictness analysis searches for parts of a program that will always be used.Dead code elimination searches for parts of the program that will never be used.Strictness analysis works by abstracting away from the program so that some dynamic information can be inferred in a static way:inferring that the boolean conditional in an if expression is False,say,and therefore calculating that the consequence of the if is never evaluated.This paper takes a static approach to determining dead code.

2.2Irrelevant Code Elimination

Irrelevant code elimination is useful for debugging purposes and to some extent is used in algorithmic debugging[13].In algorithmic debugging the debugging tool asks the user a series of questions about whether a particular sub-expression in the code is generating the correct result or not.As the questions proceed,the particular parts of the program that the debugging tool is asking questions about becomes more clearly focused.It is often the case,however,that the programmer will have some intuition where the bug will lie within the code.Extracting a particular sub-expression that is suspected to cause a bug increases the chances of?xing the error.Parts of a function that are known(or at least assumed)to be correct are temporarily removed so the programmer can concentrate e?ort on?xing the incorrect sub-expression.

As described above,the Dead Code Elimination technique may be generalized to facilitate debugging.It is possible to select a particular sub-expression of interest and to have the function pruned of declarations that are not needed by that particular sub-expression.The expression on the right-hand-side is replaced with the selected sub-expression.This particular generalization of dead code elimination is not a refactoring,it is in fact a transformation since it changes the semantics.For example,consider:

count::[[a]]->Int

count(l:list)=maximum(map length list)

pad::[[a]]->[[a]]

pad lists=map(pad’(count lists))lists

where

pad’count entry=entry++(replicate count(head entry)) Suppose the programmer suspects there is a bug in pad,speci?cally,the pro-grammer believes that the bug is in the call count lists.Isolating out only the call to count lists into a new function would allow the programmer to test that call explicitly,eliminating the parts of pad that the programmer believes to be correct:

count::[[a]]->Int

count(l:list)=maximum(map length list)

pad2::[[a]]->Int

pad2lists=count lists

The programmer can then place a call to pad2in the code,test the program, discover that the formal parameter to count is in fact incorrect and undo the previous transformation and correct the error:

count::[[a]]->Int

count list=maximum(map length list)

The de?nition of pad remains unchanged.

2.3Summary

This section has described two?avours of code elimination for Haskell.The ?rst:dead code elimination was concerned with looking at the entire result of a function and removing the parts of the function that were not needed to compute the result.This was then generalized further by allowing the user to highlight a particular sub-expression in the result and then remove the parts of the function that are not needed to compute the sub-expression;this process was called irrelevant code elimination.Dead code elimination and irrelevant code elimination,in particular,form the basis of a backwards static program slicing tool.The next section expands on the work presented here to introduce the notion of splitting and merging.

3Slicing Based Refactorings

This section de?nes what program slicing means for a functional language.In section3.1program slicing is introduced and is then implemented as a splitting refactoring in section3.2.The converse of this is then described in section3.3.

3.1Program Slicing

Weiser,in[16],introduces a program slice S as a reduced executable program obtained from a program P by removing statements,such that S replicates part of the behavior of P.This process is driven from a slicing criterion,usually a variable representing the line number and expression of interest,which is used to represent the point in the code whose impact is to be observed with respect to the entire program.Weiser introduced the concept that is now known as a backwards, static slicing method.A backwards slice consists of all parts of a program that have an e?ect on the criterion in question.Another form of program slicing is a forwards slice[15].Starting with the slicing criterion,or the program point of interest,a forwards slice is all parts of the program that the criterion will a?ect.

Orthogonal to the choice between forward and backward slicing is the distinc-tion between static and dynamic slicing:static program slicing means that all possible computations of a program are considered and dynamic program slicing means inferring names with particular values,giving a very speci?c computation of a program.Often,the slicing criterion is a sub-set of program variables—the program slice becoming the parts of the program related to the variables.

The obvious analogue to this within the functional paradigm is a subset of the components of a structured result,for example,the?elds of a tuple in Haskell. Selecting the components of a result and looking at the computation corresponds to backwards slicing,whereas selecting the subset of the arguments of a function, and seeing what can be computed on the basis of them alone,corresponds to a forwards slice.

Hitherto,there has been little work on program slicing for functional lan-guages.Ochoa et al.[9]introduced a dynamic slicing technique for a lazy logic language.The Haskell debugger,Hat[1],also includes a form of program slicer. However,at this time there is no standalone program slicing tool available for Haskell and therefore we attempt to de?ne a backwards static slicer for Haskell.

This section introduces the notion of program splitting and merging.A num-ber of issues with performing splitting and merging are also given.

3.2Splitting

A function may return a structured value,for example,a tuple.The particular examples presented in this section use only pairs,however the technique can easily work over tuples of any order.

Splitting works by selecting an element of the tuple and then working out everything needed to calculate that element.The calculated dependencies are then simply extracted and isolated from the rest of the function.

Splitting is mostly used for debugging purposes.However splitting may also be used to extract functionality out of the function so that it can be extended or re-used.The user passes a parameter to the splitter the elements of the result of the function in question which are to be extracted.

Consider the function parseMessage below.parseMessage takes a String of messages each separated by the&character.parseMessage removes the initial

message and returns the next message as the?rst element of the result and the remainder of the message as the second element:

type MessageList=String

type Message=String

parseMessage::MessageList->(Message,MessageList) parseMessage[]=([],[])

parseMessage xs=(takeWhile(/=’&’)(tail ys),

dropWhile(/=’&’)(tail ys))

where

ys=dropWhile(/=’&’)xs

As an example of the usage of parseMessage consider:

>parseMessage"goodbye&hello&world"

>("hello","&world")

The splitter works through each function clause in turn,extracting the ele-ments of the function clauses’result into separate de?nitions.It is worth noting that the results of these refactorings are themselves ready for a further refac-toring,namely replacing ys with its de?nition(removing the where clause alto-gether).It is often the case that further refactorings such as this are often per-formed.The?rst pattern clause of parseMessage is essentially trivial.Therefore the value[]is extracted for both elements of the result and two new functions are then created:

parseMessage1::MessageList->Message

parseMessage1[]=[]

parseMessage2::MessageList->MessageList

parseMessage2[]=[]

The splitter appends an index to the end of the names of the new functions,if the new names con?ict with any other identi?er in scope then the splitter chooses a new distinct name.This is simply done by incrementing the index until the name no longer con?icts with another identi?er in scope.

The next function clause’s result is then analysed.Irrelevant code elimination is then performed for each element in the resulting tuple and the result of the code elimination is placed into new function clauses for parseMessage1and parseMessage2.ys is required by both elements of the result of parseMessage so it is retained;the new function clauses are then added to the de?nitions of parseMessage1and parseMessage2within the AST.

parseMessage1xs=takeWhile(/=’&’)(tail ys)

where

ys=dropWhile(/=’&’)xs

parseMessage2xs=dropWhile(/=’&’)(tail ys)

where

ys=dropWhile(/=’&’)xs

This gives the new de?nitions of parseMessage1and parseMessage2.The source code is then modi?ed to re?ect the changes within the AST.

3.3Merging

Merging is the process of taking a number of functions and unifying them to-gether into one tuple-returning function.The process described here only merges

two functions;obviously the functionality can be easily extended however,to merge together any number of functions.

Merging works by unifying all the code from the selected functions into a new tuple-returning function.Duplicate parts of the function are also removed. Unlike when doing splitting,where names are generated automatically,the user must specify a name for the merged function.

Merging is mostly used to reuse code and improve code e?ciency.For ex-ample,merging take and drop into splitAt results in only one recursive call instead of two.Merging functions together has the possibility to introduce fur-

ther code sharing.

The remainder of this section will focus on merging parseMessage1and parseMessage2.

parseMessage1::MessageList->Message

parseMessage1[]=[]

parseMessage1xs=takeWhile(/=’&’)(tail ys)

where

ys=dropWhile(/=’&’)xs

parseMessage2::MessageList->MessageList

parseMessage2[]=[]

parseMessage2xs=dropWhile(/=’&’)(tail ys)

where

ys=dropWhile(/=’&’)xs

Firstly,the merge refactoring checks to see whether the pattern sets of parseMessage1 and parseMessage2are the same.If they are not then the merge refactoring terminates with an error to the user.The merge refactoring also checks to see whether the types of the arguments to parseMessage1and parseMessage2are

the same.If the pattern sets are not the same then the merge refactoring can-

not correctly unify the patterns;if they cannot be uni?ed the merge refactoring terminates with an error message to the user.

Each function clause in question is merged together.The?rst clause of parseMessage1and parseMessage2both have the same result value.Merging those clauses together is trivial:

parseMessage::MessageList->(Message,MessageList)

parseMessage[]=([],[])

The second clauses of parseMessage1and parseMessage2are now considered. The results are uni?ed together and placed into a new function clause: parseMessage xs=(takeWhile(/=’&’)(tail ys),

dropWhile(/=’&’)(tail ys))

where

ys=dropWhile(/=’&’)xs

ys=dropWhile(/=’&’)xs

The duplicate declaration of ys within the where clause is removed.

3.4Design and Implementation Issues

Sometimes when splitting is used patterns that are the result of recursive calls become redundant.All patterns that are not needed in the result are replaced with wildcards so that the namespace is kept clean.

One element of a tuple may depend upon another element.For instance,it is possible for one element to come from the?rst part of a recursive call,but for it to be returned in the second element in the main body.In very unusual circumstances the following can occur:

f::Int->(Char,(Char,Int))

f10=(‘a’,(g‘f’1,2))

f n=(x,(

g x1,2))

where

(_,(x,2))=f(n+1)

g::Char->Int->Char

g x y=chr(ord x+1)

The?rst element of the result of f comes from the second element in its recursive call.If one element depends on another,both of these elements must be extracted from the function,otherwise an error occurs.

Before merging,it is necessary that both functions have the same sets of pat-terns.If the?rst function has more pattern clauses than the second for example, then the merge refactoring cannot determine what to place on the right-hand-side when patterns from the?rst function are not matched by patterns in the second.An error message is presented to the user if the pattern sets are not the same.An additional refactoring was introduced to allow the user to build particular pattern clauses by instantiating general patterns with values of the same type.Consider,for example:

f10l=take42l

f1n l=take n l

f2n l=drop n l

Both f1and f2have general cases de?ned,however,f1has an additional base case de?ned.This is problematic because the merge refactoring cannot infer what the intention is of the user during the merge:

merged0l=(take42l,undefined)

merged n l=(take n l,drop n l)

When merging functions,it is also necessary that the arguments to the func-tions have the same type so that they can be successfully merged.If the functions have di?erent argument types then the merge refactoring returns an error.It is possible that the functions have di?erent return types as this will be captured in a tuple.

Merging and splitting monadic functions is a di?cult area,especially if the monad in question is a state monad,for example,the IO monad.Merging two IO monadic values is problematic because the merge refactoring cannot infer the correct order of sequencing.Side e?ects also e?ect splitting in a similar way, for example,an element of the tuple return value may depend upon some data written to a?le.It is very di?cult for the splitter to determine which parts of the monad can have a potential e?ect as all expressions have the potential to alter the state.Merging and splitting refactorings on monads will be the subject of a future paper.

4Conclusions and Future Work

This paper presented a number of refactorings for HaRe.Firstly,a technique was de?ned to eliminate dead code from Haskell functions and then generalized further to remove irrelevant code.A backwards,static program slicer for Haskell was then described as splitting tuple-returning functions;its converse,namely merging,was also described.

In the future it is planned that dead code elimination will be expanded to take a whole program into account and not just a selected function.Dead code elimination could remove the parts of the program that are not directly related to the main function,which would allow the process to be extended to the whole of a large Haskell project.

It is also planned to modify the splitter to analyze the whole scope of a program rather than,simply,tuple-returning functions in the scope of a par-ticular function of interest.It is also planned to modify the splitter so that tuple-returning functions that are called from outside a function’s scope to be extracted.

A further paper will detail work on refactoring with monads.It is intended for the work on slicing to be extended further to investigate backwards,dynamic slicing and forwards slicing(both static and dynamic).There are many more exciting possibilities to analyze for the refactoring of Haskell code;and it is hoped to continue work in these directions.

5Acknowledgments

Thanks to Dave Harrison of Northumbria University for his editorial advice.

A Source Code

All the code that has been described in this paper can be downloaded using darcs[12]with the following command:

darcs get https://www.wendangku.net/doc/e79042622.html,/projects/refactor-fp/HaRe_Project/ References

1.Olaf Chitil.Source-based trace exploration.In Draft Proceedings of the16th

International Workshop on Implementation of Functional Languages,IFL2004, pages239–244.Technical Report0408,University of Kiel,September2004.

2.P.Cousot and R.Cousot.Abstract interpretation:a uni?ed lattice model for static

analysis of programs by construction or approximation of?xpoints.In Conference Record of the Fourth Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages,pages238–252,Los Angeles,California,1977.ACM Press,New York,NY.

3.Matthew S.Hecht.Flow Analysis of Computer Programs.Elsevier Science Inc.,

New York,NY,USA,1977.

4.John H.Holland.Adaptation in natural and arti?cial systems.MIT Press,Cam-

bridge,MA,USA,1992.

5.Fred P.Brooks Jr.The Mythical Man-Month.In Proceedings of the international

conference on Reliable software,page193,New York,NY,USA,1975.ACM Press. 6.Ralf Lammel and Joost Visser.A strafunski application letter.In Proc.of

PADL’03,January2003.

7.Huiqing Li,Simon Thompson,and Claus Reinke.The Haskell Refactorer:HaRe,

and its API.In John Boyland and Grel Hedin,editors,Proceedings of the5th workshop on Language Descriptions,Tools and Applications(LDTA2005),April 2005.Published as Volume141,Number4of Electronic Notes in Theoretical Computer Science,https://www.wendangku.net/doc/e79042622.html,/science/journal/15710661.

8.Alan Mycroft.The theory and practice of transforming call-by-need into call-by-

value.In Proceedings of the Fourth’Colloque International sur la Programmation’on International Symposium on Programming,pages269–281,London,UK,1980.

Springer-Verlag.

9.Claudio Ochoa,Josep Silva,and Germ′a n Vidal.Dynamic slicing based on redex

trails.In PEPM’04:Proceedings of the2004ACM SIGPLAN symposium on Partial evaluation and semantics-based program manipulation,pages123–134,New York,NY,USA,2004.ACM Press.

10.William F.Opdyke.Refactoring object-oriented frameworks.PhD thesis,Cham-

paign,IL,USA,1992.

11.PacSoft.Programatica:Integrating programming,properties and validation.

https://www.wendangku.net/doc/e79042622.html,/PacSoft/projects//,2005.

12.David Roundy.Darcs:distributed version management in Haskell.In Haskell’05:

Proceedings of the2005ACM SIGPLAN workshop on Haskell,pages1–4,New York,NY,USA,2005.ACM Press.

13.Josep Silva and Olaf https://www.wendangku.net/doc/e79042622.html,bining algorithmic debugging and program slicing.

In PPDP’06:Proceedings of the8th ACM SIGPLAN symposium on Principles and practice of declarative programming,pages157–166,New York,NY,USA,2006.

ACM Press.

14.Harald Sondergaard and Peter Sestoft.Referential transparency,de?niteness and

unfoldability.Acta Inf.,27(6):505–517,1990.

15. F.Tip.A survey of program slicing techniques.Report CS-R9438,Centrum voor

Wiskunde en Informatica(CWI),Amsterdam,1994.

16.Mark David Weiser.Program slices:formal,psychological,and practical investiga-

tions of an automatic program abstraction method.PhD thesis,1979.

第六章 相关函数的估计

6. 相关函数的估计(循环相关) 6.1. 相关函数与协方差函数 6.1.1. 自相关函数和自协方差函数 1、 自相关和自协方差函数的定义 相关函数是随机信号的二阶统计特征,它表示随机信号不同时刻取值的关联程度。 设随机信号)(t x 在时刻j i t t ,的取值是j i x x ,,则自相关函数的定义为 j i j i j i j i N n n j n i N j i j i x dx dx t t x x f x x x x N x x E t t R ??∑= ===∞ →),;,(1lim ] [),(1 ) ()( 式中,上角标“(n )”是样本的序号。 自协方差函数的定义与自相关函数的定义相似,只是先要减掉样本的均值函数再求乘积的数学期望。亦即: j i j i j i x j x i N n x n j x n i N x j x i j i x dx dx t t x x f m x m x m x m x N m x m x E t t C j i j i j i ??∑--= --=--==∞ →),;,())(() )((1lim )] )([(),(1 ) ()( 当过程平稳时,);,(),;,(τj i j i j i x x f t t x x f =。这时自相关函数和自协方差函数只是i j t t -=τ的函数,与j i t t ,的具体取值无关,因此可以记作)(τx R 和)(τx C 。 对于平稳且各态历经的随机信号,又可以取单一样本从时间意义上来求这些统计特性: 时间自相关函数为:

? + - ∞ →+=22 )()(1lim )(T T T x dt t x t x T R ττ 时间自协方差函数为: ? + - ∞ →-+-=22 ])(][)([1lim )(T T x x T x dt m t x m t x T C ττ 在信号处理过程中,有时会人为地引入复数信号。此时相应的定义变成 ][),(* j i j i x x x E t t R = )]()[(),(* j i x j x i j i x m x m x E t t C --= 式中,上角标*代表取共轭。 2、 自相关和自协方差函数的性质 自相关和自协方差函数的主要性质如下: (1) 对称性 当)(t x 时实函数时,)(τx R 和)(τx C 是实偶函数。即 ) ()(), ()()()(),()(* * ττττττττx x x x x x x x C C R R C C R R =-=-== 当)(t x 时复值函数时,)(τx R 和)(τx C 具有共轭对称性。即 )()(), ()(* * ττττx x x x C C R R =-=- (2) 极限值 )(, )()0(,)0(2=∞=∞==x x x x x x x C m R C D R σ (3) 不等式 当0≠τ时, )()0(), ()0(ττx x x x C C R R ≥≥ 因此, )0()()(x x x R R ττρ=

VB第六章习题答案(上海立信会计学院)

上海立信会计学院 班级:学号: 姓名:指导教师: 专业: 习题六p150 -、简述子过程与函数过程的共同点和不同之处。 答:相同之处:都是功能相对独立的一种子程序结构,它们有各自的过程头、变量声明和过程体,在程序的设计过程中可以提高效率。 不同之处: (1)声明的关键字不同。子过程为Sub,而函数过程为 Funct ion。 (2)了过程无值就无类型说明,函数过程有值因此有类型的说明 (3)函数的过程名称同时是结果变量,因此在函数过程体 内至少要对函数的过程名赋值一次数据,而子过程内不能赋 值。

(4)调用的方式不同,子过程是一条独立的语句,可以用 Cal I子过程名或省略Call直接以子过程名调用;函数的过 程不是一条独立的语句,是一个函数值,必须参与表达式运算。(5)通常,函数过程可以被子过程代替,只需要在调用的 过程中改变一下过程调用的形式,并在子过程的形参表中增加一个地址传递的形参来传递结果。 二、什么是形参,实参?什么是值引用?地址引用?地址应用 对实参有什么限制? 答:形参:在定义过程时的一种假设的参数,只代表该过程的参数的个数、类型,它的名字不重要,没有任何的值, 只表示在过程体内将进行的一种操作。 实参:在调用子过程时提供过程形参的初始值,或通过过程体处理后的结果。 值引用:系统将实际参数的值传到形参之后,实参与形参断开联系,过程中对于形参的修改不会影响到实际参数的变化。 地址引用:实参与形参共同使用一个存储单元,在过程中对形参进行修改,则对应的实际参数也同时变化。

在地址引用时,实参只能是变量,不能是常量或表达式。

三、指出下面过程语句说明中的错误: Sub f1 (n%) as Integer Function f1%(f1%) Sub fl (ByVa I n% 0) Sub fl(X(i) as Integer) 答:(1) Sub子过程名没有返回值,因此就没有数据的类型 (2)函数名与形参名称相同 (3)形参n为数组,不允许声明为By Vai值传递 (4)形参x(i)不允许为数组元素 四、已知有如下求两个平方数和的fsum子过程: Publ ic Sub fsum (sum%, ByVaI a%, ByVaI b%) sum =a*a+b*b End Sub 在事件过程中若有如下变量声明: Pr ivate Sub Commandl Cl ick()

VB第六章习题答案(上海立信会计学院)

上海立信会计学院 班级:学号:姓名:指导教师: 系部:专业: 习题六p150 一、简述子过程与函数过程的共同点和不同之处。 答:相同之处:都是功能相对独立的一种子程序结构,它们有各自的过程头、变量声明和过程体,在程序的设计过程中可以提高效率。 不同之处: (1)声明的关键字不同。子过程为Sub,而函数过程为Function。 (2)了过程无值就无类型说明,函数过程有值因此有类型的说明 (3)函数的过程名称同时是结果变量,因此在函数过程体内至少要对函数的过程名赋值一次数据,而子过程内不能赋值。 (4)调用的方式不同,子过程是一条独立的语句,可以用Call子过程名或省略Call直接以子过程名调用;函数的过程不是一条独立的语句,是一个函数值,必须参与表达式运算。 (5)通常,函数过程可以被子过程代替,只需要在调用的过程中改变一下过程调用的形式,并在子过程的形参表中增加一个地址传递的形参来传递结果。 二、什么是形参,实参?什么是值引用?地址引用?地址应用对实参有什么限制? 答:形参:在定义过程时的一种假设的参数,只代表该过程的参数的个数、类型,它的名字不重要,没有任何的值,只表示在过程体内将进行的一种操作。 实参:在调用子过程时提供过程形参的初始值,或通过过程体处理后的结果。 值引用:系统将实际参数的值传到形参之后,实参与形参断开联系,过程中对于形参的修改不会影响到实际参数的变化。 地址引用:实参与形参共同使用一个存储单元,在过程中对形参进行修改,则对应的实际参数也同时变化。 在地址引用时,实参只能是变量,不能是常量或表达式。 三、指出下面过程语句说明中的错误:

(1)Sub f1(n%) as Integer (2)Function f1%(f1%) (3)Sub f1(ByVal n%()) (4)Sub f1(x(i) as Integer) 答:(1)Sub子过程名没有返回值,因此就没有数据的类型 (2)函数名与形参名称相同 (3)形参n为数组,不允许声明为ByVal值传递 (4)形参x(i)不允许为数组元素 四、已知有如下求两个平方数和的fsum子过程: Public Sub fsum(sum%, ByVal a%, ByVal b%) sum = a * a + b * b End Sub 在事件过程中若有如下变量声明: Private Sub Command1_Click() Dim a%, b%, c! a = 10: b = 20 则指出如下过程调用语句的错误所在: (1)fusum 3, 4, 5 (2)fsum c, a, b (3)fsum a + b, a, b (4)Call fsum(Sqr(c), Sqr(a), Sqr(b)) (5)Call fsum c,a,b 答:(1)furm子过程的第一个形参是地址传递,因此对应的实参3不能是常量 (2)furm的第一个形参是整型而且是地址传递,对应的实参c是单精度,数据类型不匹配(3)furm的第一个形参是地址传递,因此对应的实参a+b不应当是表达式 (4)furm的第一个形参是地址传递,因此对应的实参Sqr(c)不应当是表达式 (5)用Call语句调用furm子过程时,必须用圆括号来描述实参 六、要使变量在某事件过程中保留值,有哪几种变量声明的方法? 答:声明为static或者全局变量 七、为了使某变量在所有的窗体中都能使用,应在何处声明该变量? 答:应在窗体\模块的通用声明段用Public关键字声明为全局变量。

第六章函数-选择题

第六章函数 二、选择题 1.C语言程序由函数组成。正确的说法是____B______。 A)主函数写在必须写在其他函数之前,函数内可以嵌套定义函数 B)主函数可以写在其他函数之后,函数内不可以嵌套定义函数 C)主函数必须写在其他函数之前,函数内不可以嵌套定义函数 D)主函数必须在写其他函数之后,函数内可以嵌套定义函数 2.一个C语言程序的基本组成单位是_____C_____。 A)主程序B)子程序C)函数D)过程 3.以下说法正确的是____ C ______。 A)C语言程序总是从第一个定义的函数开始执行 B)C语言程序中,被调用的函数必须在main()函数中定义 C)C语言程序总是从主函数main()开始执行。 D)C程序中的main()函数必须放在程序的开始处 4.已知函数fun类型为void,则void的含义是____ A ______。 A)执行函数fun后,函数没有返回值B)执行函数fun后,可以返回任意类型的值 C)执行函数fun后,函数不再返回D)以上三个答案都是错误的 5.下列对C语言函数的描述中,正确的是____ A ______。 A)在C语言中,调用函数时只能将实参的值传递给形参,形参的值不能传递给实参B)函数必须有返回值 C)C语言函数既可以嵌套定义又可以递归调用 D)C程序中有调用关系的所有函数都必须放在同一源程序文件中 6.以下叙述中错误的是_____ B _____。 A)函数形参是存储类型为自动类型的局部变量 B)外部变量的缺省存储类别是自动的。 C)在调用函数时,实参和对应形参在类型上只需赋值兼容 D)函数中的自动变量可以赋初值,每调用一次赋一次初值 7.C语言中的函数____D______。 A)不可以嵌套调用B)可以嵌套调用,但不能递归调用 C)可以嵌套定义D)嵌套调用和递归调用均可 8.C语言中函数返回值类型由____D_____决定。 A)调用该函数的主调函数类型B)函数参数类型 C)return语句中的表达式类型D)定义函数时指定的函数类型 9.C语言规定,调用一个函数,实参与形参之间的数据传递方式是___D_____。 A)由实参传给形参,并由形参传回来给实参B)按地址传递 C)由用户指定方式传递D)按值传递 10.下列叙述错误的是____C______。 A)形参是局部变量 B)复合语句中定义的变量只在该复合语句中有效 C)主函数中定义的变量在整个程序中都有效 D)其他函数中定义的变量在主函数中不能使用 11.若函数类型和return语句中的表达式类型不一致,则____B______。

基于知识层次的知识组织层次模型

●李耀昌1,姚 伟1,刘建准2 (11南开大学 商学院,天津 300071;21天津工业大学 工商学院,天津 300387) 基于知识层次的知识组织层次模型 摘 要:通过引用马斯洛的“需求层次理论”,把知识划分为:基于生存需要的知识、基于技能需要的知识、基于消遣需要的知识、基于实现自我的知识,提出“知识层次理论”这一概念,并在此基础上探讨“知识组织层次模型”。 关键词:知识分类;知识组织;模型 Abstract:By citingMasl owπs“hierarchy of needs theory”,this article divides knowledge int o knowledge based on the need of survival,knowledge based on the need of skill,knowledge based on the need of recreati on and knowl2 edge based on the need of self2exp ressi on1The article puts for ward the idea of“hierarchy of knowledge theory”,and on this basis,discusses the“model of knowledge organizati on hierarchy”1 Keywords:knowledge classificati on;knowledge organizati on;model 自美国心理学家亚伯拉罕?马斯洛(A1Masl ow)在《人类激励理论》一文中突出“需求层次理论”以来[1],在管理领域掀起了一场关于组织行为和管理激励的革命风暴。该理论从人的需求层次是由低级向高级不断发展的这一角度出发,研究人的心理活动和行为,继而探索人的激励方式。因为该理论在很大程度上可以反映出人类心理和行为的普遍规律,所以需求层次理论对管理者如何更好地调动组织成员的积极性具有很大的启发作用。 半个多世纪以来,马斯洛需求层次理论随着社会的不断发展,展现出新的发展和应用。在理论上,众多研究者从不同角度出发,将该理论同各个具体学科相结合,形成具有学科特色的研究成果,给具体学科的发展注入了新鲜的血液。如将需求层次理论与教育学相结合,探索出合适的激励学习机制;与马克思主义学相结合,探讨其与马克思主义唯物史观的内在必然联系;与临床医学相结合,探索出一些对病人实施护理的方案。在实践中,不同行业的实践者通过灵活运用该理论,使得组织获益匪浅。如运用于现代企业管理中,找出如何更好地吸引人才、留住人才、运用人才等措施;运用于市场营销中,提出优化产品设计方案,提高顾客忠诚度,继而提高品牌效应;运用于房地产经济中,可以最大限度地满足当前住户对住房附加值的追求。另外在市场经济中,运用马斯洛需求层次理论可以发现一些新的商机,如随着人口老龄化时代的到来,研究如何更好地满足老年人这一特殊群体的需求,将会开辟出一个“朝阳行业”。 笔者将马斯洛需求层次理论与知识分类相结合,提出“知识层次理论”(H ierarchy of Knowledge)这一知识分类思想,并在此基础上提出“知识组织层次模型”。 1 知识层次理论 111 有关知识的分类 由于知识具有动态性、复杂性、多样性的特点[2],需要从不同的角度和层次对知识进行划分和比较,总结出一些普遍性的规律和特点,这不仅有利于人们对知识的认识更深刻,利用更加灵活、有效,从学科发展的角度讲,也有利于知识管理科学的长远发展。关于知识的分类,研究者从不同角度和理论出发,产生了一些关于知识分类的成果。这些知识分类理论和方法在知识管理的发展中具有重要的作用。 陈洪澜将知识分类方式总结为:“按照知识的效用分类、按照研究对象分类、按照知识属性分类、按照知识形态分类、按照事物运动形式分类、按照思维特征分类、按照自然现象和社会现象分类、按照知识研究方法分类、按照知识内在联系分类、按照学科发展趋势分类”共10类[3]。另外还有几种具有代表意义的知识分类:如英国哲学家、科学家波兰尼(Polanyi)将知识分为显性知识(Exp licit Knowledge)和隐性知识(Tacit Knowledge)两类;按照知识载体来源的不同,知识可以分为个人知识和组织知识。美国知识管理专家艾莉(A llee)在对知识分类方法进行研究时,从知识的复杂程度出发提出了“知识原型”的概念,知识原型是数据、信息、知识、含义、原理、智慧的联合体。她认为,知识具有“波粒二相性”,

第六章一次函数

§6.1 函数 教学目标: 1、初步掌握函数概念,能判断两个变量间的关系是否可看做函数。 2、根据两个变量间的关系式,给定其中一个量,相应地会求出另一个量的值。 3、会对一个具体实例进行概括抽象成为数学问题。 教学重点 1、掌握函数概念。 2、判断两个变量之间的关系是否可看做函数。 3、能把实际问题抽象概括为函数问题。 教学难点 1、理解函数的概念。 2、能把实际问题抽象概括为函数问题。教学过程 一、导入新课 你坐过摩天轮?你坐在摩天轮上时,人的高度随时在变化,那么变化是否有规律呢? 摩天轮上一点的高度h与旋转时间t之间有一定的关系,请看图6—1进行填表。 当t为0时,h约为3米, 当t为1分时,h约为11米, 当t为2分时,h约为37米, 当t为3分时,h约为45米, 当t为4分时,h约为37米, 当t为5分时,h约为11米.…… 二、讲授新课 做一做 1、按如图所示画圆圈,并填写下表。 层数n 1 2 3 4 5 … 圆圈总 1 3 6 10 15 … 数 随着层数的增加,物体的总算是如何变化?

2、在平整的路面上,某型号汽车紧急刹车后仍将滑行S 米, 一般地有经验公式S =300 2 V ,其中V 表示刹车前汽车的速度(单位: 千米/时)。 (1)计算当V 分别为50,60,100时,相应的滑行距离S 是多少? (2)给定一个V 值,你能求出相应的S 值吗? 议一议 在上面我们共研究了三个问题,下面大家探讨一下,在这三个问题中的共同点是什么?相异点又是什么呢? 函数的概念 一般地,在某个变化过程中,有两个变量x 和y ,如果给定一个x 值,相应地就确定了一个y 值,那么我们称y 是x 的函数,其中x 是自变量,y 是因变量。 三、随堂练习 课本随堂练习 第1、2题。 四、小结 1、初步掌握函数概念,能判断两个变量间的关系是否可看做函数。 2、在一个函数关系式中,能识别自变量与因变量,给定自变量的值,相应地会求出函数的值。 3、函数的三种表达形式。 五、作业 课本习题6.1 第1题。

第六章函数导学案

函数 教学目标: 【知识目标】1、初步掌握函数概念,能判断两个变量间的关系是否可看作函数。 2、根据两个变量间的关系式,给定其中一个量,相应地会求出另一个量的值。 3、会对一个具体实例进行概括抽象成为数学问题。 【能力目标】1、通过函数概念,初步形成学生利用函数的观点认识现实世界的意识和能力。 2、经历具体实例的抽象概括过程,进一步发展学生的抽象思维能力。 教学过程设计: 一、创设问题情境,导入新课 下图像车轮状的物体是什么 图6-1,每过6分钟摩天轮就转一圈,而且图中反映了给定的时间t 与所对应的高度h 之间的关系。下面根据图6-1进行填表: 对于给定的时间t ,相应的高度h 确定吗 这个问题中的变量有几个 ,分别是什么 二、新课学习 1、 做一做 (1)瓶子或罐子盒等圆柱形的物体,常常如下图那样堆放,随着层数的增加,物体的总数是如何变化的 t/分 0 1 2 3 4 5 …… h/米 ……

填写下表: 层数n 1 2 3 4 5 … 物体总数y … (2)在平整的路面上,某型号汽车紧急刹车后仍将滑 行S 米,一般地有经验公式300 2 V S ,其中V 表示刹车前汽 车的速度(单位:千米/时) ①计算当V 为50,60,100时,相应的滑行距离S 是多少 ②给定一个V 值,你能求出相应的S 值吗 结论: 1. 上面三个问题。每个问题都研究了 个变量。 2. 函数的概念 一般地,在某个变化过程中,有两个变量 和 ,如果给定一个x 值,相应地就确定了一个y 值,那么我们称y 是x 的 ,其中x 是 ,y 是 。 三、随堂练习 书100页 随堂练习 习题 四、本课小结 1、 初步掌握函数的概念,能判断两个变量间的关系是否可看作函数。 2、 在一个函数关系式中,能识别自变量与因变量,给定自变量的值,相应地会求出函数的值。 3、 函数的三种表达式: (1) 图象;(2)表格;(3)关系式。 五探究活动 为了加强公民的节水意识,某市制定了如下用水收费标准: 每户每月的用水不超过10吨时,水价为每吨元;超过10吨时,超过的部分按每吨元收费,该市某户居民5月份用水x 吨(x >10),应交水费y 元,请用方程的知识来求有关x 和y 的关系式,并判断其中一个变量是否为另一个变量的函数

第六章 过程汇总

第六章过程 VB过程:应用程序的功能模块,有三种类型 (1)子程序过程(Sub Procedure):不返回值 (2)函数过程(Function Procedure):返回一个值 (3)属性过程(Property Procedure):返回、设置属性 6.1 函数过程的定义 除了系统提供的内部函数过程和事件过程外,用户可自定义过程: 以Sub保留字开始的为子过程; 以Function保留字开始的为函数过程。 1.函数过程的定义 自定义函数过程有两种方法: (1)利用“工具”菜单下的“添加过程”命令定义,生成一个函数的框架。 (2)利用代码窗口直接定义。 函数过程形式: Function 函数过程名([参数列表]) [As 类型] 局部变量或常数定义 语句块 函数名 = 返回值函数过程体 [Exit Function] 语句块 函数名 = 返回值 End Function 函数过程名:命名规则同变量名 参数列表形式: [ByVal]变量名[()][As 类型] 称为形参或哑元,仅表示参数的个数、类型,无值。 函数名 = 返回值在函数体内至少对函数名赋值一次。 [Exit Function] :表示退出函数过程。 2.函数过程的调用 函数过程调用同标准函数调用 形式:函数过程名([参数列表]) 参数列表:称为实参或实元,它必须与形参个数相同,位置与类型一一对应。可以是同类型的常量、变量、表达式。 6.2 子过程 函数过程的不足: (1)不是为了获得某个函数值,而是为了某种功能的处理。 (2)要获得多个结果。 编写一个两个数交换的过程供多次调用。 Swap (x,y)子过程的定义主调程序调用Swap子过程 Public Sub Swap(x, y) Private Sub Form_Click() Dim t Dim a, b t = x a = 10

第六章脉冲响应函数

第6章 脉冲响应函数的辨识 6.1辨识问题的提法 下图所示,、将作用在系统上的一切随机干扰和噪声,用一个作用于系统输出的等效随机干扰源)t (v 来代替。其中,输入信号)(u t 是过程的运行操作信号, 是可以直接观测的确定性变量;)(y u t 是过程的实际输出,是不能被观测到的;y(t) 是过程的观测输出,混有随机噪声)t (v 。 由此可以提出辨识问题: 在已知输入、输出的观测量)(u t 、y(t)以及f t (f t 可以根据脉冲响应过渡历程时间的先验知识作粗略估计)的情况下,要求估计出脉冲响应函数)(g t 。 下面介绍两种辨识脉冲响应函数的常用方法:相关分析法和最小二乘法。 6.2用相关分析法辨识脉冲响应函数 相关函数是基于一种统计的描述,是由输出信号)(y t 同其余变量之间的关系确定脉冲响应函数。假定噪声)t (v 是一个零均值平稳随机过程,并与)(u t 不相关,且过程是线性时不变的、因果性的系统,过程的未知脉冲响应函数为)(g t ,则过程的输入、输出和脉冲响应函数之间的基本关系如下: ?∞ -=0)()()(y λλλd u t g t u (6.1) ?+-=f t t v d u t g t 0 )()()()(y λλλ (6.2) 把变量t 用τ+t 代换,得 ?++-+=+f t t v d t u g t 0)()()()(y τλλτλτ (6.3) 由于已经假设)t (v 与输入信号)(u t 不相关,因此对应的相关系数0)(uv =τR ,是可得维纳-霍夫方程。 λλλτd t R g R f t uu )()()(0uy -=? (6.4) 若将(6.4)离散化,得到离散型Wiener-Holf 方程:

vb第六章过程

第六章过程(8学时) 一、教学内容 本章讨论VB6.0中Sub子过程和Function过程的定义与调用以及过程调用中数据传递的方式。 二、目的要求 通过对本章的学习,使学生掌握子过程(Sub过程的定义、调用);掌握函数过程(Function 过程)的定义、调用;了解值传递、地址传递的传递规则。 三、教学重点与难点 教学重点:1.Sub过程及Function过程的定义与调用 2.过程调用中数据的传递。 教学难点:过程调用中数据的传递。 四、教学方法 课堂教学为主。适当提问,加深学生对概念的理解。 6.1 Sub过程(2学时) 一、教学内容 本节介绍事件过程和通用过程的区别,通用过程的定义以及通用过程的调用。 二、目的要求 了解事件过程和通用过程的区别,掌握通用过程的定义以及通用过程的调用。 三、教学重点与难点 教学重点:通用过程的定义以及通用过程的调用。 教学难点:通用过程的调用 四、教学方法 课堂教学。 五、教学过程 在VB中,的Sub子过程分为:事件过程和通用过程 6.1.1 事件过程 (1)窗体事件的语法 Private Sub Form_事件名(参数列表) <语句组> End Sub (2)控件事件的语法 Private Sub 控件名_事件名(参数列表) <语句组> End Sub 6.1.2 通用过程(Sub过程)的定义 1.子过程的定义形式如下: [Public|Private][Static] Sub 子过程名([形参表]) <局部变量或常数定义> <语句组> [Exit Sub] <语句组> End Sub 说明:

(1)子过程名:命名规则与变量名规则相同。子过程名不返回值,而是通过形参与实参的传递得到结果,调用时可返回多个值。 (2)形式参数列表:形式参数通常简称“形参”,仅表示形参的类型、个数、位置,定义时是无值的,只有在过程被调用时,虚实参结合后才获得相应的值。 (3)过程可以无形式参数,但括号不能省。 (4)参数的定义形式: [ByVal|ByRef]变量名[( )][As 类型][,…], ByVal表示当该过程被调用时,参数是按值传递的;缺省或ByRef表示当该过程被调用时,参数是按地址传递的。 提问1:如何编写一个交换两个整型变量值的子过程。 2.通用过程的建立 6.1.3 过程的调用 1、用Call语句调用Sub过程 格式:Call 子过程名(参数列表) 2、把过程名作为一个语句来使用 格式:子过程名[参数列表] 说明: (1)参数列表称为实参或实元,它必须与形参保持个数相同,位置与类型一一对应。(2)调用时把实参值传递给对应的形参。其中值传递(形参前有ByVal说明)时实参的值不随形参的值变化而改变。而地址传递时实参的值随形参值的改变而改变。 (3)当参数是数组时,形参与实参在参数声明时应省略其维数,但括号不能省。 (4)调用子过程的形式有两种,用Call关键字时,实参必须加圆括号括起,反之则实参之间用“,”分隔。 提问2:如何调用提问1写出的过程? 七、作业P154 习题6.1、6.10 6.2 Function过程(2学时) 一、教学内容:本节将介绍Function过程的定义以及调用过程 二、教学重点:Function过程的定义以及调用过程 三、教学难点:Function过程的调用过程 四、教学方法:课堂教学为主,并适当提问、收集学生学习情况。 五、教学要求:掌握Function过程的定义以及调用过程 六、教学过程: Visual Basic函数分为内部函数和外部函数,外部函数是用户根据需要用Function关键字定义的函数过程,与子过程不同的是函数过程将返回一个值。 6.2.1 函数过程(Function过程)的定义 [Public|Private][Static]Function 函数名([<参数列表>])[As<类型>] <局部变量或常数定义> <语句块> [函数名=返回值] [Exit Function] <语句块> [函数名=返回值] End Function 说明:

第6章过程函数触发器和包

第6章过程函数触发器和包 6.1.1创建存储过程 例1 创建一个存储过程,该存储过程实现向dept表中插入一条记录。 create procedure pro_insertDept is begin insert into dept values(77,'市场拓展部','JILIN'); commit; dbms_output.put_line('插入新记录成功!'); endpro_insertDept; / 例2 在当前模式下,如果数据库中存在同名的存储过程,则要求按新创建的存储过程覆盖掉已存在的存储过程;如果不存在同名的存储过程,则直接创建即可。 create or replace procedure pro_insertDept is begin insert into dept values(99,'市场拓展部','BEIJING'); --插入数据记录 commit; --提交数据 dbms_output.put_line('插入新记录成功!'); --提示插入记录成功 endpro_insertDept; / 例3. 在SQL *Plus环境中,使用execute命令执pro_insertDept存储过程,具体代码如下。SQL>execute pro_insertDept; 例4.在PL/SQL块中调用存储过程pro_insertDept,然后执行这个PL/SQL块。 SQL>set serverout on SQL>begin pro_insertDept; end; / 3.1.2存储过程的参数 例5创建一个存储过程,并定义3个in模式的变量,然后将这3个变量的值插入到dept表中。create or replace procedure insert_dept( num_deptno in number, var_ename in varchar2, var_loc in varchar2) is begin insert into dept values(num_deptno,var_ename,var_loc); commit; endinsert_dept; /

第6章习题及答案

第6章过程习题及答案一、选择题 1.Sub过程与Function过程最根本的区别是: (A) 前者可以使用Call或直接使用过程名调用,后者不可以 (B) 后者可以有参数,前者不可以 (C) 两种过程参数的传递方式不同 (D) 前者无返回值,但后者有返回值 答案:D 知识点:Sub过程、Function过程 难度:1 提示:无 题解:无 2.在定义函数过程时,不可能用到的关键字是: (A) Exit (B) As (C) Sub (D) End 答案:C 知识点:Function过程 难度:1 提示:无 题解:无 3.在定义通用过程时,下列关键字中不能用来修饰形参的是: (A) ByVal (B) ByRef (C) Optional (D) Static 答案:D 知识点:Sub过程、Function过程 难度:1 提示:无

4.在同一模块中定义了两个同名的过程,以下哪一项可以让它们实现重载: (A) 返回值类型不同 (B) 参数类型不同 (C) 参数名称 (D) 参数传递方式不同 答案:B 知识点:过程重载 难度:1 提示:无 题解:无 5.以下关于递归的说明中正确的是: (A) 递归有直接递归和间接递归 (B) 递归过程可以无限次调用自己 (C) 递归过程的形参必须是按地址传递 (D) 递归过程必须有返回值 答案:A 知识点:递归 难度:1 提示:无 题解:无 6.下列定义一个Function过程的首部,语法正确的是()。 (A)Function MyFunc(ByVal i As Integer) As Integer (B)Function MyFunc(var i :Integer):Integer (C)Function MyFunc(Dim i As Integer) As Integer (D)Function Integer MyFunc() 答案:A 知识点:Function过程 难度:1 提示:无 题解:无

相关文档