5 ms·
1) If you're reading bad code, that could be a problem. But 99% of Ruby code I read has been written by people who know when they need parentheses/brackets to m
by ashleyw 16y ago
1) If you're reading bad code, that could be a problem. But 99% of Ruby code I read has been written by people who know when they need parentheses/brackets to make the code readable (e.g. when it's not the only code on the line.) But there are tons of times when it's wonderful to be able to leave out the parentheses.
-
2) It might be because I spend a lot of time with Ruby, but I much prefer `end`s to curly brackets, they're just easier on the eyes, especially when they're going to take up the entire line anyway:
a
b
c
d
end
end
end
end
a {
b {
c {
d {
}
}
}
}
Of course, at times I wish Ruby used indentation to declare structure, like Python.
-
3) I don't think I've ever had that problem. If I'm calling `person.full_name`, I don't care if that's a variable, or a method joining first_name and last_name. And if I it was a method, ideally I'd have a corresponding `full_name=(str)` method defined too, so `person.full_name = "Joe Bloggs"` would work, and split the string into the first, last, and optional middle names.
-
4) Why? Why not? What makes this easier to read?
puts "Bankrupt" if balance <= 0.0
Ruby is a lot like the English language; when you're learning it as a second language, you're constantly confused and frustrated by it's weird syntax, but once you get past those initial hurdles, it just clicks. I love Ruby because I never feel like I'm programming in it, it almost feels like pseudo code that's not going to actually execute.
Essentially you could get any non-programmer to solve a problem on paper, and turn it into Ruby code which, without too much fuss, describes their process.
# get the customers text file
# each customer is on their own line, w/ their name and age separated by a comma
# group the customers by age
# show me the top 3 most common ages
file = File.open('customers.txt')
customers = []
file.each_line do |line|
name, age = line.split(",")
customers << {:name => name, :age => age.to_i}
end
grouped_ages = customers \
.group_by{ |c| c[:age] } \
.map{ |c| [c[0], c[1].size] } \
.sort_by(&:last) \
.reverse
grouped_ages.first(3).each do |age, size|
puts "#{age} years old: #{size} customers"
end
Four blocks of reasonably clean code (except the 3rd, that could be cleaned up a bit), which implement the four lines of plain english instructions.
- anthonyb 16y ago>I love Ruby because I never feel like I'm programming in it, it almost feels like pseudo code that's not going to actually execute. Uh, you realise that describes any high level language, right? Ruby scores pretty low on the readability scale, about halfway between Perl and Python, but I find it's more familiarity with a particular language that determines how readable people find things. Here's a quick Python version. The main thing to notice is that while the overall flow/structure is similar, I don't have a lot of { } << \ characters hanging around, and I don't have to chain blocks together since I have list comprehensions. from collections import defaultdict customer_file = (line.strip().split(',') for line in file('customers.txt')) grouped_ages = defaultdict(list) for name, age in customer_file: grouped_ages[age].append(name) age_lengths = sorted( [(len(names), age) for age, names in grouped_ages.items()], reverse=True ) for length, age in age_lengths[:3]: print "%s years old: %s customers" % (age, length)
- ataggart 16y ago>Uh, you realise that describes any high level language, right? I'm inclined to agree. I think the following also pretty closely matches the english requirements. (with-open [rdr (reader "customers.txt")] (->> (line-seq rdr) (map #(second (.split % ","))) (group-by identity) (map (fn [[age coll]] [age (count coll)])) (sort-by second (comparator >)) (map first) (take 3)))
- anthonyb 16y agoLooks kinda nasty to me, but then I'm not too familiar with Clojure/Lisp/whatever-the-hell-that-is ;) I think one of the side effects of learning a Lisp is that you get a bit blasé about using map. Do you find list comprehensions easier than map/filter? Is there a list comprehension equivalent in Lisp, or would you have to write your own?
- ataggart 16y agoIt's clojure. As for preference, given that map, filter, etc., are lazy, I like the clear visibility of each step working on each element of the sequence. Clojure has a list comprehension, for, though using it here is more trouble than it's worth since you have to group and sort, both of which require you to step outside the comprehension and work on the whole list; that's why your code has multiple sections. Instead, I see the example as just a selection/transformation process on sequences of data. Each step in the clojure code takes and returns a sequence of values (the ->> macro weaves them together): 0. a sequence of lines from a file 1. a sequence of age strings 2. a sequence of [age, [ages...]] tuples 3. a sequence of [age, count] tuples 4. a sequence of [age, count] tuples sorted by count desc 5. a sequence of age strings 6. a sequence of up to 3 age strings Fun detail: The with-open macro is akin to python's with statement, supports arbitrary number of items, is closed in reverse order of their appearance, and didn't require a change to the language to implement ;)