Jump to content
Sign in to follow this  
  • entries
    3
  • comments
    2
  • views
    3,353

Awkward RGSS code and how to refactor it.

Trihan

750 views

Ruby is a fantastic language. It can often almost read as plain English, it's not strongly typed so you don't have to worry about declaring ints and strings and floats, the brackets after method declarations are optional, it supports optional parameters and arguments...and there are a million ways to achieve a given task. While this is on the surface a good thing, it means that there are a multitude of ways to accomplish something that are either capable of being coded more efficiently or are just plain inefficient to begin with.

 

Let's say we have an array we want to set to a particular value, but only if its value has not already been set:

if example_array == nil  example_array = []end

So it takes us 3 lines to do that. It seems like there ought to be a better way. And there is! The first thing is that you don't need to compare with nil in Ruby; there's a built-in method that does this for you.

if example_array.nil?  example_array = []end

Better, but still not quite there. How about utilising Ruby's support for having if statements after the condition?

example_array = [] if example_array.nil?

Great! But...what if it could be made even better?

example_array ||= []

Even better! Ruby has what's called a conditional assignment operator, ||=, which assigns the right-hand value to the left-hand object only if that object doesn't already contain a value.

 

Okay, so let's take a "sanity check" condition where we want to return immediately if a method's passed-in value isn't an integer.

if !example_parameter.is_a?(Integer)  return "Parameter must be an integer"end

Okay, first of all, that old exclamation mark thing for not conditions needs to go, right? If only Ruby had something that was kind of like an if statement, but did the opposite...

unless example_parameter.is_a?(Integer)  return "Parameter must be an integer"end

It does! Unless is a conditional operator which returns true if the condition is false. In other words, this code will only run if the parameter is NOT an integer. But it could still be better. Oh yeah, we can have conditional operators after their conditions, can't we?

return "Parameter must be an integer" unless example_parameter.is_a?(Integer)

And you might think that's as efficient as you can make it, but remember when I said that the brackets for parameters and arguments are optional in Ruby?

return "Parameter must be an integer" unless example_parameter.is_a? Integer

One other cool thing about Ruby is implicit return values. Let's take a simple bit of code that adds up the numbers 1 to 10 and returns the result.

sum = 0for num in (1..10)  sum += numendreturn sum

Ruby automatically returns the last evaluated expression in a block of code, so you don't even need the "return":

sum = 0for num in (1..10)  sum += numendsum

There's something else about this example that bothers me. For loops seem a bit last year. I wonder if there's a better way to do this.

sum = 010.times do |n|  sum += nendsum

Much better! .times is an iterative method that can be run on pretty much any number, and is way better than a for loop.

 

Let's go back to our original example array. If I want to add the value 5 to it:

example_array.push(5)

Push is a great method for adding a value to an array, but there's actually a more efficient one if you're only adding a single value:

example_array << 5

<< does the same thing as push, but for single values it's actually less processor-intensive. It doesn't support multiple values, though.

 

These are just a few of the little optimisations you can make to scripts. If you've come up with a better way to do something in your own scripting, feel free to mention it in the comments!

  • Like 1

×
Top ArrowTop Arrow Highlighted