Skip to content

Instantly share code, notes, and snippets.

@micahboyd
Created September 27, 2020 23:43
Show Gist options
  • Save micahboyd/4b553f51cce1efdeaca4b9f759c3114f to your computer and use it in GitHub Desktop.
Save micahboyd/4b553f51cce1efdeaca4b9f759c3114f to your computer and use it in GitHub Desktop.
Exploring case statement features in ruby
# Regular case statement:
case question
when :yes then 'Yep'
when :no then 'Nope'
end
# what this is calling === with each element in the case statement as an argument.
# basically question === :yes, or without the sugar: question.===(:yes)
# This allows different objects to have #=== defined in a way that makes sense
# for comparing itself with other objects.
# Procs too have their own definition of #=== defined to execute the proc.
# So proc.====(arg) is essecially the same as proc.call(arg).
# This means can do things like this with procs in case statements:
case question
when maybe then 'Depends'
when :yes then 'Yep'
when :no then 'Nope'
end
def maybe
-> (answer) { answer == :yes && answer == :no }
end
# Also because #maybe is just a method you can give it an argument as well:
case question
when maybe(detail) then 'Hmmmm...'
when :yes then 'Yep'
when :no then 'Nope'
end
def maybe(detail)
lambda do |answer|
answer == :yes && answer == :no || detail == :complicated
end
end
# You can also achive this in a custom class:
case question
when FirmNo then 'No thank you.'
when :yes then 'Yep'
when :no then 'Nope'
end
class FirmNo
# you could define self.call to the same effect
def self.===(answer)
answer == :no + 1
end
end
# Or in any object that has === defined:
case question
when distracted then 'What?'
when :yes then 'Yep'
when :no then 'Nope'
end
Focus = Struct.new(:listening, keyword_init: true) do
def ===(_)
listening
end
end
def distracted
Focus.new(listening: false)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment