Output Field Separator in Ruby

Chris Oliver asked on LinkedIn:

Spotted this in the Rails source today. The trailing comma made me think it was a typo at first glance but it uses the $, global variable for nil instead of nil directly. Anyone know the reason for this?

I left a comment there, but I wanted to preserve it here as well:

There is no “global variable for nil”. $, is the “output field separator”. Known as OFS in AWK, it is known shorthand-mnemonically as $, in both Perl and Ruby – the mnemonic being that “comma” is a very common output field separator (think: comma-separated values). The default value of “nil” simply means “no separator”. But setting it to something else can be quite useful!

For example, to use Ruby from the command-line to convert my /etc/passwd file to CSV, sure you could do this (nowadays; there wasn’t always a stdlib CSV library – thanks, James Edward Gray!)

ruby -retc -rcsv -e 'Etc.passwd { puts CSV.generate_line it.to_a }'

But you don’t need the CSV library when you can do this:

ruby -retc -e '$,=","; $\="\n"; Etc.passwd{ print *it }'

(We are also setting the Output Record Separator, $\, here)

This reflects a bygone UNIX-style of record-processing in which “how to recognize/format a record” was separated from “where to find or write the records”. Modern front-end programmers may recognize this pattern as a kind of rudimentary stylesheet: first define how to display values; then separately produce the semantic values themselves.

So to pop the stack back to the original question, the Rails codebase is not setting sep to nil; it is setting it to “the current global output field separator” in order to comply with programmer expectations.

This mnemonic variable is deprecated in Ruby 4.0; as always, in any non-one-liner context it is preferable to use the English module aliases e.g. $OUTPUT_FIELD_SEPARATOR.

Leave a Reply

Your email address will not be published. Required fields are marked *