Chapter 20. Dynamic Programming

image with no caption

In the past 19 chapters, I’ve covered a huge range of features of the Ruby language. One thing I haven’t covered in any detail is Ruby’s dynamic programming capability.

If you have used only a nondynamic language (say one of the languages from the C or Pascal family), it is likely that dynamism in programming may take a little getting used to. Before going any further, I’ll clarify what I mean by a dynamic language. The definition is, in fact, a bit vague, and not all languages that lay claim to being dynamic share all the same features. In a general sense, however, a language that provides some means by which programs may be modified at runtime can be considered to be dynamic. Another quality of a dynamic language is its ability to change the type of a given variable—something you have done countless times in the examples throughout this book.

A further distinction may also be made between a dynamically typed language such as Ruby and a statically typed language (one in which the type of a variable is predeclared and fixed) such as C, Java, or Pascal. In this chapter, I will concentrate on the self-modifying capabilities of Ruby.

Note

In formal computer science, the term dynamic programming is sometimes used to describe an analytic approach to solving complex problems. That is not the sense in which the term is used in this chapter.

Self-Modifying Programs

In most compiled languages and many interpreted languages, writing programs and running programs are two completely distinct operations: The code you write is fixed, and it is beyond any possibility of further alteration by the time the program is run.

That is not the case with Ruby. A program—by which I mean the Ruby code itself—can be modified while the program is running. It is even possible to enter new Ruby code at runtime and execute the new code without restarting the program.

The ability to treat data as executable code is called metaprogramming. You’ve been doing metaprogramming, albeit of a rather simple sort, throughout this book. Every time you embed an expression inside a double-quoted string, you are doing metaprogramming. After all, the embedded expression is not really program code—it is a string—and yet Ruby clearly has to “turn it into” program code in order to be able to evaluate it.

Most of the time you will probably embed rather simple bits of code between the #{ and } delimiters in double-quoted strings. Often you might embed variable names, say, or mathematical expressions:

str_eval.rb

aStr = 'hello world'
puts( "#{aStr}" )
puts( "#{2*10}" )

But you aren’t limited to such simple expressions. You could, if you wanted, embed just about anything into a double-quoted string. You could, in fact, write an entire program in a string. You don’t even need to display the end result using print or puts. Just placing a double-quoted string into your program will cause Ruby to evaluate it:

"#{def x(s)
        puts(s.reverse)
    end;
(1..3).each{x(aStr)}}"

Even though the previous code fragment is a string, the Ruby interpreter will evaluate its embedded code and display the result, shown here:

dlrow olleh
dlrow olleh
dlrow olleh

Interesting as this may be, writing a whole program inside a string would probably be a pretty pointless endeavor. However, there are other occasions when this, and similar, features can be used much more productively. For example, you might use metaprogramming to explore artificial intelligence and “machine learning.” In fact, any application that would benefit from having a program’s behavior modified in response to user interaction is a prime candidate for metaprogramming.

Note

Dynamic (metaprogramming) features are ubiquitous in Ruby. Consider, for example, attribute accessors: Passing a symbol (such as :aValue) to the attr_accessor method causes two methods (aValue and aValue=) to be created.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.75.70