What does "$," mean in ruby? - ruby

I stumbled upon this piece of code in the rails source:
# File actionpack/lib/action_view/helpers/output_safety_helper.rb, line 30
def safe_join(array, sep=$,)
sep ||= "".html_safe
sep = ERB::Util.html_escape(sep)
array.map { |i| ERB::Util.html_escape(i) }.join(sep).html_safe
end
What does $, do? I read the Regexp-documentation but I couldn't find anything about it.

The official documentation for the system variables is in:
http://www.ruby-doc.org/stdlib-2.0/libdoc/English/rdoc/English.html
A lot of Ruby's special variables are accessible via methods in various modules and classes, which hides the fact that the variable is what contains the value. For instance, lineno, available in IO and inherited by File, is the line number of the last line read by an IO stream. It's relying on $/ and $.
The "English" module provides long versions of the cryptic variables, making it more readable. Use of the cryptic variables isn't as idiomatic in Ruby as they are in Perl, which is why they're more curious when you run into them.
They come from a variety of sources: most, if not all, are immediately from Perl, but Perl inherited them from sed, awk, and the rest of its kitchen-sink collection of code. (It's a great language, really.)
There are other variables set by classes like Regexp, which defines variables for pre and post match, plus captures. This is from the documentation:
$~ is equivalent to ::last_match;
$& contains the complete matched text;
$` contains string before match;
$' contains string after match;
$1, $2 and so on contain text matching first, second, etc capture group;
$+ contains last capture group.
Though Ruby defines the short, cryptic, versions of the variables, it's recommended that we use require "English" to provide the long names. It's a readability thing, which translates to a long-term ease-of-maintenance thing.

I finally found the answer myself here:
The output field separator for the print. Also, it is the default separator for Array#join. (Mnemonic: what is printed when there is a , in your print statement.)
The following code snippet shows the effect:
a = [1,2,3]
puts a.join # => 123
$, = ','
puts a.join # => 1,2,3

Related

What does $/ mean in Ruby?

I was reading about Ruby serialization (http://www.skorks.com/2010/04/serializing-and-deserializing-objects-with-ruby/) and came across the following code. What does $/ mean? I assume $ refers to an object?
array = []
$/="\n\n"
File.open("/home/alan/tmp/blah.yaml", "r").each do |object|
array << YAML::load(object)
end
$/ is a pre-defined variable. It's used as the input record separator, and has a default value of "\n".
Functions like gets uses $/ to determine how to separate the input. For example:
$/="\n\n"
str = gets
puts str
So you have to enter ENTER twice to end the input for str.
Reference: Pre-defined variables
This code is trying to read each object into an array element, so you need to tell it where one ends and the next begins. The line $/="\n\n" is setting what ruby uses to to break apart your file into.
$/ is known as the "input record separator" and is the value used to split up your file when you are reading it in. By default this value is set to new line, so when you read in a file, each line will be put into an array. What setting this value, you are telling ruby that one new line is not the end of a break, instead use the string given.
For example, if I have a comma separated file, I can write $/="," then if I do something like your code on a file like this:
foo, bar, magic, space
I would create an array directly, without having to split again:
["foo", " bar", " magic", " space"]
So your line will look for two newline characters, and split on each group of two instead of on every newline. You will only get two newline characters following each other when one line is empty. So this line tells Ruby, when reading files, break on empty lines instead of every line.
I found in this page something probably interesting:
http://www.zenspider.com/Languages/Ruby/QuickRef.html#18
$/ # The input record separator (eg #gets). Defaults to newline.
The $ means it is a global variable.
This one is however special as it is used by Ruby. Ruby uses that variable as a input record separator
For a full list with the special global variables see:
http://www.rubyist.net/~slagell/ruby/globalvars.html

Convert Ruby string to *nix filename-compatible string

In Ruby I have an arbitrary string, and I'd like to convert it to something that is a valid Unix/Linux filename. It doesn't matter what it looks like in its final form, as long as it is visually recognizable as the string it started as. Some possible examples:
"Here's my string!" => "Heres_my_string"
"* is an asterisk, you see" => "is_an_asterisk_you_see"
Is there anything built-in (maybe in the file libraries) that will accomplish this (or close to this)?
By your specifications, you could accomplish this with a regex replacement. This regex will match all characters other than basic letters and digits:
s/[^\w\s_-]+//g
This will remove any extra whitespace in between words, as shown in your examples:
s/(^|\b\s)\s+($|\s?\b)/\\1\\2/g
And lastly, replace the remaining spaces with underscores:
s/\s+/_/g
Here it is in Ruby:
def friendly_filename(filename)
filename.gsub(/[^\w\s_-]+/, '')
.gsub(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
.gsub(/\s+/, '_')
end
First, I see that it was asked purely in ruby, and second that it's not the same purpose (*nix filename compatible), but if you are using Rails, there is a method called parameterize that should help.
In rails console:
"Here's my string!".parameterize => "here-s-my-string"
"* is an asterisk, you see".parameterize => "is-an-asterisk-you-see"
I think that parameterize, as being compliant with URL specifications, may work as well with filenames :)
You can see more about here:
http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize
There's also a whole lot of another helpful methods.

Ruby Array#puts not using overridden implementation?

I am using Ruby 1.8.6 for the following code:
# Create an array and override the #to_s on that object
thing = [1,2,3]
def thing.to_s
'one'
end
print "Using print: "
print thing
puts
puts "Using puts: "
puts thing
Output:
Using print: one
Using puts:
1
2
3
So thing is an Array and I have overridden thing#to_s. print seems to use my overriden implementation while puts does not. Why?
I have followed the source code of Kernel#puts and Kernel#print (which are C-implementations) and see that they are very different implementations. I want to know what might be the design-decision (if any) behind this?
By the way, if I create thing as an instance of another class I wrote (or as a Hash/String/other-classes I tried), both print and puts use the overridden implementation of to_s.
Oh boy ... This has already been the topic of a countless number of endless threads on the ruby-talk mailinglist, the ruby-core mailinglist and a gazillion of blogs.
The gist of it is that puts special cases Arrays. Why it special cases those, why it special cases only those (as opposed to, say, all Enumerables), why it special cases those (and not, say, print), nobody really knows. It is the way it is.
BTW, since you mentioned the POLS: the Ruby community has always made it very clear that the POLS only applies to matz. So, Ruby is about not surprising matz. If you or me or anybody else is surprised, that doesn't count.
From the Ruby Programming Language:
alt text http://ecx.images-amazon.com/images/I/41n-JSlBHkL._SL75_.jpg
Output streams are appendable, like strings and arrays are, and you can write values to them with the << operator. puts is one of the most common output methods. It converts each of its arguments to a string, and writes each one to the stream. If the string does not already end with a newline character, it adds one. If any of the arguments to puts is an array, the array is recursively expanded, and each element is printed on its own line as if it were passed directly as an argument to puts. The print method converts its arguments to strings, and outputs them to the stream. If the global field separator $, has been changed from its default value of nil, then that value is output between each of the arguments to print. If the output record separator $/ has been changed from its default value of nil, then that value is output after all arguments are printed.
As for design decisions, that I do not know.

Why are there so many slightly different ways to do the same thing in Ruby?

I am learning Ruby. My background is C++/Java/C#. Overall, I like the language, but I am a little confused about why there are so many different ways to accomplish the same thing, each with their own slightly different semantics.
Take string creation, for example. I can use '', "", q%, Q%, or just % to create strings. Some forms support interpolation. Other forms allow me to specify the string delimiters.
Why are there five ways to create string literals? Why would I ever use non-interpolated strings? What advantage does the % syntax have over quoted literals?
I know there must be value in the redundency in Ruby, but my untrained eyes are not clearly seeing it. Please enlighten me.
Why would I ever use non-interpolated strings?
When you don't want the interpolation, of course. For example, perhaps you're outputting some documentation about string interpolation:
'Use #{x} to interpolate the value of x.'
=> "Use #{x} to interpolate the value of x."
What advantage does the % syntax have over quoted literals?
It lets you write strings more naturally, without the quotes, or when you don't want to escape a lot of things, analogous to C#'s string-literal prefix #.
%{The % syntax make strings look more "natural".}
=> "The % syntax makes strings look more \"natural\"."
%{<basket size="50">}
=> "<basket size=\"50\">"
There are many other %-notations:
%w{apple banana #{1}cucumber} # [w]hitespace-separated array, no interpolation
=> ["apple", "banana", "\#{1}cucumber"]
%W{apple banana #{1}cucumber} # [W]hitespace-separated array with interpolation
=> ["apple", "banana", "1cucumber"]
# [r]egular expression (finds all unary primes)
%r{^1?$|^(11+?)\1+$}
=> /^1?$|^(11+?)\1+$/
(1..30).to_a.select{ |i| ("1" * i) !~ %r{^1?$|^(11+?)\1+$} }
=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
%x{ruby --version} # [s]hell command
=> "ruby 1.9.1p129 (2009-05-12 revision 23412) [x86_64-linux]\n"
There's also %s (for symbols) and some others.
Why are there five ways to create string literals?
This isn't terribly unusual. Consider C#, for example, which has several different ways to generate strings: new String(); ""; #""; StringBuilder.ToString(), et cetera.
I'm not a Ruby expert, but had you ever heard the term "syntactic sugar" ? Basically some programing languages offer different syntax to accomplish the same task. Some people could find one way easier than others due to his previous programing/syntax experience.
The original question is why there are so many slightly different ways of doing things in Ruby.
Sometimes the different things are sensible: quoting is a good case where different behaviour requires different syntax - non/interpolating, alternate quoting characters, etc. - and historical accidence causes synonyms like %x() vs ``, much as in Perl.
The synonym issue - [].size [].length [].count - feels like an attempt to be helpful in a world where the language is too random for IDEs to be able to help: monkey-patching and the weird combination of strict but dynamic typing together make runtime errors an inevitable and frustrating part of the coding, so folks try to reduce the issue by supplying synonyms. Unfortunately, they end up confusing programmers who're accustomed to different methods doing different things.
The 'so similar but not quite' issue, for example ...
$ ruby -le 'e=[]; e << (*[:A, :B])'
-e:1: syntax error, unexpected ')', expecting :: or '[' or '.'
$ ruby -le 'e=[]; e << *[:A, :B]'
-e:1: syntax error, unexpected *
$ ruby -le 'e=[]; e.push(*[:A, :B])'
$
... can only really be viewed as a flaw. Every language has them, but they're usually more arcane than this.
And then there's the plain arbitrary 'use fail instead of raise unless you're just rethrowing an exception' nonsense in the Rubocop coding standards.
There are some nice bits in Ruby, but really - I'd far rather be coding in something better-founded.
In most situations, you'll end up using normal string delimiters. The main difference between single and double quotes is that double quotes allow you to interpolate variables.
puts 'this is a string'
# => this is a string
puts "this is a string"
# => this is a string
v = "string"
puts 'this is a #{v}'
# => this is a #{v}
puts "this is a #{v}"
# => this is a string
%q and %Q are useful when you can't use quotes because they are part of the internal string.
For example, you might end up writing
html = %Q{this is a <img src="#{img_path}" class="style" /> image tag}
In this case, you can't use double quotes as delimiters unless you want to escape internal attribute delimiters. Also, you can't use single quote because the img_path variable won't be interpolated.
A lot of ruby's syntax is derived from perl's, like using q to quote a few words into a string. That probably is the main reason for such a big variety.
One more reason is a minor performance boost for non-interpolated strings. Using '' vs "" means that Ruby doesn't have to consider what's inside the string at all. So you'll see people using single quotes for array keys or symbols because they're faster. For what it's worth I'll include a little benchmark.
require 'benchmark'
Benchmark.bmbm(10) do |x|
x.report("single-quote") do
for z in 0..1000000
zf = 'hello'
end
end
x.report("double-quote") do
for z in 0..1000000
zf = "hello"
end
end
x.report("symbol") do
for z in 0..1000000
zf = :hello
end
end
end
yields:
Rehearsal ------------------------------------------------
single-quote 0.610000 0.000000 0.610000 ( 0.620387)
double-quote 0.630000 0.000000 0.630000 ( 0.627018)
symbol 0.270000 0.000000 0.270000 ( 0.309873)
--------------------------------------- total: 1.580000sec
You would use non-interpolated strings if your string contains a lot of special characters (like backslashes, #{} etc.) and you don't want to escape all of them.
You'd use different delimiters if your string contains a lot of quotes that you'd otherwise have to escape.
You'd use heredocs if your strings has a lot of lines which would make normal string syntax look unwieldy.
Ruby borrows constructs and ideas from lots of languages. The two most apparent influences are Smalltalk and Perl.
Depending on your comfort with Smalltalk or Perl you may well choose different constructs to do the same thing.
Along the lines of John's answer:
In quick hacks, I often end up running a perl or sed one-liner with grep syntax from within my ruby script. Being able to use %[ ] type syntax means that I can simply copy-paste my regexp from the terminal

how to convert strings like "this is an example" to "this-is-an-example" under ruby

How do I convert strings like "this is an example" to "this-is-an-example" under ruby?
The simplest version:
"this is an example".tr(" ", "-")
#=> "this-is-an-example"
You could also do something like this, which is slightly more robust and easier to extend by updating the regular expression:
"this is an example".gsub(/\s+/, "-")
#=> "this-is-an-example"
The above will replace all chunks of white space (any combination of multiple spaces, tabs, newlines) to a single dash.
See the String class reference for more details about the methods that can be used to manipulate strings in Ruby.
If you are trying to generate a string that can be used in a URL, you should also consider stripping other non-alphanumeric characters (especially the ones that have special meaning in URLs), or replacing them with an alphanumeric equivalent (example, as suggested by Rob Cameron in his answer).
If you are trying to make something that is a good URL slug, there are lots of ways to do it.
Generally, you want to remove everything that is not a letter or number, and then replace all whitespace characters with dashes.
So:
s = "this is an 'example'"
s = s.gsub(/\W+/, ' ').strip
s = s.gsub(/\s+/,'-')
At the end s will equal "this-is-an-example"
I used the source code from a ruby testing library called contest to get this particular way to do it.
If you're using Rails take a look at parameterize(), it does exactly what you're looking for:
http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html#M001367
foo = "Hello, world!"
foo.parameterize => 'hello-world'

Resources