CSC/ECE 517 Summer 2008/wiki1 7 ev: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 108: Line 108:


   // Create an array for the function name and function definition
   // Create an array for the function name and function definition
   StringBuffer[] function1 = new StringBuffer[10];
   StringBuffer[] function1 = new StringBuffer[10]; // We could have more than one
   StringBuffer[] function2 = new StringBuffer[10];
   StringBuffer[] function2 = new StringBuffer[10]; // We could have more than one
   
   
   // Dynamically create/define function
   // Dynamically create/define function

Revision as of 02:49, 2 June 2008

Introduction

  • A

Pros and cons

As with any feature there is a price to pay for the benefits.

Pros

  • Dynamic Metaprogramming Capability
  • Flexibilility
  • Ease of Use

Cons

  • Performance
  • Security

Ruby Example

The eval function can be used for dynamically calling functions. For example in Ruby:

  # Create an array of functions
  functions = ['function1','function2','function3']
  
  # Define functions
  def function1()
      puts "inside function1"
  end 

  def function2()
     puts "inside function2"
  end 

  def function3()
     puts "inside function3"
  end 

  # Factory Pattern
  def CallFunction(functionname)
     eval functionname
  end 

  #Results
  irb(main):039:0> CallFunction functions[0]
  inside function1
  => nil
  irb(main):040:0> CallFunction functions[1]
  inside function2
  => nil
  irb(main):041:0> CallFunction functions[2]
  inside function3
  => nil

What makes this so powerful is that the function names in the array can be stored in an array or someplace else like a database or xml file.

Taking this one step further we can store the function definition in an array as well:

  #Create an array for the function name and function definition
  function1 = ['function4'] # We could have more then one
  function2 =['def function4 ()  puts "inside function4" end'] # We could have more then one
  
  # Dynamically create/define function
  eval function2[0]
  
  # Dynamically call the the name of the function
  irb(main):060:0> eval function1[0]
  inside function4
  => nil

So, in this example function4() is created dynamically at run-time. This allows us to store parts of the code as data and to create functions when needed. An application written using eval to dynamically generate functions would allow new functions to be added easily. For example, you could create new definitions of functions and insert them into a database table.

Java Example

The base Java language does not have a direct equivalent to Ruby's eval() facility, because Java is a compiled, statically typed language. However, Java environments can use a facility similar to Ruby's eval() through the BeanShell addon, available from http://beanshell.org/bsh-2.0b4.jar.

Because a Java program can create instances of the BeanShell interpreter, and submit arbitrary Java code to the interpreter for evaluation at run time, Java developers can take advantage of BeanShell's eval facility to create programs that create and execute new programs on the fly.

A BeanShell interpreter object retains state across invocations, so that previously evaluated classes, objects, methods, and variables are available to classes, objects, methods, and variables that are evaluated later in the lifetime of each BeanShell instance.

BeanShell is distributed as an executable jar, which when run, provides a BeanShell workspace in which Java code can be developed in a command line environment. To view the output from the code below in the BeanShell Workspace, the user must invoke "File->Capture System in/out/err" from the "Bsh Workspace" menu, before running the code.

  import java.lang.StringBuffer;  // needed for mutable strings

  // Create an array for function names
  StringBuffer[] functions = new StringBuffer[4];

  // Define functions
  void function1() {System.out.println("inside function1");}
  void function2() {System.out.println("inside function2");}
  void function3() {System.out.println("inside function3");}

  // Factory Pattern
  void CallFunction (functionname) {eval(functionname + "();");}

  // Initialize function names
  functions[0] = new StringBuffer("function1");
  functions[1] = new StringBuffer("function2");
  functions[2] = new StringBuffer("function3");

  // Results
  bsh % CallFunction (functions[0]);
  inside function1
  bsh % CallFunction (functions[1]);
  inside function2
  bsh % CallFunction (functions[2]);
  inside function3
  bsh % 

As in the Ruby example, the function names in the array can be stored in an array, or someplace else like a database or xml file.

In addition, similar to the Ruby example, we can store the function definition in an array as well:

  // Create an array for the function name and function definition
  StringBuffer[] function1 = new StringBuffer[10]; // We could have more than one
  StringBuffer[] function2 = new StringBuffer[10]; // We could have more than one

  // Dynamically create/define function
  function1[0] = new StringBuffer("function4");

  // Dynamically call the the name of the function
  bsh % function2[0] = new StringBuffer("void function4() {System.out.println(\"inside 
  function 4\");}");
  bsh % eval(function2[0].toString());
  bsh % CallFunction (function1[0]);
  inside function 4
  bsh %

As in the Ruby example, in this Java example using BeanShell eval(), function4() is created dynamically at run-time. This allows us to store parts of the code as data and to create functions when needed. An application written using eval to dynamically generate functions would allow new functions to be added easily. For example, you could create new definitions of functions and insert them into a database table.

Links

Wikipedia::Eval

link title

Inspecting a Live Ruby Process

link title

link title

Java Expression Evaluator

link title

link title

link title

BeanShell

Calling BeanShell from Java

link name

link name

link name

link name

link name

link name

link name

link name

link name