In what languages can you dynamically rewrite func

2019-06-21 06:00发布

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&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)

12条回答
男人必须洒脱
2楼-- · 2019-06-21 06:35

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();
查看更多
放我归山
3楼-- · 2019-06-21 06:39

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.

查看更多
We Are One
4楼-- · 2019-06-21 06:40

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

查看更多
做个烂人
5楼-- · 2019-06-21 06:41

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

查看更多
来,给爷笑一个
6楼-- · 2019-06-21 06:42

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).

查看更多
放我归山
7楼-- · 2019-06-21 06:43

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
>>> 
查看更多
登录 后发表回答