Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calyx cannot handle string methods that accept parameters #20

Open
tra38 opened this issue May 13, 2017 · 2 comments
Open

Calyx cannot handle string methods that accept parameters #20

tra38 opened this issue May 13, 2017 · 2 comments

Comments

@tra38
Copy link
Contributor

tra38 commented May 13, 2017

The good news is that I am right now using Calyx in a real-world project. The bad news is that doing so means you quickly encounter edge cases...


Sometimes, your program has to generate sentences without knowing in advance if they'd be plural or not.
class CatWatch < Calyx::Grammar
   start "Today, I saw {number} cats on the way to work."
end

reporter = CatWatch.new
reporter.generate(number: 1)
#=>"Today, I saw 1 cats on my way to work."

I thought about doing some monkey-patching to handle this sort of pluralization, with plans to eventually refactor to a "best practice" solution using modifiers...

class String
   def pluralize(possible_word)
      if self.to_i == 1
         "#{self} #{possible_word}"
      else
         "#{self} #{possible_word}s"
      end
   end
end

"1".pluralize("cat")
#=>"1 cat"

"2".pluralize("cat")
#=>"2 cats"

However, this monkey-patched solution doesn't work in Calyx.

class CatWatch < Calyx::Grammar
   start "Today, I saw {number.pluralize('cat')} on the way to work."
end

reporter = CatWatch.new
reporter.generate(number: 1)
=>"Today, I saw {number.pluralize('cat')} on the way to work."

Refactoring to "best practice" doesn't work either.

module Pluralize
   def pluralize(possible_word)
      if self.to_i == 1
         "#{self} #{possible_word}"
      else
         "#{self} #{possible_word}s"
      end
   end
end

class CatWatch < Calyx::Grammar
   modifier Pluralize
   start "Today, I saw {number.pluralize('cat')} on the way to work."
end

reporter = CatWatch.new
reporter.generate(number: 1)
#=>Today, I saw {number.pluralize('cat')} on the way to work.

Even more oddly, if I do a slight change to the start method...it is no longer gets interpreted as part of the string...even though I still get incorrect output.

class CatWatch < Calyx::Grammar
   modifier Pluralize
   start "{number.pluralize('cat')}"
end

reporter = CatWatch.new
reporter.generate(number: 1)
#=>"1"

Now, since I'm on a tough deadline, I wind up doing this solution instead to handle pluralization.

class String
   def pluralize_cats
      if self.to_i == 1
         "#{self} cat"
      else
         "#{self} cats"
      end
   end
end

class CatWatch < Calyx::Grammar
   start "Today, I saw {number.pluralize_cats} on the way to work."
end

reporter = CatWatch.new
reporter.generate(number: 1)
#=>"Today, I saw 1 cat on the way to work."

...which "works", but is pretty hacky. There has to be a better solution (one that hopefully doesn't involve using meta programming to generate a bunch of unique methods for handling pluralization). It'll do for now though.

I decided to follow best practice by moving my pluralize_cats method over to a module, but I then encountered a different issue with modifiers (which I reported in #21).

@maetl
Copy link
Owner

maetl commented May 13, 2017

The syntax limitation is by design, but I appreciate the feedback on this.

I’ll provide some recommendations once #21 is fixed.

@tra38
Copy link
Contributor Author

tra38 commented May 29, 2017

In case anyone was curious, this was my final solution to this problem. If I get time, I'm going to look at Inflecto to see whether I can incorporate that library into this solution in case I ever need to deal with pluralization again.

module Macros

  def generate_pluralization_method(singular:, plural:)
    method_suffix = plural.gsub(" ","_")
    define_method :"pluralize_#{method_suffix}" do |argument|
      if (argument.to_f == 1)
        "#{argument} #{singular}"
      else
        "#{argument} #{plural}"
      end
    end
  end

end

module CatWatchHelpers
   extend Macros
   generate_pluralization_method(singular: "cat", plural: "cats")
end

class CatWatch < Calyx::Grammar
   modifier CatWatchHelpers
   start "Today, I saw {number.pluralize_cats} on the way to work."
end

reporter = CatWatch.new
reporter.generate(number: 1)
#=>Today, I saw 1 cat on the way to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants