To_s with argument

How can I write a to_s method for some class accepting an argument, like a boolean ?
For example, I tried, but no luck!

def to_s(io : IO, format = false)
    if format
       io << "n:" << @after << ",p:" << @before
    else
       io << @after << ":" << @before
    end
end

I got:

Error: expected argument #1 to ‘to_s’ to be IO, not Bool

You must also override the #to_s method that doesn’t take any argument:

def to_s(format = false)
  String.build { |io| to_s(io, format) }
end

Thanks @ysbaddaden

Mind you, it’s always better to use named arguments for bool properties for readability.

def to_s(io : IO, *, format = false)
  if format
    io << "n:" << @after << ",p:" << @before
  else
    io << @after << ":" << @before
  end
end

def to_s(*, format = false)
  String.build { |io| to_s(io, format: format) }
end
1 Like

I don’t know anything about this specific use case.
But in general, I believe a separate method is usually better than adding parameters to a standardized method like #to_s which typically isn’t expected to be called with arguments.

These are the #to_s methods in the standard library that take extra arguments:

  • Int#to_s accepts base, precision, and upcase
  • BigRational#to_s accepts base
  • Time#to_s accepts format
  • URI#Params#to_s accepts space_to_plus
  • Crystal::Types#to_s accepts generic_args
1 Like