This is an extremely simplistic (lol, only the 4 essential files) library that adds the Optional (anti)1 design pattern too ALL methods globally.
It even supports logic operators (and
, or
, etc.)!
some = Optionil[42] #=> Optionil::Some[42]
none = Optionil[nil] #=> Optionil::None[] (you don't want Optionil::Some[nil], do you?…)
Optionil::Some[nil] #!> NoMatchingPatternError (Do you???)
none.equal? Optionil[] #=> true (the two are equivalent and all calls give the same constant)
Optionil::Some[] #!> wrong number of arguments (given 0, expected 1) (ArgumentError)
Optionil::None[nil] #!> wrong number of arguments (given 1, expected 0) (ArgumentError)
some.value #=> some
none.value #=> nil
some.value! #=> 42
none.value! #!> NoMatchingPatternError
some.value { 0 } # => some
some.value { raise } # => some
none.value { 0 } # => 0
none.value { Optionil[0] } # => Optionil::Some[0]
some.each {|n| -n } #=> -42
some.each {|n| Optionil[-n] } #=> Optionil::Some[-42]
none.each {|n| -n } #=> nil
none.each {|n| raise } #=> nil
Optionil == some #=> true
Optionil == none #=> true
Optionil::Some == some #=> true
Optionil::Some == none #=> false
Optionil::None == some #=> false
Optionil::None == none #=> true
some.some? #=> true
none.some? #=> false
some.none? #=> false
none.none? #=> true
some.some? Integer #=> true
some.some? String #=> false
none.some? Integer #=> false
some.some? &:even? #=> true
some.some? &:odd? #=> false
some.none? &:even? #=> false
some.none? &:odd? #=> true
!some #=> false
!none #=> true
som2 = Optionil::Some[-69]
some and som2 #=> som2
some and none #=> none
none and som2 #=> none
some or som2 #=> some
some or none #=> some
none or som2 #=> som2
none or none #=> none
som0 = Optional::Some[false]
!som0 #=> true
som0 and some #=> som0
# applies to `Optional::Some[nil]` as well
I’m intentionally not supporting this. Please tune in to pipeine operator discussions instead, such as https://bugs.ruby-lang.org/issues/20770.
Copyright © 2024 ParadoxV5
I made this little joke as entertainment in a day. I release it to the public domain; you can redistribute it and/or modify it under the “terms” of the Do What The Fuck You Want To Public License, Version 2.
Footnotes
-
Cold take: the Optional pattern only exists because you can’t properlly handle
nil
s.Yes,
null
is a billion-dollar mistake in traditional languages; but this is Ruby – we don’t havenull
s, we havenil
s! AString
can never benil
, only aString?
(RBS) can!Even for, say Java,
NonNull
exists (JetBrains, Android, Lombok), so nullable variables are alreadySome|None
Schrödinger boxes, why bother addingOption
as another layer of wrapper? You’d thinkOptional[T]?
wouldn’t be a thing? Do you needOptional[Optional[T]]
for that? JavaScript already has bothnull
andundefined
, questionably, yet how many more types ofnil
s do you still need? ↩