What's an Example of Ruby Code That's "Too Clever"

What's an example of Ruby code that's too clever?

After giving a straight answer to your question, I'd like to also dispute the premise; whenever a group of programmers characterizes the users of another language in this way, the odds are that they are telling you more about themselves than about the community they are describing.

You could, for example, accuse c programmers of being too obsessed with low level details, or haskell programmers with being blinded by their desire for functional purity; perl mongers for brevity, etc. But you would, IMHO, by getting the causality backwards when you do so.

When I want to write a program that is best expressed in a certain style, I try to choose a language that supports that style. Sometimes you want a tool that lets you do unusual things, and for such a task having a language such as ruby is as valuable as having mathematica for math or javascript for browser manipulation in your toolkit. If I want to play with typography I hop into postscript because that's what it's best at.

It's like saying "Have you ever noticed that people who use power drills are always poking holes in things?" It's true, but it kind of misses the point.

Best practice for handling null strings from database (in Java)

If you are using any ORM tool or somehow you map your DB fields to Java bean you can allways have:


public void setFoo(String str) {
this.foo = str != null ? str : "";
}

Ruby Code Translation Request

Wow. That's some ugly ruby.

So num here is actually a String (the tip offs being the use of the #sub and #=~ methods.

list is an Array of

  • Regexp objects and/or
  • pairs of Regexp and replacement String objects.

If none of the given Regexps match the string, the method returns nil.

If an unpaired Regexp matches the string, the method returns that Regexp.

If a paired Regexp matches the string, the method substitutes the part of the string
that the Regexp matches with the paired replacement text, and returns the modified String.

Once a Regexp matches the string, the method returns - no later Regexps are considered.

In no cases is the original String modified.

It's really a franken-method, IMHO, since it's trying to do very different things.

An example call:

 in_list("abe lincoln", [ [/linc/, 'zelda'] ]) #=> "abe zeldaoln"
in_list("abe lincoln", [ [/linc/] ]) #=> /linc/
in_list("abe lincoln", [ [/link/] ]) #=> nil

Really, with that multitude of return types, it seems like more of a pain in the ass than it's worth.

In pseudo-code


DEF IN-LIST( text, regexps )
FOREACH regexp IN regexps
IF HAS-MATCH( text, regexp )
IF HAS-REPLACEMENT-TEXT( regexp )
RETURN REPLACE-MATCHED-PORTION( text, regexp, GET-REPLACEMENT-TEXT(regexp) )
ELSE
RETURN regexp
ENDIF
ENDIF
ENDFOREACH
RETURN NOTHING-FOUND
ENDDEF

But like I said, this is some ugly-ass ruby. I'd avoid using it. It's a codesmell that tells me there's a whole lot wrong with this code.

If I had an array of Regexps, and wanted to find the first one that matched some text, I'd do:

# general case
regexps.find { |re| text =~ re }
# example
[ /earn/, /more/, /sessions/, /by/, /sleaving/ ].find { |re| "A baby?" =~ re } # would return /by/

If I had an collection of Regexp, replacement text pairs, and I wanted to replace the first match in some text, I'd do this

# general case
text_dupe = text.dup
pairs.find { |re,replace| text_dupe.sub!( re, replace ) }
# example
text_dupe = "One two three four".dup
[ [/ape/, 'frog'], [/our/, 'my'] ].find { |re,replace| text_dupe.sub!( re, replace } } # would return "One two three fmy"

I'd rather use a Hash for the last actually, but since that loses the order the original list came in (and who am I to say
that's not important, not knowing how it's used), I didn't.

If this code is not a joke, how on earth does it work?

EDIT: The person who posted the original obfuscated example gave the actual source code in his answer. He also posted a corrected version of the obfuscated code, because as I noted, some of it didn't make sense even when you removed the funky syntax.

That is some nicely obfuscated code. As with most obfuscated code, it's mostly a lot of ternary operators and a stubborn refusal to put in whitespace where a normal person would. Here is basically the same thing written more normally:

class Tree
def initialize(*d)
@d, = d # the comma is for multiple return values,
# but since there's nothing after it,
# all but the first are discarded.
end
def to_s
@l || @r ? ",>" : @d
end
def total
total = @d.is_a?(Numeric) ? @d : 0
total += @l.total if @l
total += @r.total if @r
end
def insert(arg)
if @d
if @l
@l.insert(arg)
else
@l = Tree.new(arg)
end
else
@d = arg
end
end
end

The insert method is not syntactically valid (it's missing a method name at one part), but that's essentially what it does as far as I can tell. The obfuscation in that method is pretty thick:

  1. Instead of just doing @l = whatever, it uses instance_variable_get() and instance_variable_set(). Even worse, it aliases instance_variable_get() to just be g().

  2. It wraps most of the functionality in a lambda function, to which it passes the name of the @l. Then it calls this function with the lesser-known syntax of func[arg1, arg2], which is equivalent to func.call(arg1, arg2).

Why is split(' ') trying to be (too) smart?

It's consistent with Perl's split() behavior. Which in turn is based on Gnu awk's split(). So it's a long-standing tradition with origins in Unix.

From the perldoc on split:

As another special case, split emulates the default behavior of the
command line tool awk when the PATTERN is either omitted or a literal
string composed of a single space character (such as ' ' or "\x20" ,
but not e.g. / / ). In this case, any leading whitespace in EXPR is
removed before splitting occurs, and the PATTERN is instead treated as
if it were /\s+/ ; in particular, this means that any contiguous
whitespace (not just a single space character) is used as a separator.
However, this special treatment can be avoided by specifying the
pattern / / instead of the string " " , thereby allowing only a single
space character to be a separator.

How to find more clever algorithm to check pairs of primes to see if paired they produce another prime?

Your efficiency problem is that you are attempting to find target prime numbers by construction of a very large set of possibilities and filtering by results. The set of all building blocks and their combinations is much larger than the available targets, so you spend a huge amount of time constructing the combinations, only to filter almost all of them out.

It makes more sense to start the work from a set of possible target "combined" prime numbers. You know that these target numbers must decompose into two smaller primes. A strategy based on that would work loosely as follows:

  • Generate a list of primes up to some target number - one million (or perhaps 10 million). This can be done pretty quickly, e.g. Prime.take(75000)

  • Use that list to generate split (opposite of concatenate) arrays of allowed pairs. From Prime.take(75000) there are 23494 such pairs, with 7216 unique primes and that list can be generated in a few seconds - contrast that with the number of items you were trying to work with in your original code.

  • Obviously don't take that list of 7216 primes and use it directly, you'd be back where you started. Instead, use the list of pairs you generated to create an efficient search for a group of 5 which satisfies your constraints. Think of the properties that such a group of 5 would have that you could test using the list of valid pairs.

I hope that gives you enough to start again. I am not going to supply the remainder of this solution or any Ruby code, since I think it reduces the value of the Euler challenge.

Why do people say that Ruby is slow?

Why is Ruby considered slow?

Because if you run typical benchmarks between Ruby and other languages, Ruby loses.

I do not find Ruby to be slow but then
again, I'm just using it to make
simple CRUD apps and company blogs.
What sort of projects would I need to
be doing before I find Ruby becoming
slow? Or is this slowness just
something that affects all programming
languages?

Ruby probably wouldn't serve you well in writing a real-time digital signal processing application, or any kind of real-time control system. Ruby (with today's VMs) would probably choke on a resource-constrained computer such as smartphones.

Remember that a lot of the processing on your web applications is actually done by software developed in C. e.g. Apache, Thin, Nginx, SQLite, MySQL, PostgreSQL, many parsing libraries, RMagick, TCP/IP, etc are C programs used by Ruby. Ruby provides the glue and the business logic.

What are your options as a Ruby
programmer if you want to deal with
this "slowness"?

Switch to a faster language. But that carries a cost. It is a cost that may be worth it. But for most web applications, language choice is not a relevant factor because there is just not enough traffic justify using a faster language that costs much more to develop for.

Which version of Ruby would best suit
an application like Stack Overflow
where speed is critical and traffic is
intense?

Other folks have answered this - JRuby, IronRuby, REE will make the Ruby part of your application run faster on platforms that can afford the VMs. And since it is often not Ruby that causes slowness, but your computer system architecture and application architecture, you can do stuff like database replication, multiple application servers, loadbalancing with reverse proxies, HTTP caching, memcache, Ajax, client-side caching, etc. None of this stuff is Ruby.

Finally, I can't find much news on
Ruby 2.0 - I take it we're a good few
years away from that then?

Most folks are waiting for Ruby 1.9.1. I myself am waiting for Rails 3.1 on Ruby 1.9.1 on JRuby.

Finally, please remember that a lot of developers choose Ruby because it makes programming a more joyful experience compared to other languages, and because Ruby with Rails enables skilled web developers to develop applications very quickly.



Related Topics



Leave a reply



Submit