12  Saying what something is

Conversions are always written out. Nothing here converts a column on your behalf, because a column that quietly changes what it holds is the hardest kind of mistake to find later.

messy |> add(word = to_text(n)) |> add(digits = characters(word))
raw n word digits
ann marie 7 7 1
bob 99 99 2
messy >> add(word = to_text(col.n)) >> add(digits = characters(col.word))
raw n word digits
ann marie 7 7 1
bob 99 99 2

Every conversion begins to_, and nothing else does: to_number, to_whole, to_text, to_date. Ask for the characters in a number without converting it first and you are told which conversion you wanted:

collect(messy |> add(size = characters(n)))
Error:
! 
illegal: `characters` counts the characters in text, and this is a number. Convert it first with `to_text(...)`
  |
2 |   then add [size] as characters([n])
  |                                  ^
try:
    collect(messy >> add(size = characters(col.n)))
except GodError as refusal:
    print(refusal)

illegal: `characters` counts the characters in text, and this is a number. Convert it first with `to_text(...)`
  |
2 |   then add [size] as characters([n])
  |                                  ^

12.1 The four conversions

to_text, to_number, to_whole and to_date are the whole set. Each one says what it makes rather than what it takes, so there is nothing to remember about direction.

to_number gives a number that may have a decimal point. to_whole gives one that may not, and it truncates rather than rounding, which is worth knowing before you use it on money.

messy |>
  add(as_text = to_text(n), rounded = to_whole(to_number(n) / 2)) |>
  pick(n, as_text, rounded)
n as_text rounded
7 7 4
99 99 50
(messy
  >> add(as_text = to_text(col.n), rounded = to_whole(to_number(col.n) / 2))
  >> pick(col.n, col.as_text, col.rounded))
n as_text rounded
7 7 4
99 99 50

A conversion that cannot be made is not a silent missing value in either language. The engine underneath decides what to do with to_number("abc"), and this is one of the few places where what you get depends on where the pipeline ran.

12.2 Between two ends

between is not a conversion, and it is here because it is the other word you reach for when a column has just become a number. It asks whether a value falls in a range.

sales |> keep(between(revenue, 150, 400)) |> sort(revenue)
region product revenue cost
West Gadget 150 50
West Widget 200 50
West Gadget 300 100
sales >> keep(between(col.revenue, 150, 400)) >> sort(col.revenue)
region product revenue cost
West Gadget 150 50
West Widget 200 50
West Gadget 300 100

Both ends count, the way SQL and dplyr both have it, so nothing here needs checking against a manual.