Hacker News new | past | comments | ask | show | jobs | submit login
Ruby Trick Shots (rubyreloaded.com)
200 points by wlll on Feb 7, 2012 | hide | past | web | favorite | 30 comments

One handy trick that I've found a lot of people don't know:

There's often the problem when working in IRB that you want to run a command that will produce a huge amount of output. For example, you might be reading a large file and assigning its value to a variable:

    s = File.read("largefile.txt")
This can take a long time, as you wait for Ruby to print the entire contents to the terminal. However, this can be avoided by using a semicolon and another statement:

    s = File.read("largefile.txt"); 0
Now the only thing printed out to the terminal will be 0, but s will still get the contents of largefile.txt.

> However, this can be avoided by using a semicolon and another statement:

Just a semicolon is sufficient, actually.

Also, importantly, it's not a statement, it's an expression (which is why you see the return value of your read to begin with).

A semicolon is not exactly sufficient-- it leaves the expression open, and thus unexecuted, until you close it. Try `puts 1;` vs. `puts 1;0`.

This confused the hell out of me when I came from MatLab to Ruby. I thought the semicolon was working like in MatLab to just suppress output. It wasn't... Many bugs ensued!

Having now watched the video, if someone had told me that '_' in irb was equivalent to 'ans' in MatLab, I would have been very happy.

Ohh, you're giving me ideas now. How great would it be to have a whole panoply of "[language a] for [language b] developers" videos or articles ;-) I know of a few but still..

You're quite right! irb does indeed do that… I've been using pry, which handles it ‘correctly’.

In that case, I'd say we're both right-- though it's an open question what's the "right" behavior.

Also, importantly, it's not a statement, it's an expression (which is why you see the return value of your read to begin with)

This needs to be drilled into the heads of everyone learning Ruby. Saves much head-scratching later on.

Ruby: Objects, messages, and expressions. (Mostly)

Pry[1] will less (and pretty print, for hashes and such) returns, not to mention it's other tricks.

[1] http://pry.github.com

Pry is in exactly the same basket as awesome_print in terms of awesomeness, IMHO. It just did make my genuinely random selection for this video but will definitely be in the finished item :-)

Another neat IRB trick is to put a useful expression after the semicolon, like in your case s.length. This is especially useful on, say, the Rails console.

Also keep in mind that Ruby can evaluate lots of different expressions, so if say you calculated a number "n" and expect that there are "n" records that meet a given query, you can go:

    stuff = SomeModel.somescope; stuff.size == n
and Ruby will just say "true" or "false".

Neat, works in the CoffeeScript REPL too, thanks!

Nice trick, thanks!

This also works in node. Doesn't work in python though -- python just displays both values.

I wonder if this saves time because Ruby does lazy file i/o.

Terminal output is just really slow.

A couple tricks that are specific to MRI and probably not useful for everyday programming:

1. Get the bytecode for some code:

    irb(main):001:0> x = RubyVM::InstructionSequence.new '1 + 1'
    => <RubyVM::InstructionSequence:<compiled>@<compiled>>
    irb(main):002:0> puts x.disasm
    == disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
    0000 trace            1                                               (   1)
    0002 putobject        1
    0004 putobject        1
    0006 opt_plus         <ic:1>
    0008 leave            
    => nil
2. Output parser states and debugging information:

    $ ruby -y -e'1 + 1'
(The output is long so I haven't pasted it. :-) )

I've seen #1 before but never remember it so I want to include it. And #2.. that's one that's new to me. Yay for Ruby things :-)

With Rubinius, you can use the compile subcommand:

    $ bin/rbx compile -A -S -B -e '1 + 1'  # A(ST), S(exp), B(ytecode)

Any chance of a command-line session transcript instead?

I suspect there may be some interesting content here, but this is the kind of thing where I just hate screencasts. I can't skim it to see if these are things I already know or care to know, and even if they are it'll take me half an hour to get through, when I could probably read through the command-line session in 5 minutes.

When I do a video like this, usually someone does something like that within a few hours(!) but if not, I can do one. That said, it will all be on the Web eventually - the video was just to promote the effort (and put me on the line to finish it ;-))

As a list, though, it digs into: random numbers from a range, awesome_print, curious concatenation, fiddle, simple substring presence, spaces as string literal delimiters, multiple module inclusion, shorthand for ivar interpolation, ruby syntax checking, ruby syntax analysis with ripper, chained ifs, "next" as Proc's return, zipping arrays, exploding ranges into arrays, json output, __method__, multi line chaining, _ in irb, checking set bits, params defaulting to other params, Proc#source_location, prepending to a string in place, accessing the current source file as data, and some regex tricks.

Er, sign up for the free e-book?

Nice collection. The weird concatenation, I suspect, is a part of the grammar. It's frequently used in C code as well, when the format string is too long to fit in one line.

    printf("%d ... blah blah blah"
           "%f ...", 1, 1.2);

It actually works for string literals only, so you can't do a real concatenation there, with a variable for example. In C it's done at compile time, so you never actually concat those strings, the literals are merged. From what I see it's the same in ruby:

  irb(main):001:0> a = "avs"
  => "avs"
  irb(main):002:0> "sada" "sadasd"
  => "sadasadasd"
  irb(main):003:0> "sada" "sadasd" "sda"
  => "sadasadasdsda"
  irb(main):004:0> "sada" "sadasd" a
  SyntaxError: compile error
  (irb):4: syntax error, unexpected tIDENTIFIER, expecting $end
        from (irb):4
        from :0

Thanks for the video Peter, seems interesting.

Also seems mainly like a foot-shooting manual so far!

But it's certainly true that I didn't know a number of these behaviors!

Also seems mainly like a foot-shooting manual so far!

Could be, but a key value for examples of stuff you'd probably be better off not using very often is in learning why things behave as they do.

The idea of Technical books on Kindle is not new. I have converted numerous Sitepoint PDF books to Kindle format and read them on the Kindle AND on my computer using the Kindle app for Mac. I loved the video and PROMISE to buy the Kindle book when it is available.

Yeah, I'm discovering that now, lol. My "research" consisted entirely of searching for "ruby" and going through the first few pages. They were nearly entirely Kindle versions of established print books. Turns out.. Amazon prefers to feature books that actually sell ;-)

I've since discovered some cheap indie Kindle programming books and even a whole range of cheap O'Reilly "What is *?" books. So it seems there's a market but IMHO not a very mature one, so I look forward to giving it a go. Thanks for the support!

For the array zip one @14:20, I'm surprised he didn't briefly mention that you can use unpacking in the block parameters:

    names = ['fred', 'bill']
    ages = [33, 40]
    locations = ['san francisco', 'dubai']
    names.zip(ages, locations) do |n, a, l|
      puts n
      puts "lives in " + l
      puts "is #{a} years old"

Awesome :-)

FULL kudos to Peter Cooper for this.

Ruby is such an amazing and zany roadtrip of a language ... these few little gems have got me hungry for more. Its awfully addictive when you realise you can do so much with so little.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact