views:

481

answers:

12

I recently had the necessity of rewriting a javascript function in javascript, dynamically. The ease with which I did it, and how fun it was, astounded me.

Over here I've got some HTML:

<div id="excelExport1234" 
     onclick="if(somestuff) location.href='http://server/excelExport.aspx?id=56789&amp;something=else'; else alert('not important');"
  >Click here to export to excel</div>

And I couldn't change the outputted HTML, but I needed to add an extra parameter to that link. I started thinking about it, and realized I could just do this:

excelExport = $('excelExport1234');
if (needParam)
  eval('excelExport.onclick = ' + excelExport.onclick.toString().replace("excelReport.aspx?id", "excelReport.aspx?extraParam=true&id") + ';');
else
  eval('excelExport.onclick = ' + excelExport.onclick.toString().replace("extraParam=true&", "") + ';');

And it worked like a champ! excelExport.onclick returns a function object which I convert to a string, and do some string manip on. Since it's now in the form of "function() { ... }", I just go back and assign it to the onclick event of the dom object. It's a little ugly having to use eval, but AFAIK there isn't a javascript function constructor that can take a string of code and turn it into an object nicely.

Anyway, my point isn't that I'm super clever (I'm not), my point is that this is cool. And I know javascript isn't the only language that can do this. I've heard that lisp has had macros for years for this exact purpose. Except to really grok macros you need to really grok lisp, and I don't grok it, I just 'kind of get it'.

So my question is: In what other languages can you (easily) dynamically rewrite functions, and can you show me a simple example? I want to see where else you can do this, and how it's done!

(also, I have no idea what to tag this as, so I took random guesses)

+1  A: 

I used to do this all the time in TCL, it was a breeze and worked wonderfully. I could investigate somethings interface over the network and then create a custom-made interface on the fly to access and control things. For example, you could make a custom SNMP interface from a generic SNMP library.

I haven't used it, but C# has some built-in support for generating it's own byte-code, which is fairly impressive.

I've done this sort of thing in C as well, but there it is non-portable and almost never worth the hassle. It is a technique used sometimes for "self-optimizing" code to generate the appropriate C function to optimally process a given data set.

Chris Arguin
In Tcl you can even redefine the built-in control structures for the ultimate in flexibility/insanity (delete according to taste) :-)
Colin Macleod
+8  A: 

LISP is the ultimate language at this. LISP functions are actual LISP lists, meaning you can manipulate LISP source code as if it were any other data structure.

Here's a very trivial example of how it works:

(define hi 
  (lambda () (display "Hello World\n")))
;; Displays Hello World
(hi)
(set! hi
      (lambda () (display "Hola World\n")))
;; Displays Hola World
(hi)

This, however, is possible in any language where functions are first-class objects. One of the most interesting showcases of the power of this syntax for LISP is in its macro system. I really don't feel I could do the topic justice, so read these links if you're interested:

http://en.wikipedia.org/wiki/Macro_(computer_science)#Lisp_macros

http://cl-cookbook.sourceforge.net/macros.html

Falaina
Lisp functions are not lists. Expressions that define function are lists, but functions are distinct type of objects.
dmitry_vk
Calling Lisp "LISP" is sooooo 20th century. :-)
Luís Oliveira
+1  A: 

Easy enough in Perl.

*some_func = sub($) {
    my $arg = shift;
    print $arg, "\n";
};
some_func('foo');

Re Sam Saffron's request:

*hello_world = sub() {
    print "oops";
};
hello_world();
*hello_world = sub() {
    print "hello world";
};
hello_world();
chaos
chaos, can you rewrite my ruby sample in Perl ? (see my answer)
Sam Saffron
Uh, the short one I hope?
chaos
i gave you a +1 but I did mean the long one :)
Sam Saffron
+2  A: 

Self-modifying code is also called degenerate code. This is generally considered a bad thing, and it used to be a goal of high-level languages to prevent it from being written easily.

This is from the wikipedia entry:

Self-modifying code is seen by some as a bad practice which makes code harder to read and maintain. There are however ways in which self modification is nevertheless deemed acceptable, such as when sub routine pointers are dynamically altered - even though the effect is almost identical to direct modification.

T.E.D.
I agree that you definitely should not do this under normal circumstances. What a maintainability nightmare. But as mentioned, it does open some really neat doors -- for instance, there are some fascinating CS applications for code that evolves to solve a problem.
Brian MacKay
This answer, does not answer the OPs question.
Sam Saffron
+3  A: 

I guess it depends on what exactly you define as "easily dynamic rewriting". For example in .Net you have the Func type and lambdas which allows you to define functions as variables or as temporary anonymous functions eg.

int[] numbers = {1, 2, 3, 4, 5};

Func<int[], int> somefunc;
if (someCondition) 
{
   somefunc = (is => is.Sum());
} else {
   somefunc = (is => is.Count());
}

Console.WriteLine(somefunc(numbers).ToString());

The above is a very contrived example of either counting the items in an array of integers or summing then using dynamically created functions subject to some arbitrary condition.

Note - Please don't point out that these things can be easily accomplished without lambdas (which they obviously can) I was simply trying to write a very simple example to demonstrate the concept in C#

RobV
+2  A: 

I think that it is the case in most of dynamic languages. Here is an example in Python

def f(x):
    print x

def new_function(x): print "hello", x

f("world")    
f = new_function
f("world")

The output is

world
hello world

I think that such technique should be used carefully

luc
Don't such thing frustrate the JIT? It is stuff that is fine for interpreters but not good for JITs, since essentially they are compilers and need special handling for this
Marco van de Voort
+2  A: 

Scheme allows you to do that.

(define (salute-english name) (display "Hello ") (display name))
(define (salute-french nom) (display "Salut ") (display nom))

Now you redefine a fonction by assigning the salute variable to the right function, either salute-english or salute-french, like this:

(define salute salute-english)

(define (redefined-the-salute-function language)
  (if (eq? language 'french)
      (set! salute salute-french)
      (set! salute salute-english)))

More generaly functional programming language allows you to do that or as functions are first class value. Functions can be manipulated, passed around, sometimes assigned to variables and so on. The list then include: Lisp, Scheme, Dylan, OCaml and SML. Some languages having first class functions includes Python, Ruby, Smalltalk and i think Perl.

Note that when you have an interactive language where you can interactively type your program, the redefinition of functions/methods must be possible: the REPL has to be able to do that, just in case you happen to retype the definition of an already defined functions.

Pierre
A: 

In PLSQL:

create or replace procedure test
as
begin
 execute immediate '
create or replace procedure test2
as
begin
  null;
end;
 ';
end;
/
FerranB
+1  A: 

You could do it in C++, but it wouldn't be easy, safe, or recommended.

  1. Generate the text of the source code
  2. invoke the compiler (fork & exec) to build a dynamic library. In gcc, you can pass the source code you want to compile on standard input, it doesn't have to be in a file.
  3. Load the library (LoadLibrary() on windows, dlopen() on linux)
  4. get a function pointer to whatever function you want (GetProcAddress() on windows, dlsym() on linux)
  5. If you want to replace an existing function, if it's a virtual function you could modify the v-table to point to the new function (that part especially is a horrible idea fraught with peril). The location of the v-table or the format of it isn't part of the C++ standard, but all the toolchains I've used have been consistent within themselves, so once you figure out how they do it, it probably won't break.
KeyserSoze
A: 

Here's something else in Python (in addition to luc's answer), which I am not recommending, but just to show it - there is exec, which can execute a string which you could build to be whatever code...

I/O shown here is from a Python 2.5.2 interpreter session. Just some simple examples of constructing strings to execute from substrings (>>> is the interpreter prompt)...

>>> def_string = 'def my_func'
>>> param_string_1 = '():'
>>> param_string_2 = '(x):'
>>> do_string_1 = '  print "Do whatever."'
>>> do_string_2 = '  print "Do something with", x'
>>> do_string_3 = '  print "Do whatever else."'
>>> do_string_4 = '  print "Do something else with", x'
>>> def_1 = '\n'.join([def_string+param_string_1, do_string_1, do_string_3])
>>> print def_1
def my_func():
  print "Do whatever."
  print "Do whatever else."
>>> exec def_1
>>> my_func()
Do whatever.
Do whatever else.
>>> def_2 = '\n'.join([def_string+param_string_2, do_string_2, do_string_4])
>>> print def_2
def my_func(x):
  print "Do something with", x
  print "Do something else with", x
>>> exec def_2
>>> my_func('Tom Ritter')
Do something with Tom Ritter
Do something else with Tom Ritter
>>>
Anon
A: 

Trivial in Ruby:

def hello_world; puts "oops"; end
hello_world
# oops
def hello_world; puts "hello world"; end
hello_world
# hello world

Of course that example is boring:

require "benchmark"
# why oh _why 
class Object
  def metaclass; class << self; self; end; end
  def meta_eval &blk; metaclass.instance_eval &blk; end
end

class Turtle
end

def make_it_move(klass)
  klass.send(:define_method, :move) { |distance|
    puts "moving #{distance} meters"
    sleep(0.1 * distance)
  }
end

make_it_move(Turtle)

turtle = Turtle.new
turtle.move(1)
# moving 1 meters

def profile(instance, method)
  instance.meta_eval do
    m = instance_method(method)
    define_method method do |*a|
      puts "Benchmarking #{instance.class} #{method}"
      puts Benchmark.measure {
        m.bind(instance).call(*a)
      }
    end
  end
end

profile(turtle, :move)

turtle.move(10)
# Benchmarking Turtle move
# moving 10 meters
#  0.000000   0.000000   0.000000 (  1.000994)


Turtle.new.move(3)
# moving 3 meters

The code above:

  1. Defines a blank class
  2. Adds a method to it
  3. Grabs an instance
  4. Intercepts that method on that instance only
Sam Saffron
A: 

Changing what a function does is supported in a lot of languages, and it's not as complicated as you might think. In functional languages, functions are values, and function names are symbols that are bound to them like any variable. If the language allows you to reassign the symbol to a different function, this is trivial.

I think the more interesting features are the ability to get the source code for a function (toString above) and to create a new function from a string (eval in this case).

Jay Conrod