Have you ever cooked your favourite dish!! If not, try it once. You would have a recipe describing the steps involved, the amount of each ingredient, and other required instructions. The execution of a program happens the same way, and you have a set of instructions with proper control flow defined. In this blog, you will learn about various aspects of program execution in Ruby. So what are you waiting for? Let's directly jump into the concepts !!
Remember that Ruby is a scripting language, meaning that the code will be executed in order of appearance. It is different from languages such as C++ or Java, where the starting point is the main function. However, conditional statements or loops can be used to alter the flow of the program.
Ruby first scans the program from BEGIN statements; if found, it executes code inside its body after this execution begins from the first line.
If the interpreter encounters a class or method, it gets executed then and there, creating a new class or method.
Later if these methods are invoked, then their execution happens.
Single-line scripts can be directly written on the command line.
Execution terminates if "end of file" is reached or __END__ token is read.
Tracing Program's Execution
While the program execution is happening, set_trace_func executes a Proc with all sorts of juicy debugging information whenever a new source line is executed, methods are called, objects are created, and so on.
There exists a trace_var method which lets you hook to a global variable. Proc object is invoked whenever an assignment is made to the global variable.
You can use the caller method, which returns an Array of String objects representing the current call stack, to know the calling history.
Marshalling
Ruby's ability to serialise objects is called marshalling. It resembles railroad yards, where numerous compartments are attached to build a complete train.
Use the Marshal::dump method to save an object partially or wholly. Typically, you will dump an entire object tree starting with some given object. Later on, you can reconstitute the object using Marshal::load.
Custom Serialization
Procedure objects, bindings, instances, class IO and singleton objects cannot be saved outside of Ruby's runtime environment and thus cannot be dumped. Therefore, if these problematic elements are present, you may want to take control of object serialisation yourself.
Ruby provides this feature to serialise objects as needed. Marshal provides the hooks you need. In the objects that require custom serialisation, implement two methods: an instance method called _dump, which writes the object out to a string, and a class method called _load, which reads a string that you'd previously created and converts it into a new object.
Distributed Ruby
Now you know how to serialise objects, you can exploit this knowledge to build a distributed system. Object serialisation allows for creating an out-of-storage process; when combined with networking, you can have a distributed object system.
You can use a drb library to make your life easier. A Ruby process can act as server and client simultaneously. A drb server acts as a source of objects, while the client is the user of those objects. It appears the objects are local, but in reality, they are remote.
A server starts a service by associating an object with a given port. Threads are created internally to handle incoming requests on that port.
Runtime | Compile time
In contrast to compiled languages such as Java, there's not much difference between 'runtime' and 'compile time' in Ruby. It's all the same. You can make changes in a running process, redefine functions on the fly as well as change the scope of variables from private to public or vice-versa. Even objects and classes can be altered on the go.
Once you get familiar with Ruby, it will be challenging to get back to static languages such as C++ or Java. The flexibility that Ruby provides is fantastic.
Frequently Asked Questions
What is a runtime environment?
The hardware and software infrastructure that supports running a code in real-time is called a runtime environment. For example, c++ requires MinGW as a compiler, and Java requires JRE and many more.
What is the advantage of using Ruby?
It is flexible and open-source with native multi-threading support. Changes are easy to make in Ruby. Also, it is exceptionally secure. The programming language holds and stores all the objects by reference instead of value, preventing any data from being hacked.
What is a process in Ruby?
The Process module in Ruby is a collection of functions used to manipulate processes. These functions are used to handle the Operating System-level programs.
What is meant by 'scope'?
Scope defines the accessibility of variables from various locations, i.e. if a variable is defined inside a class, its scope is limited within the class only. Access modifiers are used to extend the scope of variables.
What is a port?
It is a communication endpoint that serves networking purposes—for example, port 443 for HTTPS traffic, port 22 for ssh etc. Any incoming request or outgoing data is transferred via these ports.
Conclusion
Well done, Ninja !! You have reached the end of this blog. We know it's hard to learn these complex concepts. You did a commendable job. In this blog, you learned about program execution in Ruby. Various implementation aspects were covered in detail, and you knew about flow control, serialisation, marshalling etc.
After reading about program execution in ruby, are you not feeling excited to read more articles on the topic of Ruby? Don't worry; Coding Ninjas has you covered. To learn, see Ruby_Coding_Ninjas, Ruby on Rails, Coding Ninjas Studio, and Coding Ninjas guided paths.
You may follow official Ruby documentation, faqs and koans for further in-depth information.
Please do upvote our blogs if you find them helpful and informative!