Most of us would have seen 'n' number of posts on how to use lambda( I have seen at least 10+ posts), but eventually will end up writing common methods. I have never used block call or yield, as it looks like a complicated feature that my brain never wants to learn it( "why to complicate things ! :D").
Unfortunately, I have to use it in my work, to avoid duplicate issues. Then I told myself, if not now then when?
Before jumping into the code, we should be aware of what is lambda and its syntax.
Note: '->' is equivalent to lambda literal
class WithoutLambdaExample | |
def self.run_examples | |
scores = [1, 2, 3, 4] | |
ClassA.calculate_score(scores) | |
scores = [4, 5, 6, 7] | |
ClassB.calculate_score(scores) | |
scores = [8, 9, 10, 11] | |
ClassC.calculate_score(scores) | |
scores = [12, 13, 15, 14] | |
ClassD.calculate_score(scores) | |
end | |
end | |
class ClassA | |
THRESHOLD = 5 | |
FACTOR = 2 | |
def self.calculate_score(scores) | |
score_point = process_score(scores) | |
puts "Class A: score point #{score_point}" | |
end | |
def self.process_score(scores) | |
sum = 0 | |
unless scores.empty? | |
scores.each do |score| | |
sum += score if Utils.allowed_score(score) && (score * FACTOR > THRESHOLD) | |
end | |
end | |
sum | |
end | |
end | |
class ClassB | |
THRESHOLD = 10 | |
FACTOR = 2.5 | |
def self.calculate_score(scores) | |
score_point = process_score(scores) | |
puts "Class B: score point #{score_point}" | |
end | |
def self.process_score(scores) | |
sum = 0 | |
unless scores.empty? | |
scores.each do |score| | |
sum += score if Utils.allowed_score(score) && (score + FACTOR < THRESHOLD) | |
end | |
end | |
sum | |
end | |
end | |
class ClassC | |
THRESHOLD = 5 | |
FACTOR = 3 | |
def self.calculate_score(scores) | |
score_point = process_score(scores) | |
puts "Class C: score point #{score_point}" | |
end | |
def self.process_score(scores) | |
sum = 0 | |
unless scores.empty? | |
scores.each do |score| | |
sum += score if Utils.allowed_score(score) && (score - FACTOR >= THRESHOLD) | |
end | |
end | |
sum | |
end | |
end | |
class ClassD | |
THRESHOLD = 8 | |
FACTOR = 3.5 | |
def self.calculate_score(scores) | |
score_point = process_score(scores) | |
puts "Class D: score point #{score_point}" | |
end | |
def self.process_score(scores) | |
sum = 0 | |
unless scores.empty? | |
scores.each do |score| | |
sum += score if Utils.allowed_score(score) && (score / FACTOR < THRESHOLD) | |
end | |
end | |
sum | |
end | |
end | |
class Utils | |
LOW_RANGE = 2 | |
HIGH_RANGE = 15 | |
def self.allowed_score(score) | |
score >= LOW_RANGE && score <= HIGH_RANGE | |
end | |
end |
Now you have seen that condition alone changes but calculating steps remain the same.
How these repeating steps can be moved to a common method?
We can pass FACTOR and THRESHOLD, but how about operators?
Is there a way that I can pass this condition alone from the calling method and make it simple?
To answer all the above questions, we have our LAMBDA for it.
class LambdaExample | |
def self.run_examples | |
scores = [1, 2, 3, 4] | |
ClassA.calculate_score(scores) | |
scores = [4, 5, 6, 7] | |
ClassB.calculate_score(scores) | |
scores = [8, 9, 10, 11] | |
ClassC.calculate_score(scores) | |
scores = [12, 13, 15, 14] | |
ClassD.calculate_score(scores) | |
end | |
end | |
class ClassA | |
THRESHOLD = 5 | |
FACTOR = 2 | |
def self.calculate_score(scores) | |
condition_block = lambda { |score| (score * FACTOR) > THRESHOLD } | |
score_point = Processor.process_score(scores, &condition_block) | |
puts "Class A: score point #{score_point}" | |
end | |
end | |
class ClassB | |
THRESHOLD = 10 | |
FACTOR = 2.5 | |
def self.calculate_score(scores) | |
condition_block = lambda { |score| (score + FACTOR) < THRESHOLD } | |
score_point = Processor.process_score(scores, &condition_block) | |
puts "Class B: score point #{score_point}" | |
end | |
end | |
class ClassC | |
THRESHOLD = 5 | |
FACTOR = 3 | |
def self.calculate_score(scores) | |
condition_block = lambda { |score| (score - FACTOR) >= THRESHOLD } | |
score_point = Processor.process_score(scores, &condition_block) | |
puts "Class C: score point #{score_point}" | |
end | |
end | |
class ClassD | |
THRESHOLD = 8 | |
FACTOR = 3.5 | |
def self.calculate_score(scores) | |
condition_block = lambda { |score| (score / FACTOR) < THRESHOLD } | |
score_point = Processor.process_score(scores, &condition_block) | |
puts "Class D: score point #{score_point}" | |
end | |
end | |
class Processor | |
LOW_RANGE = 2 | |
HIGH_RANGE = 15 | |
def self.process_score(scores, &condition_block) | |
sum = 0 | |
unless scores.empty? | |
scores.each do |score| | |
sum += score if allowed_score(score) && !condition_block.nil? && condition_block.call(score) | |
end | |
end | |
sum | |
end | |
def self.allowed_score(score) | |
score >= LOW_RANGE && score <= HIGH_RANGE | |
end | |
end |
Now repeating steps are moved into a common method called process_score, having score and lambda as arguments.
We can do this in different ways, but this post is exclusively for how we can make use of lambda.
Thanks for reading! Suggestions are welcome!
Note: This is post originally posted in my medium account https://medium.com/@subha220993/oh-my-lambda-a1386a0bdad2
Top comments (0)