Open MarkDBlackwell opened 8 years ago
There are several ways of using Dogeify. The first way is to go through ... Dogeify ... itself. The second way is to modify the String or Array classes by including either core extension.
Here's some example code with Dogeify as a module (rather than as a class. Just for demonstration purposes, it prefixes with "hello", instead of actually converting to doge-speak):
class EngTagger; def hello(s) "hello #{s}" end end
module Dogeify
Tagger=EngTagger.new
extend self
def dogeify(*a)
case
when (!a.empty?) then Tagger.hello a.join ''
when (self.is_a? String) then Tagger.hello self.to_s
when (self.is_a? Array) then self.map{|e| Tagger.hello e}
else self
end
end
end
class String; include Dogeify end
class Array; include Dogeify end
Dogeify.dogeify 'a' #=> "hello a"
"abc".dogeify #=> "hello abc"
%w(this that).dogeify #=> ["hello this", "hello that"]
You can even fail gracefully with:
class Object; include Dogeify end
/something/.dogeify #=> /something/
Even better:
class EngTagger; def hello(s) "Hello, #{s}!" end end
module Dogeify
Tagger=EngTagger.new
public
extend self
def dogeify(*a)
return dogeify_object self if a.empty?
dogeify_object a
end
private
def array_like?( object) object.respond_to? :map end
def string_like?( object) object.is_a? String end
def dogeify_object(object)
return object.map{|e| dogeify_object e} if array_like? object
return process object if string_like? object
object
end
def process(s) Tagger.hello s end
end
class String; include Dogeify end
class Array; include Dogeify end
Dogeify.dogeify 'a' #=> "Hello, a!"
"abc".dogeify #=> "Hello, abc!"
%w(this that).dogeify #=> ["Hello, this!", "Hello, that!"]
[1, %w(this that)].dogeify #=> [1, ["Hello, this!", "Hello, that!"]]
['one', /pattern/, 3, 'four'].dogeify #=> ["Hello, one!", /pattern/, 3, "Hello, four!"]
/pattern/.dogeify #=> NoMethodError: undefined method `dogeify' for /pattern/:Regexp
But:
class Object; include Dogeify end
/pattern/.dogeify #=> /pattern/
While writing my first Ruby gem, I found (via Google) your Engineering Lunch Series tutorial on gem writing. It uses the Dogeify gem as an example, and it states:
Arising from this decision, presently each new instance of Dogeify instantiates a new EngTagger.
For even more efficiency—in a highly entertaining post—@mattetti (Matt Aimonetti) and @evanphx (Evan Phoenix) in effect suggest you take this basic idea even further. You can instantiate EngTagger once only (at gem load time) and keep a reference to this EngTagger instance in a constant in Dogeify's module namespace:
Of course this means Dogeify needn't be a class after all! :)
As you know, due to the multicore crisis, both Elixir, the (Ruby-related) language—as well as functional programming in general—are important (read: "the new coolness").
Perhaps it's best not to teach people to write gems as classes unnecessarily. Do you think so?
If you agree, alternatively (and more easily) you could tell your readers that converting Dogeify to a class really wasn't necessary but you did so for didactic purposes. Thus, your presentation focused on gem creation. It minimized the number of concepts new to programmers from backgrounds like Java (presumably the majority). :-)