C54b1538124ee5c6f3af5f628e1750dc

This is a tiny bit of code I wrote just to display a general case. What I want to do is replace the value in biggest_square if another value is bigger. the problem is that this way, it will calculate square(base) twice for every base, one to compare and one to assign. An alternative is to assign the value to a temporary variable, but that's not really clean either.

Is there a way to do both the comparison and assignment in one?

ruby

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Simple method to calculate the square of a number
def square(number)
  return number**2
end

# Variable to be assigned the biggest square value
biggest_square = 0

# Iterate over a list of base numbers and compare their squared values to biggest_square, and replace if bigger.
[1,4,3,5].each do |base|
  # Compare values
  if square(base) > biggest_square
    # Assign new value
    biggest_square = square(base)
  end
end

# Alternative
[1,4,3,5].each do |base|
  temp = square(base)
  if temp > biggest_square
    biggest_square = temp
  end
end

Refactorings

No refactoring yet !

F04aeb28129f653b207e8b5d92706096

Amos King

September 21, 2008, September 21, 2008 15:11, permalink

4 ratings. Login to rate!

Don't forget you Enumberable functions. Use max.

1
2
3
4
5
6
7
8
9
10
11
# Simple method to calculate the square of a number
def square(number)
  return number**2
end

# Variable to be assigned the biggest square value
biggest_square = 0

[1,4,3,5].each do |base|
  biggest _square = [biggest_square, square(base)].max
end
5071c5b861341c0dcfcf6ac86327701f

Tien Dung

September 21, 2008, September 21, 2008 15:43, permalink

3 ratings. Login to rate!

I prefer using temp variable for PERFORMANCE. For me, the # Alternative code is already clean and clear.

If your concern is lines of code. Here is one line assignment using temp variable refactoring.

1
2
3
4
5
6
7
8
9
def square(number)
  return number**2
end

biggest_square = 0

[1,4,3,5].each do |base|
  (temp = square(base)) > biggest_square && biggest_square = temp
end
5071c5b861341c0dcfcf6ac86327701f

Tien Dung

September 21, 2008, September 21, 2008 15:58, permalink

4 ratings. Login to rate!

Refactor Amos King .max function version

1
2
3
4
5
def square(number)
  return number**2
end

biggest_square = [1,4,3,5].map{|base| square(base)}.max
C54b1538124ee5c6f3af5f628e1750dc

ruphin.myopenid.com

September 21, 2008, September 21, 2008 15:58, permalink

No rating. Login to rate!

Thanks, I was already looking into something like putting them both in an array and taking the highest value, but it seemed like too much hassle to me. That last one also looked good, I'll probably put it in some more lines for readability though. Thanks.

5071c5b861341c0dcfcf6ac86327701f

Tien Dung

September 21, 2008, September 21, 2008 16:19, permalink

No rating. Login to rate!

Don't know who vote 1 star for my "one line assignment using temp variable refactoring". Please tell me why you think it's bad. As I said the original code is perfect for me. That refactoring is in case your concern is lines of code.

880cbab435f00197613c9cc2065b4f5a

danielharan

September 21, 2008, September 21, 2008 16:23, permalink

3 ratings. Login to rate!

Tien Dung's last function is crystal clear. If you have a function that's as predictable as square though, you can do:

1
2
3
4
5
def square(number)
  return number**2
end

biggest_square = square([1,4,3,5].max)
C54b1538124ee5c6f3af5f628e1750dc

ruphin.myopenid.com

September 21, 2008, September 21, 2008 19:10, permalink

No rating. Login to rate!

Don't know who downvoted, I gave a 5, I hadn't thought of && myself.

880cbab435f00197613c9cc2065b4f5a

danielharan

September 21, 2008, September 21, 2008 19:38, permalink

No rating. Login to rate!

Tien - I voted 5 for your 2nd refactoring, 1 for the 1st.

The 1st is bad because 1 - it's still procedural and 2- it's hard to read. The '&&' operator is generally only used for boolean operations rather than chaining assignment or other operations with side-effects. Consider the three statements for which you find more readable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
biggest_square = 0
[1,4,3,5].each do |base|
  (temp = square(base)) > biggest_square && biggest_square = temp
end

# Using a loop w/ temp variable to avoid [].max sorting through the whole array
# (yes, I would leave the above line as a comment
# explaining *why* Enumerable methods weren't used)
biggest_square, temp = 0
[1,4,3,5].each do |base|
  biggest_square = temp if (temp = square(base)) > biggest_square
end

# Procedural style, split for clarity, self-commenting
squares        = [1,4,3,5].collect {|e| square(e) }
biggest_square = squares.max
5071c5b861341c0dcfcf6ac86327701f

Tien Dung

September 21, 2008, September 21, 2008 22:31, permalink

No rating. Login to rate!

Thanks Daniel. I found the last one is more readable and self-commenting. Nice refactoring.

1e8f141e7857d397d8020ed3b759e88a

Maciej Piechotka

September 21, 2008, September 21, 2008 23:45, permalink

2 ratings. Login to rate!

@danielharan:

Well - -100 < 10 but (-100)** > 10**2 as 10000 > 100.

@Tien Dung:

Sorry for voting 1 on the second refactoring. I meant 5 but clicked in wrong place. Do anybody knowns how to change it?

880cbab435f00197613c9cc2065b4f5a

danielharan

September 21, 2008, September 21, 2008 23:53, permalink

No rating. Login to rate!

Maciej, nice catch, that doesn't handle negatives.

I'll ask Marc-André to add a feature: the ability to change ratings!

5071c5b861341c0dcfcf6ac86327701f

Tien Dung

September 22, 2008, September 22, 2008 00:01, permalink

No rating. Login to rate!

Hi Daniel, can you ask Marc-Andre for comment on rating also. For me the reason or thinking behind a refactoring or a rating is more important than the code or the rating itself.

5071c5b861341c0dcfcf6ac86327701f

Tien Dung

September 22, 2008, September 22, 2008 01:27, permalink

1 rating. Login to rate!

temp variable based version using inject function.

1
2
3
4
5
def square(number)
  return number**2
end

biggest_square = [1,4,3,5].inject(0){ |max, base| (temp = square(base)) > max ? temp : max }
880cbab435f00197613c9cc2065b4f5a

danielharan

September 22, 2008, September 22, 2008 16:34, permalink

1 rating. Login to rate!

I sent MA a link to your request :)

Inject is a good choice here.

1
biggest_square = [1,4,3,5].inject(0){ |memo, i| [memo, square(i)].max }
A8d3f35baafdaea851914b17dae9e1fc

Adam

September 22, 2008, September 22, 2008 17:46, permalink

No rating. Login to rate!
1
biggest_square = [ 1, 4, 3, 5 ].max { |a,b| a.abs <=> b.abs } ** 2

Your refactoring





Format Copy from initial code

or Cancel