Groovy Functions!

Groovers,

I wanted to hack up a way where i could type some groovy code

in a text box and have it compute math functions on arrays of numbers.

Is the code below the best way to do this?

The groovy tutorial is a bit "thin" (to use yawmarks words) in explaining

the ways to get this done.

For those new to Groovy, catch up quickly:

Download

http://groovy.codehaus.org/Download

Install

http://groovy.codehaus.org/Installing+Groovy

Compile + Run Code Below w/ Classpath

-classpath .;"C:\...\groovy-1.0\embeddable\groovy-all-1.0.jar"

Embedding + BSF Tutorial

http://groovy.codehaus.org/Embedding+Groovy

http://groovy.codehaus.org/Bean+Scripting+Framework

About the code:

I dont know how to create and return double arrays in groovy so

i just return a double to test the code : /

For streamlining its possible to wrap the users code in the Class +

Method like:

String code = "public class X implements... " + code + " } \n } ";

but i left that in for clarity.

import javax.swing.*;

import javax.swing.event.*;

import java.awt.*;

import java.awt.event.*;

import groovy.lang.*;

publicclass GroovyTesterimplements ActionListener{

publicstaticvoid main(String[] args){

new GroovyTester();

}

public GroovyTester(){

guiSetup();

}

publicvoid guiSetup(){

numberField =new JTextField("1.0");

numberField.addActionListener(this);

groovyBox =new JTextArea(CODE);

scrollPane =new JScrollPane(groovyBox);

answerField =new JTextField();

contentPane =new JPanel();

contentPane.setLayout(new BorderLayout(2, 1));

contentPane.add(numberField, BorderLayout.NORTH);

contentPane.add(scrollPane, BorderLayout.CENTER);

contentPane.add(answerField, BorderLayout.SOUTH);

window =new JFrame();

window.setContentPane(contentPane);

window.setSize(400, 400);

window.setLocationRelativeTo(null);

window.setVisible(true);

}

publicvoid actionPerformed(ActionEvent e){

if(e.getSource() == numberField){

processFunction();

}

}

publicvoid processFunction(){

Computation c = loadGroovyFunction();

if(c !=null){

double[] values = inputArray();

if(values.length > 0){

double answer = c.compute(values);

answerField.setText("answer: " + answer);

}else{

answerField.setText("no input");

}

}else{

answerField.setText("error");

}

}

publicdouble[] inputArray(){

String[] input = numberField.getText().split("\\s*[, ]\\s*");

for(int i = 0; i < input.length; i++){

System.out.println("Input #" + (i+1) +": '" + input[i] +"'");

}

double[] values =newdouble[input.length];

for(int i = 0; i < input.length; i++){

try{

values[i] = Double.parseDouble(input[i]);

}catch(Exception e){

values[i] = 0;

}

}

return values;

}

public Computation loadGroovyFunction(){

try{

ClassLoader parent = getClass().getClassLoader();

GroovyClassLoader gcl =new GroovyClassLoader(parent);

String groovyCode = groovyBox.getText();

Class clazz = gcl.parseClass(groovyCode);

Object object = clazz.newInstance();

return (Computation)object;

}catch(Exception e){

e.printStackTrace();

returnnull;

}

}

publicstaticinterface Computation{

publicdouble compute(double[] values);

}

JFrame window;

JPanel contentPane;

JTextField numberField;

JScrollPane scrollPane;

JTextArea groovyBox;

JTextField answerField;

publicstaticfinal String CODE =

"\npublic class X implements GroovyTester.Computation{\n"+

"\n" +

"public double compute(double[] values){\n" +

"return values[0] * 2;\n" +

"}\n" +

"\n" +

"}\n";

}

[7662 byte] By [TuringPesta] at [2007-11-27 11:28:33]
# 1

> Is the code below the best way to do this?

Have you considered just using the Groovy console?

http://groovy.codehaus.org/Groovy+Console

> I dont know how to create and return double arrays in groovy

doubleArray = [1.2, 3.4, 5.6]

assert doubleArray == [1.2, 3.4, 5.6]

~

yawmarka at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 2

Hey thanks.

If the console is what I think it is it wont work for what im doing.

I want to use this inside an audio program im writing as an effects

module. I can try out different functions and algorithms without

having to recompile the program.

As my inability to create an array shows, i still have quite a bit of

groovy learning to do first...: )

TuringPesta at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 3

As I read it, you're looking for a way to execute arbitrary code at runtime. If that's not what you're looking for, then I missed it. If it *is* what you're looking for, dig in to the Groovy console. The following article may also help:

http://iterative.com/blog/2007/05/14/embedding-a-groovy-console-in-a-java-server-application

~

yawmarka at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 4

>> As I read it, you're looking for a way to execute arbitrary code at runtime.

*bingo*

>> The following article may also help

reading it now. thankx.

TuringPesta at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 5

You cats are the Groovyest.

I haven't even peeked at it yet.

%

duffymoa at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 6

> You cats are the Groovyest.

>

> I haven't even peeked at it yet.

Now that you're the SpringMaster, you should give it a run. Groovy works just fine with Spring, too. ;o)

Here's a good, quick little overview:

http://www.ibm.com/developerworks/library/j-pg09196.html

~

yawmarka at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 7

Is there a way to "unload" a class?

the groovyclassloader docs dont specify a way

http://groovy.codehaus.org/api/groovy/lang/GroovyClassLoader.html

And for the "Class parseClass(String text)" method they dont specify

what happens when you reload the same class over and over.

Is it saving every version of the class in memory or is the garbage

collector removing the old ones?

TuringPesta at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 8

If it works like in Ruby the class when reloaded replaces the previous version.

What happens to existing instances of that class already in memory I've not gotten around to trying (but I expect it won't be pretty).

And no, I've not gotten around to Groovy either. For now I'm still trying to figure out what the Ruby hype is all about, and at my age I can only analyse one hype at a time :)

jwentinga at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 9

> Is there a way to "unload" a class?

Not that I'm aware of, but that doesn't mean much.

~

yawmarka at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 10

Anyone have any clue why this line doesnt work

when typed into the "groovy box":

double[] result = new double[]{ 1, 2, 3 };

this works:

double[] result = [ 1, 2, 3 ];

double[] result = new double[3];

i prefer the "=[1,2,3]" way, but i thought groovy accepted valid

java code?

TuringPesta at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 11

> Anyone have any clue why this line doesnt work

> when typed into the "groovy box":

>

> double[] result = new double[]{ 1, 2, 3 };

Yes, that's not valid Groovy syntax. Note that "d = [1, 2, 3]" doesn't declare a double array. It declares a list.

d = [1, 2, 3]

assert d instanceof ArrayList

> i prefer the "=[1,2,3]" way, but i thought groovy accepted valid

> java code?

No, Groovy is a different language. The syntax is similar, but it's not the same.

~

yawmarka at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 12

well i guess the thing that is throwing me off (aside from

not RTFM, lol) is that this:

result = [1,2,3];

does NOT work. only:

double[] result = [1,2,3];

works. so is it a list, is it a double[], is it java, is it groovy, lol?

wtf is going on?

EDIT: ah, i was missing the elusive "def" keyword!

http://groovy.codehaus.org/Collections

TuringPesta at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 13

> well i guess the thing that is throwing me off (aside

> from

> not RTFM, lol) is that this:

>

> result = [1,2,3];

>

> does NOT work.

Sure it does.

result = [1, 2, 3]

assert result == [1, 2, 3]

What problem are you having?

> EDIT: ah, i was missing the elusive "def" keyword!

> http://groovy.codehaus.org/Collections

The def keyword isn't strictly necessary here.

~

yawmarka at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 14

Well, the tutorials give a lot of the code as you would script with

Groovy but I guess its slightly different for the classes.

Because:

result = [1, 2, 3]

assert result == [1, 2, 3]

does NOT work.

public class X implements GroovyTester.Computation{

public double compute(double[] values){

result = [1,2,3];

// assert result == [1, 2, 3];

return 1;

}

}

Throws this error:

Exception in thread "AWT-EventQueue-0" groovy.lang.MissingPropertyException:

No such property: result for class: X

"def" fixes it though.

Why is all the tutorial code littered with asserts?

TuringPesta at 2007-7-29 16:22:44 > top of Java-index,Java Essentials,Java Programming...
# 15

> I guess its slightly different for the classes.

Ah, sorry. I didn't know you were trying to define it as a local variable. Here's an example, without the need for all the extra declarations:

d = [1, 2.3, 4]

assert 7.3 == new X().compute(d)

class X {

public double compute(values) {

double result = 0

values.each { result += it }

return result

}

}

> Why is all the tutorial code littered with asserts?

Inline testing.

~

yawmarka at 2007-7-29 16:22:49 > top of Java-index,Java Essentials,Java Programming...
# 16

Wow. It works great. This is so much fun!

public double[] compute(double[] values){

def square = { it * it }

def result = [1,2,3]

result.each{ println "Item: $it" }

result = result.collect(square)

result.each{ println "Item: $it" }

return [1]

}

Is there a collect(closure) function for Lists that will change the values

in place instead of returning a new array?

TuringPesta at 2007-7-29 16:22:49 > top of Java-index,Java Essentials,Java Programming...
# 17

> Wow. It works great. This is so much fun!

Out of curiosity, why are you bothering with defining a method in a class at all?

> Is there a collect(closure) function for Lists that will change the values in place instead of returning a new array?

Not to my knowledge, no.

~

yawmarka at 2007-7-29 16:22:49 > top of Java-index,Java Essentials,Java Programming...
# 18

I just want to write a chunk of code and have it process

an array of numbers - over and over and over again.

I figured that loading the code as a class would be faster than

evaluating a GroovyScript over and over.

Dude, im all new to this so i have no clue. You've sugggested

the groovy console a few times and i read that article you posted but

that seems like overkill. Theres XML and networking involved...

The GroovyScriptEngine and GroovyObject loader require a Script

file but it'd be annoying to save off a new file every time you make a

small change to the code.

Plus the GroovyClassLoader already comes with a parseClass

method for loading Java and Groovy source from a String instead

of a File.

http://groovy.codehaus.org/api/groovy/lang/GroovyClassLoader.html

I believe the GroovyShell (from the tutorial page) reparses and

evaluates a script provided as a String every time it is run.

For complicated algorithms that might be too much.

What do you have in mind?

http://groovy.codehaus.org/Embedding+Groovy

TuringPesta at 2007-7-29 16:22:49 > top of Java-index,Java Essentials,Java Programming...
# 19

> why are you bothering with defining a method in a class at all?

actually, the short answer may be that the tutorial told me to,

so i can use it as an Interface:

Class groovyClass = loader.parseClass(code);

GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();

Object[] args = {};

groovyObject.invokeMethod("run", args);

versus

Class clazz = gcl.parseClass(code);

Object aScript = clazz.newInstance();

MyInterface myObject = (MyInterface) aScript;

myObject.interfaceMethod();

TuringPesta at 2007-7-29 16:22:49 > top of Java-index,Java Essentials,Java Programming...
# 20

> What do you have in mind?

It just depends on what you want to do. You integrate the Groovy Shell, the Groovy Console, Groovy Script objects, etc.

Example:s = '''

def mass = 22.3

def velocity = 10.6

mass * velocity**2 / 2

'''

def kineticEnergy = evaluate(s)

assert kineticEnergy == 1252.814

> Dude, im all new to this so i have no clue.

Then don't start with some huge project. Give yourself time to play around.

~

yawmarka at 2007-7-29 16:22:49 > top of Java-index,Java Essentials,Java Programming...
# 21

>> Then don't start with some huge project. Give yourself time to play around.

I am playing! : )

I just got VSTs working in my audio program pet project.

This groovy class loading will let me write sounds in program.

Im very excited!

TuringPesta at 2007-7-29 16:22:49 > top of Java-index,Java Essentials,Java Programming...