Stringish
A small utility library that provides string-like operations for things that are not strings (and for strings, too). In this way, text-based algorithms can be abstracted to work not just on plain strings, but also on, for example, HTML.
Basically, the same thing that Scala's Numeric
does for numbers. Except that the operations are modelled as individual types, one per operation. Not every string-ish type needs to be able to implement all of them.
By default, implementations for String
and NodeSeq
are provided. New implementations can be added easily.
Dependency management and compatibility
stringish
is compatible with Scala 2.13. Best effort is made to always keep it up-to-date with the latest Scala version.
Cross-versioning will not be supplied. When a new Scala version is released, your code should be updated to that version as soon as possible anyways.
SBT
libraryDependencies += "net.jackadull" %% "stringish" % "1.1.0"
Maven
<dependency>
<groupId>net.jackadull</groupId>
<artifactId>stringish_2.13</artifactId>
<version>1.1.0</version>
</dependency>
Usage
Here is an example method that would make a natural-language enumeration out of a sequence of parts. For example, given Seq("bell", "book", "candle")
it would return "bell, book and candle"
:
import net.jackadull.stringish.{Concat, FromString}
def nlEnum[S](seq:Seq[S])(implicit concat:Concat[S], fromString:FromString[S]):S = seq match {
case Seq() => fromString("")
case Seq(single) => single
case Seq(first, second) => concat(first, concat.sPlusX("and", second))
case Seq(first, rest@_*) => concat(first, concat.sPlusX(", ", nlEnum(rest)))
}
As can be seen in the example, the string-like abstraction works by depending on an implicit operation parameter, and the concrete string-like type is left open.
Because the implicits for String
and NodeSeq
are provided by default, the method above will work out of the box with both of these types.
Aside from Concat
and FromString
, Stringish also provides the Capitalize
operation, which buts the first letter of a string in upper case.
When all of those operations are provided for a certain type, it is useful to also provide the Stringish
meta-operation. This is the equivalent to Numeric
for numbers.
Implementing operations for other types
Adding further types to be supported by the Stringish operations is fairly easy: Just implement the Stringish operations that you would like to support, and provide implicit values for them. If you pull them in scope, either by putting them in the companion object, or with an import
statement, all methods with Stringish operations will work with them just fine.
And remember: If you implement all of the Stringish operations, it may be a good idea to supply an implementation of the Stringish
type itself as well.