2006-8-27
				
		
		
				
						
						
								 
						
				
		
		
				
						Perl
				
				作为一种脚本语言可以实时地生成和执行代码。这种特性可以把代码的编译推迟到运行时,所以又称为“动态代码”。另外,
				
						Perl
				
				也如
				
						Java
				
				、
				
						C++
				
				一样提供了异常处理机制。本文将初步探讨
				
						Perl
				
				中实现动态代码和异常处理机制的函数:
				
						eval
				
				。如有错误不足,欢迎讨论和批评指正。
		
		
				
						
								 
						
				
		
		
				
						eval
				
				函数可以看作是
				
						Perl
				
				虚拟机,它的参数就是一段
				
						Perl
				
				代码。利用
				
						’perldoc –f eval’
				
				可以获取
				
						eval
				
				函数使用帮助,其中介绍了它的两种使用方式:
		
		
				
						
								 
						
				
		
		
				
						l         
				
				
						eval EXPR
				
		
		
				
						EXPR
				
				是一个的表达式,例如:
		
		
				eval
				
				
				"print $a"
				;
				
						
						
				
		
		
				eval
				
				
				'print $a'
				 . 
				', $b'
				;
				
						
						
				
		
		
				eval
				
				
				1
				
				
				+
				
				
				3
				;
				
						
						
				
		
		
				eval
				
				
				'print '
				 . 
				'$a + $b, "\n"'
				;
				
						
						
				
		
		
				eval
				
				
				$command;#$command = ‘print “hello Perl”’
		
		
				eval
				
				
				$ARGV[0];
		
		
				在执行时,
				
						Perl
				
				解释器会首先解析表达式的值,然后将表达式值作为一条
				
						Perl
				
				语句插入当前执行上下文。所以,新生成的语句与
				
						eval
				
				语句本身具有相同的上下文环境。这种方式中,每次执行
				
						eval
				
				语句,表达式都会被解析。所以,如果
				
						eval EXPR
				
				如果出现在循环中,表达式可能会被解析多次。
				
						eval
				
				的这种方式使得
				
						Perl
				
				脚本程序能实时生成和执行代码,从而实现了“动态代码”。
		
		
				
						
								 
						
				
		
		
				
						l         
				
				
						eval BLOCK
				
		
		
				
						BLOCK
				
				是一个代码块,例如:
		
		
				
						eval {print $a};
				
		
		
				
						eval {$a = 1, $b = 2, $c = $a + $b};
				
		
		
				与第一种方式不同,
				
						BLOCK
				
				只会被解析一次,然后整个插入当前
				
						eval
				
				函数所在的执行上下文。由于解析上的性能的优势,以及可以在编译时进行代码语法检查,这种方式通常被作为
				
						Perl
				
				用来为一段代码提供异常捕捉机制,虽然前一种方式也可以。
		
		
				
						
								 
						
				
		
		
				按帮助的名称,称
				
						eval
				
				的参数程序为“小程序”
				
						(mini-proggram)
				
				。在两种方式中,
				
						eval
				
				函数的返回值都是小程序的最后一条语句的值,如果遇到
				
						return
				
				语句,与子例程相同。
		
		
				
						
								
										| 
														
																
																		Script1:
																
														
												 
														#!/usr/bin/perl -w
														
																
																
														
												 
														
																 
														
												 
														push
														(
														@program,'$i = 1;');
														
																
																
														
												 
														push
														(
														@program,'$i = 3; $j = 2; $k = $i + $j');
														
																
																
														
												 
														push
														(
														@program, '$i = 3; return 24; $k = $i + $j');
														
																
																
														
												 
														
																 
														
												 
														foreach
														
														
														$exp (@program)
														
																
																
														
												 
														{
														
																
																
														
												 
														
																    
														
														$rtn =eval($exp);
														
																
																
														
												 
														
																    
														
														print
														
														
														$rtn,"\n";
														
																
																
														
												 
														}
														
																
																
														
												 
														
																
																		Output:
																
														
												 
														1
												 
														5
												 
														24
														
																
																
														
												 | 
						
				
		 
		
				
						
								 
						
				
		
		
				如果小程序中有语法错误、运行时错误遇到
				
						die
				
				语句,
				
						eval
				
				将返回
				
						undef
				
				。错误码被保存在
				
						$@
				
				中。
		
		
				
						
								
										| 
														
																
																		Script2:
																
														
												 
														#!/usr/bin/perl -w
														
																
																
														
												 
														
																 
														
												 
														push
														(
														@program, '$i = 3; die "error message"; $k = $i + $j');
														
																
																
														
												 
														
																 
														
												 
														foreach
														
														
														$exp (@program)
														
																
																
														
												 
														{
														
																
																
														
												 
														
																    
														
														$rtn =eval($exp);
														
																
																
														
												 
														
																    
														
														if
														(
														!
														defined
														(
														$rtn))
														
																
																
														
												 
														
																    
														
														{
														
																
																
														
												 
														
																       
														
														print
														
														
														"Exception: "
														, 
														$@,"\n";
														
																
																
														
												 
														
																    
														
														}
														
																
																
														
												 
														
																    
														
														else
														
																
																
														
												 
														
																    
														
														{
														
																
																
														
												 
														
																       
														
														print
														
														
														$rtn,"\n";
														
																
																
														
												 
														
																    
														
														}
														
																
																
														
												 
														}
														;
														
																
																
														
												 
														
																 
														
												 
														
																
																		Output:
																
														
												 
														Exception: error message at (eval 1) line 1.
														
																
																
														
												 
														
																
																		 
																
														
												 | 
						
				
		 
		
				
						
								 
						
				
		
		
				
						
								| 
												
														
																Script3:
														
												
										 
												#!/usr/bin/perl -w
												
														
														
												
										 
												
														 
												
										 
												# a run-time error
												
														
														
												
										 
												eval
												
												
												'$answer ='
												;   
												# sets $@
												
														
														
												
										 
												warn
												
												
												$@ if$@;
												
														
														
												
										 
												
														
																 
														
												
										 
												
														
																Output:
														
												
										 
												syntax error at (eval 1) line 2, at EOF
												
														
														
												
										 |