8 ms·
Ruby Tips, Part 5
- danso 12y agoSomething in my computer-science-student background feels unsettled when I can use a language for years and still learn new tricks (or often, that I've forgotten that I've learned) about common functionality such as string interpolation...but I do love a lot of Ruby's tricks. if path =~ %r{^/assets/mobile/img} ... end I knew about `%r` but hadn't realized that it escapes forward-slashes while leaving other regex symbols intact. But with the previous explanation of `%q`, in which arbitrary delimiters can be used, it makes sense...curly braces simply replace `/` as the delimiter, and `/` simply retains its non-specialness in regex...saves me a lot of writing `Regex.escape("/path/to")`. Another regex notation that I recently learned (elsewhere) and now love to abuse: "He is 32-years old"[/\d+/] # => "32" as opposed to: "He is 32-years old".match(/\d+/)[0]
- petercooper 12y agoThe extension of that can also be handy and is often overlooked. Contrived example: "28 men are 32 years old"[/(\d+) (year|day|month)/, 1] # => "32"
- Xylakant 12y agoYou can also use Regexp.new("/foo/bar") to achieve the desired result but the %r{} shortcut is handier.
- omaranto 12y agoThis explanation of how %r works here is incorrect: > I knew about `%r` but hadn't realized that it escapes forward-slashes while leaving other regex symbols intact. The correct explanation can also be found in the next sentence of your comment: > But with the previous explanation of `%q`, in which arbitrary delimiters can be used, it makes sense...curly braces simply replace `/` as the delimiter, and `/` simply retains its non-specialness in regex.
- jebus989 12y agoNot sure arbitrary regex delimiters can be counted as one of "Ruby's tricks" given they've been implemented in sed for maybe 4 decades?
- rickdale 12y agoThese are some good tips. If you are into the Ruby language and want more, I recommend checking out Ruby Tapas http://www.rubytapas.com/ http://www.rubytapas.com/ . I have no affiliation with it, just happy customer.
- bstar77 12y agoMy favorite Ruby resources: http://www.confreaks.com http://www.confreaks.com | http://www.rubytapas.com http://www.rubytapas.com | https://www.destroyallsoftware.com/screencasts https://www.destroyallsoftware.com/screencasts | http://railscasts.com http://railscasts.com (dated but still useful) | https://www.ruby-toolbox.com https://www.ruby-toolbox.com
- riffraff 12y agonotice that this is wrong x ||= y # equivalent to: x || x = y it's actually something slightly different (or at least it was some years ago).
- matsadler 12y agoHere's an example that shows x ||= y behaves like x || x = y, rather than x = x || y class Foo def foo=(object) puts "foo= called with #{object.inspect}" @foo = object end def foo puts "foo called" @foo end end puts "x || x = y" a = Foo.new a.foo || a.foo = 1 a.foo || a.foo = 2 puts "\nx = x || y" b = Foo.new b.foo = b.foo || 1 b.foo = b.foo || 2 puts "\nx ||= y" c = Foo.new c.foo ||= 1 c.foo ||= 2 This outputs: x || x = y foo called foo= called with 1 foo called x = x || y foo called foo= called with 1 foo called foo= called with 1 x ||= y foo called foo= called with 1 foo called and you can see that the output for ||= matches the output for x || x = y
- riffraff 12y agoI didn't mean that it is "x = x || y", I meant "it's completely ad hoc". For example, if you try "x || x = y" you will get an exception if x is not defined, but "x ||= y" will work fine. The same is true of constants "X || X = 1" will explode while "X ||= 1" will work fine.
- ultimoo 12y agoI think growing a string with << is an expensive operation. Since once the allocated memory is full, it will cost O(n) to copy the entire string to a new location. If we are carrying out m insertions, this could take O(mn). The way I have been building strings is to store the m strings in an Array and then join() it at the end (which should be only O(n)). The m small objects need to be allocated in both cases, the only difference being that we hold on to those and join them later on. Am I missing something? I have never measured the performance on either of the these operations so I could be off the mark here.
- matsadler 12y agoFor the cases I have benchmarked concatenation with << has been faster than join on an array. Here's a simple benchmark: require "benchmark" n = 100_000 Benchmark.bm(4) do |x| x.report("<<") do n.times do "aaaaa " << "bbbbbb " << "ccccc " << "ddddd " << "eeeee " << "fffff" end end x.report("join") do n.times do ["aaaaa", "bbbbbb", "ccccc", "ddddd", "eeeee", "fffff"].join(" ") end end end The results I get for this are: user system total real << 0.140000 0.000000 0.140000 ( 0.143750) join 0.230000 0.000000 0.230000 ( 0.228035) I'd be interested to see if there were any use cases where the relative performance was reversed.
- xentronium 12y agorequire "benchmark" n = 100_000 A = "foo " * 20 B = "bar " * 20 C = "baz " * 20 D = "foobar " * 20 STRINGS = [A, B, C, D] Benchmark.bm(4) do |x| x.report("<<") do n.times do "" << A << B << C << D end end x.report("join") do n.times do STRINGS.join end end end user system total real << 0.090000 0.010000 0.100000 ( 0.102411) join 0.070000 0.010000 0.080000 ( 0.071142)