Why I Like Ruby
blog.wekeroad.com
blog.wekeroad.com
For me, if you write "if (myvariable != null) { }" or "unless(myvariable.nil?) end" doesn't make a difference. In fact, if I were to read it as English "if my variable is not null do" sounds better than "unless my variable is null, question mark?" -- I'm actually puzzled how you would "read" that.
In any case, my argument is that a translation from code -> mental model is more efficient than code -> English -> mental model, in which case expressiveness is only helpful in as much as it helps in parsing the code and not "reading" it in English.
display_warning() if problem_condition()
feels much more expressive in some situations than if(problem_condition) display_warning()
The later just emphasizes the primary activity to me - again, in some circumstances. It's something I miss now that I'm not doing Ruby anymore. if (condition) consequence();
You're able to "run" the condition in your head and step into the consequence without loss of pace. But when you put the consequence before the condition, you will have to backtrack. backtrack = true unless consequence.signifies? :block_end
It doesn't seem that much harder to read.To avoid excessive test coverage it would be more pragmatic to do:
backtrack = (consequence.signifies? :block_end) ? false : true
But that's not as easy to read :(A lot of software engineering lore crumbles into tautologies or is completely obviated when you're working at the microscopic level.
Yes, you're right that my mental model of the 'if' construct will be basically the same in any language, but it's fundamentally less work and less error prone for me to translate ruby than some other language into that model, and the same is true going the other direction
include 'rspec'
your_point.disagree do
the_example.in_ruby = "if myvariable"
me.think do
this_thing(the_example.in_ruby).is(:more_readable)
end.because do
that_thing.expresses(the_example.in_ruby.what_its_doing.minimalist_core)
end
me.could do
using "blub" do
self.say "IfConditionIsTrue(myVariable.booleanValueOfNullStatus())"
end
end.implying do
self.last_statement.is(:crazy_talk)
end
end
your_point.agree do
constructs = languages.map do |language|
in language do
me.mental_models.find_by_name("The If Construct")
end
end
constructs.should be_identical
end.with_caveat do
languages.min do |language|
in language do
me.mental_models.find_all
return me.mental_strain
end
end.should == "Ruby"
endend.should be "Ruby"
Not only that, but most of the time, the expression could simply be written "if myvariable; ...; end", seeing as the vast majority of the time, we only care if the thing we're testing is falsy.
Ruby does give you the tools to be very expressive, indeed almost conversational in your coding style, but it also gives you enough rope to hang yourself.
So this would be a no-no:
unless ($this > $that) {
do_something();
}
He's happy they're used to postfix statements however he says that these should only be used for flow control. For eg. for my $i (@list) {
next unless $i % 2 == 0;
do_something();
}So last example should be:
for my $i (@list) {
next if not $i % 2 == 0;
do_something();
}
Personally I don't follow the bible to the letter :) I do use prefix & postfix unless but only with simple truth conditions like this: unless ($this) { ... }
next unless $this;The idea is lets leave the brainpower for the hard problems, and not require you to use all that brainpower to figure out the plumbing.
resources :people do
resource :avatar
member do
get :republish_deep_links
post :resend
put :accessible_projects, :upload_preference
end
end
That code sets up various URL paths in a Rails app. It maps URLs like /people/george/resend to the proper controller in the MVC framework.In many other languages, you could set up an API like this, but instead of taking a block, the "resources" function would have to accept some sort of nested data structure. That gets you pretty far, but what about when you want to do something that the parser of that data structure didn't expect? Usually you can't.
But in Ruby, code is data and you can do whatever you want in those blocks. You could do this, for example:
resources :people do
resource :avatar
member do
["apple", "orange", "peach"].each do |fruit|
get "eat_" + fruit
end
end
end
That would map /people/george/eat_apple, /people/george/eat_orange, and /people/george/eat_peach.And maybe that's not that impressive to you, but you can inject arbitrary code in there. That's what people mean when they talk about expressiveness.
Examples of this are everywhere in the Ruby world. Check out HAML and assert_select.
APIs + Rigid data structures = Pain and suffering
APIs + Ruby blocks = Flexibility and power
Case 1 - His examples are toys, I don't think there's really an argument here. Better examples might convince.
Case 2 - This is less about the language and more about the tools and the culture. The ecosystem in C# land is focused much more heavily in the business / enterprise direction which personally I hate. Point to Ruby.
Case 3 - Half a point maybe. The .Net library is actually pretty good and each version of C# brings the language a step closer to the sort of concise code he shows. You can certainly get very close with a few wrappers here and there.
Case 4 - Meta Programming, oh yes. 10 points to Ruby. It has been said elsewhere that C# doesn't have meta programming because it was designed to be predictable for whoever has to read it. In practice this seriously restricts our ability to express certain types of concepts that don't fit the basic OO model. Aspect oriented programming and mix-ins are the two currently frustrating me.
We try to tackle this with all sorts of hacks (e.g. PostSharp, mangling .dlls after compilation) but they don't fit well with the rest of the tools.
This means lots of boiler plate repetition we can't kill. Microsoft likes to use code generation for this which I also hate.
"It's clear that C# isn't the best language to use for Web Development. Just ask the guys who are writing the frameworks with it."
Sure C# is verbose. But I still feel it's pretty expressive. I'm working on a web framework in C# (http://github.com/ecoffey/Bebop). Granted it's totally a toy thing, but still. Looks beautiful to me :-P
Also it annoys me he compares non-idiomatic C# with idiomatic Ruby.
I guess I should quote this FTA: "My whole point here is to tell you why I like it - not to convince you of anything.", and finish with it all comes back to the right tool for the job shrug.
Specifically: a null check.
my_variable.andand.do_whatever
It would seem to me that verbosity and expressiveness are opposites - a language which inherently uses many lines to express an action is a language which inherently expresses little per line. How could it be otherwise?
> a language which inherently uses many lines to express an action is a language which inherently expresses little per line
Depends on what you an action is. It's nice working in a language where each thing does one thing and one thing only. A single line that does numerous things at once can get pretty crazy, with magical processes spreading pixie dust over your data.
In C# or Java, you'll have to define exactly how your dicts nest and everything (or give up type safety), and that means you have a much lower flexibility.
Finally, C-inherited Java are dreadful at string munging. Which is understandable, they don't really like strings after all, but again the wider web deals with strings a lot (if not almost exclusively), that means one more clash.
Sinatra doesn't have all that. A combination of Heroku, Sinatra, and DataMapper (nice, cleaner, simpler alternative to active record) and what you have is a very easy to deploy application.
I'm doing the above, and doing it on Windows (sorry, I'd love to use Linux but my wife uses this machine when I'm not and has some apps that are not replaceable, and I don't want to mess around with dual booting. So when I get FU money I'll be Linux all the way).
If you have any questions I'd be glad to help.
Git also comes with a SVN bridge, which works wonderfully for me.
Also ... Rails has its own development web-server. You don't need to have a production environment to learn it.
And I really recommend that when learning about any web framework, in any language ... just learn how to deploy a production server by yourself. It saves a lot of pain later on ;)
Not to mention that I wouldn't use Heroku ... sure they provide a valuable service, but personally I get a cheaper deal by getting EC2 instances and configuring them myself. It's hard the first time, but then you can scale your infrastructure easily ... EC2 is wonderful in that regard.
The pragmatic book mentions something about kcode (I think), but Rails seems to use something else. Back when I last tried, I couldn't find any definite answers to this.
Maybe Ruby 1.9 solves this problem - but is it ready yet? Again, last I tried, there wasn't even a MySQL driver for it.
raise "Hey dude! Where's My Variable Assignment" if my_variable.nil?
I really hate raising an exception like that. I am surprised Rubyists like it like he says they do. my_variable or raise 'Hey dude! Where's My Variable Assignment'
or else: my_variable.nil? and raise 'Hey dude! Where's My Variable Assignment'
since it puts what's being tested in front like with if/then but is also syntactically light-weight.