
Linguagens dinâmicas apresentam várias vantagens sobre as linguagens compiladas. Uma dessas vantagens é a habilidade de adicionar código em tempo de execução com facilidade. Por exemplo, imagine um servidor que de alguma forma receba e processe comandos. Num ambiente Java (onde o servidor é um programa Java assim como os comandos são objetos Java) é um certo malabarismo com o Classloader para fazer isso.
http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html?page=2
Enquanto que esse dinamismo é ainda “sustentável” para Classes, a situação é mais complicada para fragmentos de código. Nesse caso é preciso compilar uma classe Java e carregá-la. Com Javascript, a situação é outra. Uma vez que a linguagem é interpretada, é simplesmente trivial adicionar fragmentos de código. Para provar isso vou implementar um programa que imprime gráficos, para funções arbitrárias de uma variável x “real” (aliás, radicalmente arbitrárias... não irei nem mesmo validar se a entrada é de fato uma função).
Inicialmente definimos uma interface para a função. Não queremos que o código cliente seja impregnado com detalhes técnicos do funcionamento do javax.script. Queremos definir a interface mais simples possível sem comprometer o desempenho da aplicação.
1 2 3 4 5 | public interface Function { double [] function( double xInit, double xfinal, double step); public double function( double x); } |
Agora faremos teste com uma função bem conhecida x^2 (ou f(x) = x*x). Aqui o teste unitário da função:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * Test of function method, of class RhinoCalc. */ @Test public void functionXQuadrado() throws Exception { setFunction(); double xInit = 0.0 ; double xfinal = 10.0 ; double step = 1 ; double [] result = function.function(xInit, xfinal, step); assertTrue(Arrays.equals( new double [] { 0 , 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 , 0 }, result)); for ( int i = 0 ; i < result.length; i++) { System.out.println(result[i]); } } |
1 2 3 4 | public RhinoFunction() { ScriptEngineManager mgr = new ScriptEngineManager(); jsEngine = mgr.getEngineByName( "JavaScript" ); } |
1 2 3 4 | public void setFunction(String function) throws ScriptException { jsEngine.eval( "function f(x) { \n" + " return " + function + ";}" ); invocableEngine = (Invocable) jsEngine; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public double function( double x) { try { return (Double) invocableEngine.invokeFunction( "f" , x); } catch (Exception e) { Logger.getLogger(RhinoFunction. class .getName()).log(Level.SEVERE, null , e); throw new RuntimeException(e); } } public double [] function( double xInit, double xfinal, double step) { double deltaX = xfinal - xInit; int size = ( int ) Math.ceil(deltaX / step); double [] result = new double [size + 1 ]; int i = 0 ; for ( double x = xInit; x < xfinal; x += step, i++) { try { result[i] = (Double) invocableEngine.invokeFunction( "f" , x); } catch (Exception ex) { Logger.getLogger(RhinoFunction. class .getName()).log( Level.SEVERE, null , ex); throw new RuntimeException(ex); } } return result; } |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | private void plotButtonActionPerformed(java.awt.event.ActionEvent evt) { CartesianPanel painel = (CartesianPanel) this .graphicPanel; try { rhinoFunction.setFunction(polinomioTextField.getText()); } catch (ScriptException e) { e.printStackTrace(); JOptionPane .showMessageDialog( this , "O interpretador não conseguiu interpretar a função escrita." , "Função Inválida" , JOptionPane.ERROR_MESSAGE); } painel.setFunction(rhinoFunction); double initialX = Double.parseDouble(initialXTextField.getText()); double finalX = Double.parseDouble(xFinalTextField.getText()); double initialY = Double.parseDouble(initialYTextField.getText()); double finalY = Double.parseDouble(finalYTextField.getText()); painel.getCartesianPlan().setDimension(initialX, finalX, initialY, finalY); painel.repaint(); } |
Comentários
1 - O q vc tem contra o <pre>?
2 - Nessa linha:
CartesianPanel painel = (CartesianPanel) this.graphicPanel;
Pq o cast?
3 - Tem algum easter egg? ;-)
...
Respondendo
1) Acho que o pre não fica bom, não sei. Queria que ficasse colorido como no eclipse.
2) Essa é fácil:
Se eu não usasse o cast não poderia fazer isso depois:
painel.setFunction(rhinoFunction);
3) Ainda não tenho easter egg. :(