RPG Maker Forums

Block and Closure Function
 
Introduction
Lately, a friend of mine just told how awesome functional programming awesome was. One of its feature which catch my interest most is the closure function. In fact, I used this feature a lot in prototype programming (Javascript, Lua) and decided to research about this feature in Ruby. And well, we get block, proc and lambda there.
 
Block
Block is a cool feature in Ruby, and most of you are using this. We see this a lot when working with Array, this is an example of block:
 

array = [1, 2, 3, 4, 5]array.each { |x| puts x }array.each do |x| puts xendOf course, those above blocks are equal. And the question there, how we make our own blocks for class. Luckily, we have the powerful yield keyword to do our work there:

class Game_Party < Game_Unit def each_member members.each { |member| yield member } endendWith this short code, we can use block with Game_Party ($game_party):

$game_party.each_member { |member| puts member.name }$game_party.members.each { |member| puts member.name }Those 2 lines do the same thing, but in first case, you can control your way to work with each member, and it's a better convention than calling its property and mapping each member of that array.
 
For example of change the way to work with each member, we have a battle system, and each of end turn, we reset all actors ready state, except for actors who need to rest (because of some skills require them to rest for a few turns):

class Game_Party < Game_Unit def reset_state members.each do |member| member.reset_state # a method to reset for each member yield member if member.is_ready? # only return ready member in block end endendThat way, you can do anything with all members who don't need a rest in new turn:

$game_party.reset_state do |member| # do anything with member that don't need a rest # in short, only member has is_ready? method return trueend$game_party.members do |member| member.reset_state if member.is_ready? # do anything with member that don't need a rest endendThose two blocks do the same thing, but in case 1, we have a nicer convention, and we can use it as a normal method (reset_state for all members). In short, we can shorten our code in this way.
 
But wait, we remove the block, only use the method:

$game_party.reset_stateAnd get a crash! yield only work when a block is given, so we have to change the code a bit to check if the block is given:

class Game_Party < Game_Unit def reset_state members.each do |member| member.reset_state # a method to reset for each member end # separate mapping with yield for better code members.each do |member| yield member if member.is_ready? # only return ready member in block end if block_given? endendTry again, and it work beautifully! The method block_given? only return true if a block is given.
 
Those examples are good for now, but what if we have a block that use again and again all the time? Procs and Lambdas will do it for you in a nice and short way.

Proc (Procedure)

Sometimes, you will find that you write a block code over and over again, and you also want to pass the function around method(s) and class(es). Proc is the best way to do this. For creating a new Proc, you can just use below code:

func1 = Proc.new { |arg1, arg2| your_code_here() }func2 = proc { |arg1, arg2| your_code_here() }Those two lines do the same thing, except in ruby 1.8.x, the func2 will check number of arguments when it's called, whilst func1 doesn't. From ruby 1.9.x, func1 and func2 are exactly the same, they don't check number of arguments and will pass nil value to missing argument(s).

And to call the Proc, there are two ways to execute them:

func = Proc.new { |a, b| return a + b } # create procfunc.call(1, 2) # will return 3func[1, 2] # also return 3Lambda

Lambda does the same thing as Proc, except it will check number of argument on call.

# in this example, your_code_here() doesn't raise error when a and b are nillamb1 = lambda { |a, b| your_code_here() }lamb2 = ->(a, { your_code_here() }func = Proc.new { |a, b| your_code_here() }lamb1.call() # raises an errorlamb2.call() # raises an errorfunc.call() # does not raise errorlamb1 and lamb2 are the same, and syntax in lamb2 is called stabby lambda.

 
RESERVED FOR USAGE AND MORE INFORMATION!!!

Latest Threads

Latest Posts

Latest Profile Posts

Just beat the last of us 2 last night and starting jedi: fallen order right now, both use unreal engine & when I say i knew 80% of jedi's buttons right away because they were the same buttons as TLOU2 its ridiculous, even the same narrow hallway crawl and barely-made-it jump they do. Unreal Engine is just big budget RPG Maker the way they make games nearly identical at its core lol.
Can someone recommend some fun story-heavy RPGs to me? Coming up with good gameplay is a nightmare! I was thinking of making some gameplay platforming-based, but that doesn't work well in RPG form*. I also was thinking of removing battles, but that would be too much like OneShot. I don't even know how to make good puzzles!
one bad plugin combo later and one of my followers is moonwalking off the screen on his own... I didn't even more yet on the new map lol.
time for a new avatar :)

Forum statistics

Threads
106,018
Messages
1,018,357
Members
137,803
Latest member
andrewcole
Top