Metaprogramming: Ruby vs. Javascript
fingernailsinoatmeal.com
fingernailsinoatmeal.com
Metaprogramming inside of a running JS system would involve eval() and generating JS code from strings, which you don't want to do. It's prone to exploding in your face and the performance profile is terrible.
Please read the article and think about its quality before voting.
If you would like to look at some interesting JavaScript metaprogramming, check out projects like Objective-J/Cappuccino, Clamato, BiwaScheme, HotRuby, and a Python one I'm forgetting the name of (not Pyjamas, that does not run itself in JavaScript, it is compiled by a different language.)
These pre-process some other types of code into native JavaScript structures which execute in the browser or JavaScript interpreter. They are distinct from inserting snippets of live generated code from strings into a system that is already live (as in eval() and friends) to modify it at runtime. That is one of the worst ways to use metaprogramming. What you want is a system that is self-hosting, in order to let you express yourself more deeply in the language. That way, your metaprogramming constructs execute in a controlled environment instead of chaotically determined by various factors at runtime. Lisp is the prime example of this.
Generating source code at runtime definitely counts as metaprogramming, but doing that and having to re-parse it is probably the coarsest and most error-prone way. Lisp routes around this by working with ADTs directly, but that forces a lot of other trade-offs in the language design.
When we say "meta x" we mean talking about x, e.g. "meta discussions" on HN is discussions about discussions. Meta programming is writing programs about the program, which can also just be doing introspection and making choices based on that.
No, I'm not. We seem to have a terminology mismatch somewhere. Asking a function how many arguments it takes and then taking some action based on that fact would be meta-programming, but taking input isn't.
By what programmers? I have a feeling we are coming from completely different places here.
What do you call what Smalltalk programmers do? In Smalltalk, what we call "meta-programming" happens a great deal but I've never seen eval called in a Smalltalk program ever.
Have you read the book "The art of the meta-object protocol"? Everything in that book is meta-programming yet I don't recall eval being used anywhere, and much of the code was simply to allow programs to discover things about the program itself at runtime.
Some C++ template trickery is clearly metaprogramming - at least, it is to me and people in the C++ community who refer to it as such. It does not give the flexibility that's available in a Lisp, but it's still metaprogramming.
There is a difference between program control flow based on user input and generating program logic during the course of execution.
I posit that you may have metaprogramming in a progam that has the same output every time.
To me, metaprogramming is writing code which generates or modifies behavior, logic or program flow control. This may happen at compile or run time. Wether generating a closure and setting an attribute on a JS object or using "eval" to define the function, the effect is the same -- the object's implementation was not defined by the original source or environment.
For instance, this is metaprogramming:
def decorate(obj) obj.send :define_method, :yay, (Proc.new{ puts "woohoo!"}) end
a = File.open('tmp.txt','w')
decorated_a = decorate(a) a.yay
Here, there is no eval, but a's implementation changes at runtime. The same is trivially reproduced in JS.
edit: the difference between the original article and this is that the original article makes modifications directly to the original objects, and not to arbitrary objects, which i suppose is why you object to referring to this as meta-programming.
"The language in which the metaprogram is written is called the metalanguage. The language of the programs that are manipulated is called the object language. The ability of a programming language to be its own metalanguage is called reflection or reflexivity."
Reflection is what I was describing. Asking a function its arity is indeed accomplished by passing said function to some other function, but if you want to find the source code for this function look for "reflection" because that's where it should be defined.
"Metaprogramming usually works through one of two ways. The first way is to expose the internals of the run-time engine to the programming code through application programming interfaces (APIs). The second approach is dynamic execution of string expressions that contain programming commands. Thus, 'programs can write programs'. Although both approaches can be used in the same language, most languages tend to lean toward one or the other."
You seem to only accept the second kind as meta-programming. What do you base your description on? Knowing that would make it easier to see where you're coming from and hopefully what the source of the misunderstanding is.
Reflection as it is defined in that passage is more of what I am talking about, yes. But I think most languages lack this, including JavaScript. Some good examples are Lisp, Template Haskell, and the macro tools available in OCaml. I have nothing against runtime features, but I do not really consider it metaprogramming if that is the only way to accomplish it, since you are effectively being locked out of a true meta-circular system as a programmer. This style of programming is what defines Lisp and many other languages in the functional realm.
Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data ...
JavaScript is entirely capable of doing metaprogramming, but in the article posted here, it does not.
You seem confident that your definition of metaprogramming is the accepted definition, but I don't see evidence of that.
-- the linked blog post doesn't do this, though it is possible.
sword_symbol = "*********"
drew.metaclass.send(:define_method, 'swing') do |sound_effect|
puts "#{name}: #{sword_symbol} #{sound_effect}"
end
drew.swing 'slash!!'
I understand that to add the swing method without writing the source code to do it. This use is trivial, but it's easy for me to extrapolate to how one could make the newly created method depend on runtime information.Correct. The author compares Ruby to JavaScript in a situation which requires metaprogramming in Ruby, but not in JavaScript.
Metaprogramming inside of a running JS system would involve eval()
Incorrect. You could implement pre/post conditions in JavaScript by using metaprogramming, and it would not use eval(). The basic idea would be to iterate functions on MyClass.prototype, replacing each one with a new function that calls the original. This would be code (the pre/post implementation) modifying code (the MyClass definition).
Please read the article and think about its quality before voting.
Please calm down, the article is useful to Ruby people who are unfamiliar with JavaScript, and the literal definition of metaprogramming (code that modifies code) is largely misunderstood anyway. The most correctly you could ever use the term would be in reference to runtime or compile time optimization or safety checking, instrumented profiling, or logging, and I rarely ever see it used that way.
In addition, there's no way (that I've found) to override the subscript operator [] in javascript.
Lua is really powerful, but it's been carefully designed so that a subset of the language can be used for configuration files, data dumps (much like JSON), etc., without having to know anything about programming. The deep elements are there, you just have to look for them. Coroutines, prototypes, metatables, tail-calls, first-class functions, eval, real lambdas, etc. And, did I mention that it mixes well with C?
I think it's deceptively simple, so programmers might not think there's much there. In addition, it's pretty minimalistic, you don't get OO out of the box (which isn't necessarily a bad thing, depending on what you're doing), and the number of libraries pales in comparison, all of which deter others for exploring it more fully.
That only means that the field is ripe for some exploration.
While Lua standalone is a decent language (almost a Python/Scheme hybrid), Lua + C is quite powerful. It's particularly well-suited to the two-level programming style John Ousterhout describes here (http://www.vanderburg.org/OldPages/Tcl/war/0009.html). I haven't used TCL much, but it sounds like the same development style - since you can just use another language when necessary, Lua doesn't have to do everything. It can stay small and simple. While low-level code and hotspots for a project may be written in C, the rest can be written in shell scripts, TCL, Lua, etc. for rapid prototyping. The clear boundary between the layers of development can help keep complexity contained, too.