2009-07-13 14 views
5

मुझे हाल ही में जावास्क्रिप्ट में गतिशील रूप से जावास्क्रिप्ट फ़ंक्शन को फिर से लिखने की आवश्यकता थी। जिस तरह से मैंने इसे किया, और यह कितना मजेदार था, मुझे आश्चर्यचकित कर दिया।आप किन भाषाओं पर गतिशील रूप से कार्यों को फिर से लिख सकते हैं?

यहाँ से अधिक मैं कुछ 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> 

और मैं outputted एचटीएमएल बदल नहीं सकता है, लेकिन मुझे लगता है कि लिंक के लिए एक अतिरिक्त पैरामीटर जोड़ने की जरूरत है। मैं इसके बारे में सोचना शुरू कर दिया, और महसूस किया मैं तो बस ऐसा कर सकता है:

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&", "") + ';'); 

और यह एक विजेता की तरह काम किया! excelExport.onclick एक फ़ंक्शन ऑब्जेक्ट देता है जिसे मैं एक स्ट्रिंग में परिवर्तित करता हूं, और कुछ स्ट्रिंग मैनिप करता हूं। चूंकि यह अब "फ़ंक्शन() {...}" के रूप में है, इसलिए मैं वापस जाता हूं और इसे डोम ऑब्जेक्ट की ऑनक्लिक घटना में असाइन करता हूं। यह eval का उपयोग करने के लिए थोड़ा बदसूरत है, लेकिन AFAIK एक जावास्क्रिप्ट फ़ंक्शन कन्स्ट्रक्टर नहीं है जो कोड की एक स्ट्रिंग ले सकता है और इसे अच्छी तरह से किसी ऑब्जेक्ट में बदल सकता है।

वैसे भी, मेरा मुद्दा यह नहीं है कि मैं सुपर चालाक हूं (मैं नहीं हूं), मेरा मुद्दा यह है कि यह अच्छा है। और मुझे पता है कि जावास्क्रिप्ट एकमात्र ऐसी भाषा नहीं है जो यह कर सकती है। मैंने सुना है कि इस सटीक उद्देश्य के लिए लिस्प में वर्षों से मैक्रोज़ हैं। वास्तव में ग्रोक मैक्रोज़ को छोड़कर आपको वास्तव में गड़बड़ करने की ज़रूरत है, और मैं इसे ग्रोक नहीं करता हूं, मैं बस इसे प्राप्त करता हूं।

तो मेरा प्रश्न है: अन्य भाषाओं में आप (आसानी से) गतिशील रूप से कार्यों को फिर से लिख सकते हैं, और क्या आप मुझे एक साधारण उदाहरण दिखा सकते हैं? मैं देखना चाहता हूं कि आप यह कहां कर सकते हैं, और यह कैसे किया जाता है!

(भी, मुझे नहीं पता क्या के रूप में इस टैग करने के लिए है, तो मैं यादृच्छिक अनुमान लिया)

+7

इस तरह पागलपन है। – skaffman

+0

शायद समुदाय विकी? – ChristopheD

+0

मैंने कभी नहीं कहा कि यह करने के लिए सबसे सुंदर बात थी, लेकिन यह बहुत अच्छा है। यह सबसे कम twiddling हैक्स की तरह है - खतरनाक कारण वे संकलक कार्यान्वयन और इस तरह, लेकिन अभी भी चालाक और दिलचस्प पर भरोसा कर सकते हैं। –

उत्तर

1

मैं TCL में यह सब समय करते थे, यह एक हवा थी और शानदार काम किया। मैं नेटवर्क पर somethings इंटरफ़ेस की जांच कर सकता हूं और फिर चीजों को एक्सेस और नियंत्रित करने के लिए फ्लाई पर कस्टम-निर्मित इंटरफ़ेस बना सकता हूं। उदाहरण के लिए, आप एक सामान्य एसएनएमपी लाइब्रेरी से एक कस्टम एसएनएमपी इंटरफ़ेस बना सकते हैं।

मैंने इसका उपयोग नहीं किया है, लेकिन सी # में अपने स्वयं के बाइट-कोड उत्पन्न करने के लिए कुछ अंतर्निहित समर्थन है, जो काफी प्रभावशाली है।

मैंने सी में इस तरह की चीज भी की है, लेकिन वहां यह गैर पोर्टेबल है और लगभग परेशानी के लायक नहीं है। यह कभी-कभी किसी दिए गए डेटा सेट को संसाधित करने के लिए उपयुक्त सी फ़ंक्शन उत्पन्न करने के लिए "स्वयं-अनुकूलन" कोड के लिए उपयोग की जाने वाली तकनीक है।

+1

Tcl में आप भी फिर से परिभाषित कर सकते हैं में निर्मित लचीलापन/पागलपन में परम के लिए नियंत्रण ढांचे (स्वाद के अनुसार हटाना) :-) –

9

LISP इस पर परम भाषा है। LISP फ़ंक्शन वास्तविक LISP सूचियां हैं, जिसका अर्थ है कि आप LISP स्रोत कोड में हेरफेर कर सकते हैं जैसे कि यह कोई अन्य डेटा संरचना थी।

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

लेकिन यह किसी भी भाषा जहां कार्यों प्रथम श्रेणी वस्तुओं रहे हैं में संभव है:

यह ऐसे काम करता का एक बहुत ही तुच्छ उदाहरण है। LISP के लिए इस वाक्यविन्यास की शक्ति के सबसे दिलचस्प प्रदर्शनों में से एक अपने मैक्रो सिस्टम में है। मैं वास्तव में मैं विषय न्याय कर सकता है महसूस नहीं है, इसलिए इन कड़ियों को पढ़ने अगर आप रुचि रखते हैं: पर्ल में पर्याप्त

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

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

+1

लिस्प कार्यों सूचियों नहीं हैं। अभिव्यक्तियां जो फ़ंक्शन को परिभाषित करती हैं वे सूचियां हैं, लेकिन फ़ंक्शन अलग-अलग प्रकार की ऑब्जेक्ट्स हैं। –

+5

कॉलिंग लिस्प "लिस्प" sooooo 20 वीं सदी है। :-) –

1

आसान।

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

पुन सैम केसर के अनुरोध:

*hello_world = sub() { 
    print "oops"; 
}; 
hello_world(); 
*hello_world = sub() { 
    print "hello world"; 
}; 
hello_world(); 
+0

अराजकता, क्या आप पर्ल में अपने रूबी नमूने को फिर से लिख सकते हैं? (मेरा जवाब देखें) –

+0

उह, मुझे उम्मीद है कि छोटा? – chaos

+0

मैंने आपको +1 दिया लेकिन मेरा मतलब लंबा था :) –

2

Self-modifying code भी पतित कोड कहा जाता है। इसे आम तौर पर एक बुरी चीज माना जाता है, और यह आसानी से लिखे जाने से रोकने के लिए उच्च स्तरीय भाषाओं का लक्ष्य होता था।

यह विकिपीडिया प्रविष्टि से है:

स्वयं संशोधित कोड एक बुरा व्यवहार जो कोड कठिन पढ़ सकते हैं और बनाए रखने के लिए बनाता है के रूप में कुछ लोगों द्वारा देखा जाता है। ऐसे कई तरीके हैं जिनमें स्वयं संशोधन को स्वीकार्य समझा जाता है, जैसे कि जब नियमित दिनचर्या पॉइंटर्स गतिशील रूप से परिवर्तित होते हैं - भले ही प्रभाव प्रत्यक्ष संशोधन के लगभग समान है।

+0

मैं मानता हूं कि आपको सामान्य परिस्थितियों में यह निश्चित रूप से नहीं करना चाहिए। क्या एक रखरखाव दुःस्वप्न है। लेकिन के रूप में उल्लेख है, यह वास्तव में कुछ साफ दरवाजे खोल करता है - उदाहरण के लिए, वहाँ एक समस्या को हल करने में विकसित है कि कोड के लिए कुछ आकर्षक सीएस अनुप्रयोग हैं। –

+2

यह उत्तर, ओपीएस प्रश्न का उत्तर नहीं देता है। –

3

मुझे लगता है कि यह वास्तव में "आसानी से गतिशील पुनर्लेखन" के रूप में परिभाषित करने पर निर्भर करता है। उदाहरण के लिए .Net में आपके पास Func प्रकार और lambdas हैं जो आपको चर के रूप में या अस्थायी अनाम कार्यों जैसे कार्यों को परिभाषित करने की अनुमति देता है।

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()); 

ऊपर का एक बहुत ही काल्पनिक उदाहरण है या तो पूर्णांकों की एक सरणी में आइटम गिनती या तो संक्षेप डायनामिक रूप से तैयार कार्यों कुछ मनमाने ढंग से इस शर्त के अधीन का उपयोग कर।

नोट - कृपया कहना नहीं है कि इन बातों को आसानी से (जो वे स्पष्ट रूप से कर सकते हैं) मैं बस सी #

2

मैं में अवधारणा को प्रदर्शित करने के लिए एक बहुत ही सरल उदाहरण लिखने के लिए कोशिश कर रहा था lambdas के बिना पूरा किया जा सकता लगता है कि यह गतिशील भाषाओं में सबसे अधिक मामला है। यहाँ अजगर

में एक उदाहरण है
 
def f(x): 
    print x 

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

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

उत्पादन

 
world 
hello world 

मुझे लगता है कि इस तरह के तकनीक ध्यान से इस्तेमाल किया जाना चाहिए

+0

ऐसी बात JIT को हताश नहीं है? यह सामान है कि दुभाषियों के लिए ठीक है, लेकिन JITs के लिए अच्छा नहीं है, के बाद से अनिवार्य रूप से वे compilers कर रहे हैं और इस बात के लिए विशेष हैंडलिंग की जरूरत है –

2

योजना आप ऐसा करने की अनुमति देता है।

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

अब आप एक fonction सही कार्य करने के लिए salute चर बताए द्वारा, या तो salute-english या salute-french को फिर से परिभाषित कर देते हैं:

(define salute salute-english) 

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

अधिक आम तौर पर कार्यात्मक प्रोग्रामिंग भाषा आपको लगता है कि या कार्यों के रूप में करने की अनुमति देता प्रथम श्रेणी मूल्य हैं। कार्यों का उपयोग किया जा सकता है, चारों ओर पारित किया जा सकता है, कभी-कभी चर के लिए आवंटित किया जाता है और इसी तरह। सूची तो में शामिल हैं: लिस्प, योजना, डायलन, OCaml और एसएमएल। प्रथम श्रेणी कार्यों होने कुछ भाषाओं अजगर, रूबी, स्मालटाक भी शामिल है और मुझे लगता है कि पर्ल

ध्यान दें कि जब आपके पास एक इंटरैक्टिव भाषा होती है जहां आप अपने प्रोग्राम को अंतःक्रियात्मक रूप से टाइप कर सकते हैं, तो कार्यों/विधियों का पुनर्वितरण संभव होना चाहिए: आरईपीएल को ऐसा करने में सक्षम होना चाहिए, बस अगर आप परिभाषा को फिर से लिखना चाहते हैं पहले से परिभाषित कार्यों।

0

PLSQL में:

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

आप इसे C++ कर सकता है, लेकिन यह आसान सुरक्षित, या सिफारिश नहीं होगा।

  1. स्रोत कोड
  2. संकलक (कांटा & कार्यकारी) आह्वान एक गतिशील पुस्तकालय का निर्माण करने का पाठ उत्पन्न करें। जीसीसी में, आप उस स्रोत कोड को पास कर सकते हैं जिसे आप मानक इनपुट पर संकलित करना चाहते हैं, इसे फ़ाइल में नहीं होना चाहिए।
  3. लोड पुस्तकालय (LoadLibrary() खिड़कियों पर, लिनक्स पर dlopen())
  4. जो कुछ भी समारोह आप चाहते करने के लिए एक समारोह सूचक मिलता है (linux पर GetProcAddress() खिड़कियों पर, dlsym())
  5. अगर आप चाहते हैं किसी मौजूदा फ़ंक्शन को प्रतिस्थापित करने के लिए, यदि यह वर्चुअल फ़ंक्शन है तो आप नए फ़ंक्शन को इंगित करने के लिए v-table को संशोधित कर सकते हैं (वह हिस्सा विशेष रूप से खतरे से भरा एक भयानक विचार है)। वी-टेबल का स्थान या इसका प्रारूप सी ++ मानक का हिस्सा नहीं है, लेकिन मेरे द्वारा उपयोग किए जाने वाले सभी टूलचेन स्वयं के भीतर संगत रहे हैं, इसलिए एक बार जब आप यह समझ लें कि वे इसे कैसे करते हैं, तो शायद यह नहीं होगा टूटना।
0

यहां पाइथन (ल्यूक के उत्तर के अलावा) में कुछ और है, जिसे मैं अनुशंसा नहीं कर रहा हूं, लेकिन इसे दिखाने के लिए - वहां निष्पादन है, जो एक स्ट्रिंग निष्पादित कर सकता है जिसे आप जो भी कोड बना सकते हैं ..

आई/ओ यहां दिखाया गया है एक पायथन 2.5.2 दुभाषिया सत्र से है। बस सबस्ट्रिंग (>>> दुभाषिया शीघ्र है) से निष्पादित करने के लिए तार के निर्माण की कुछ सरल उदाहरण ...

>>> 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 
>>> 
0

रूबी में तुच्छ:

def hello_world; puts "oops"; end 
hello_world 
# oops 
def hello_world; puts "hello world"; end 
hello_world 
# hello world 
पाठ्यक्रम कि उदाहरण उबाऊ है के

:

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 

उपरोक्त कोड:

  1. करने के लिए इसे
  2. एक उदाहरण
  3. अवरोध कि विधि पकड़ लेता है कि उदाहरण के केवल
0

बदलने पड़ता कि एक समारोह का एक बहुत में समर्थित है पर एक खाली वर्ग

  • एक विधि जोड़ता को परिभाषित करता है भाषाएं, और यह उतना जटिल नहीं है जितना आप सोच सकते हैं। कार्यात्मक भाषाओं में, फ़ंक्शन मान होते हैं, और फ़ंक्शन नाम ऐसे प्रतीक होते हैं जो किसी भी चर के समान होते हैं। यदि भाषा आपको प्रतीक को एक अलग कार्य में पुन: असाइन करने की अनुमति देती है, तो यह मामूली है।

    मुझे लगता है कि अधिक दिलचस्प विशेषताएं एक फ़ंक्शन (toString ऊपर) के लिए स्रोत कोड प्राप्त करने की क्षमता है और एक स्ट्रिंग से एक नया फ़ंक्शन बनाने के लिए (eval इस मामले में)।

  • संबंधित मुद्दे

     संबंधित मुद्दे