6 ms·
New Ruby 1.9 Features, Tips & Tricks
- JonnieCache 16y agoAlso there are lots of other lovely methods on Array and Enumerable: * Array * new method: * Array#keep_if * Array#repeated_combination * Array#repeated_permutation * Array#rotate * Array#rotate! * Array#select! * Array#sort_by! * extended methods: * Array#{uniq,uniq!,product} can take a block. * Enumerable * New methods: * Enumerable#chunk * Enumerable#collect_concat * Enumerable#each_entry * Enumerable#flat_map * Enumerable#slice_before http://rbjl.net/27-new-array-and-enumerable-methods-in-ruby-1-9-2-keep_if-chunk http://rbjl.net/27-new-array-and-enumerable-methods-in-ruby-...
- mapgrep 16y agokeep_if is like select! but slightly different; each_entry is like each but slightly different; flat_map is like map but slightly different. In no case are you saving more than a few keystrokes, yet any ruby coder who works with other ruby coders now has more language "surface area" to learn in order to read ruby. This, guys, is how Perl became Perl. Oy. keep_if is the truly maddening WTF eye-bleeding rage-inducing make-a-normally-calm-rubyist-very-stabby one. First off, it's a mutator but the name doesn't end in a bang. It should be keep_if! but for some random reason isn't. Yet another example of how the pleasant idea of using question marks for bool-returning methods (file.exists?) and exclamations for mutators (file.delete!) is just that -- a neat idea (very!) inconsistently applied and thus pointless. Ruby should use method punctuations consistently or get rid of them, for heaven's sake. keep_if is also egregious because it is the THIRD verb for doing basically the same thing. We already had find_all and select (synonyms) and now select! and, presumably, find_all!. So your workaday ruby coder gets to pick between find_all, select and keep_if to pick items out of an array based on truthiness of a callback. He gets to figure out which two are true synonymous and which is a near-synonym , and then wonder/research why you would ever want to use the near synonym. Which brings us to the third reason keep_all is egregious, which is that brings very, very little to the table. It is just like select! except it always returns the object, whereas select! returns the object except when no changes are made, in which case it returns nil. In this regard select! behaves like your other ruby mutators (string.sub! and string.gsub!, for example). Now this behavior, which keep_if was invented to circumvent, can be annoying in a very narrow range of circumstances, for example when you stick a mutator on a var at the end of a method and take it for granted that it will always return the thing it's mutating, as your return value, until one day your method is randomly returning nil and you have to delete a single character from your method to fix this. But 99/100 times the whole reason you are using a mutator is that you don't care about the return value just the side effect (the mutation); if you cared about the rv you would just use the non mutator. So keep_if is "fixing" a "problem" with an extremely minor scope and with an extremely easy programmer fix. Also, keep_if is a one off. In other words: If it's problematic that mutators in ruby return nil on non mutation, then the Correct Solution, i.e. the non aneurism inducing one, is either to change how ALL mutators work, say in 2.0, or to invent some kind of new standard alternate syntax like say a double bang or something. Because there are a LOT of mutators that work the way select! works. The way NOT to fix this (supposed) mutator problem is to invent a one off solution for one particular type of mutator, a solution that invents /a whole different name/ for the method it is altering, thus setting the precedent of sprawling the language. By the apparent reasoning behind keep_if we now need something called like, oh I don't know, "rewrite_all" to similarly be like-but-not-quite-like "gsub!". And "rewrite" to do same for "sub!", and so on and so on for the other mutators until ruby is getting nearly as bloated and unreadable as.... Perl. (Which I love and used to code in but, let's face it, has some mmmmmhowdoyousay -- issues? -- with readability.) So keep_if is a one-off inelegant language bloating solution to a non problem. That's egregiousness three. Egregiousness four is that keep_if was introduced at the same time as the thing it was invented to fix -- the (apparently sometimes) undesirable behavior of select!. select! was introduced.... at the same time as keep_if. Ugh. Facepalm. So it's not like I'm going to stop using ruby or anything, and it's not like anyone would care if I did, but I am going to have disagree with you a little here about these new methods being "lovely," in the sense that methods that will eventually send ruby spiralling into, at best, a /near brush/ with morbid, Perl-esque language obesity are not "lovely" /in my humble opinion./ Anyway sorry for the rant! (And Ruby 1.9 does, in general, rock the Casba, previous nothwithstanding.)
- ollysb 16y agoDoes feel a little like someone vandalised your car doesn't it. At this rate someones going to be writing "ruby, the good bits".
- loveatlonglast 16y agoNamed captures in regular expressions looks really nice! I'm especially excited to play with Oniguruma.
- masklinn 16y agoMost of it seems pretty nice (although I can hardly believe Ruby 1.8 does not have named groups), but... tip "Ruby 1.9 supports 4 ways to call a proc!" f =->n {[:hello, n]} p f[:ruby] # => [:hello, :ruby] p f.call(:ruby) # => [:hello, :ruby] p f.(:ruby) # => [:hello, :ruby] p f === :ruby # => [:hello, :ruby] wtf? Why are they writing that like it's a good thing?
- carbon8 16y agoAgreed. If there is anyone here who knows the justification for the latter two, please explain. Edit: found the explanation for the last one: http://www.aimred.com/news/developers/2008/08/14/unlocking_the_power_of_case_equality_proc/ http://www.aimred.com/news/developers/2008/08/14/unlocking_t... So, basically, it's just using it as a normal case equality operator and you generally shouldn't use it in place of a regular #call.
- farrel 16y agoProc#=== allows you to do this: def multiple_of( n ) lambda{ |x| x.modulo( n ).zero? } end case 10 when multiple_of( 3 ): puts "3!" when multiple_of( 4 ): puts "4!" when multiple_of( 2 ): puts "2!" end Basically you can now run code when checking case equality (===).
- petercooper 16y agoSince we're talking Ruby 1.9 here, that code won't even run :-( .. drop the colons and you're good though! :-) But if we're really talking Ruby 1.9, you could also go with: ->(x){ x % n == 0 }
- rue 16y agoOr, more simply: case $stdin.gets.chomp when lambda {|matchobj| matchobj.count("!") > 1 } puts "Quitcher yelling!" when "hi" puts "Hi yourself" end
- philwelch 16y ago
- viggity 16y agoNamed captures are a great way to document your regular expressions. Don't use the "#" notation to comment on what the regex is doing, just name the group instead! .Net has had them for a long, long time and they are AWESOME! It'd be cool to see Ruby get something like a MatchEvaluator, too http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.matchevaluator.aspx http://msdn.microsoft.com/en-us/library/system.text.regulare... A MatchEvaluator lets you much more complicated regex find replace. Currently, find/replace only lets you re-order or remove groups or insert static text. A MatchEvaluator lets you handle what to replace the match with code - meaning you can call a webservice that will replace MM/DD/YY with the equivalent Mayan/Persian/Lunar date.
- igrigorik 16y agoSpeaking of named captures.. Something I didn't mention in the blog post, but a rather handy feature: ruby-1.9.2-p136 :011 > /My name is (?<first>\w+) (?<last>\w+)/ =~ "My name is Ilya Grigorik" ruby-1.9.2-p136 :012 > first "Ilya" ruby-1.9.2-p136 :013 > last "Grigorik"
- rue 16y ago> Currently, find/replace only lets you re-order or remove groups or insert static text. I must be misunderstanding you, but that's obviously incorrect. "foo 1 bar 2".gsub(/\d+/) {|m| m.to_i * 2 } 1.8 also. Does MatchEvaluator bring more to the table?
- viggity 16y agothat looks exactly like a match evaluator, so it looks like ruby does have that ability. Awesome.
- timmorgan 16y ago"stabby proc" -- sweet name for the new -> proc syntax.
- briandoll 16y agoor perhaps better yet: "stabda"
- pyrhho 16y agoConspicuously missing is the brilliant new Proc.curry method! For those that don't know currying is a method that returns another Proc with one fewer argument, so you can do: multiply = Proc.new { |x, y| x * y } multiply_by_five = multiply.curry(5) multiply_by_five.call(3) # => 15
- deleted 16y ago[deleted]
- riffraff 16y agoUseful little thing: Object#tap. But Mostly, no mention of Fibers? :)