zhifu ge - how to be weird in ruby - with notes

77
How To Be Weird The Idiomatic Ruby Ways

Upload: ottawaruby

Post on 11-Jan-2017

235 views

Category:

Technology


1 download

TRANSCRIPT

How To Be WeirdThe Idiomatic Ruby Ways

https://www.youtube.com/watch?v=5MgBikgcWnY

It takes 20 hours of deliberate practice to be reasonably good at something, anything.

The Algorithm of Rapid Ruby Acquisition

1. Learn enough to self-correct

2. Practice at least 20 hours

Practice at least 20 hourscodeeval.com

The second step is easy. There are numerous online resources for you to practice. One example of them is codeeval.com

Learn enough to self-correctlisten to this talk

The first step, however, is easier. You only have to listen to this talk. That’s recursion right there

Learn enough to self-correct

• Assignment

• Naming

• Control Expressions

• Methods

Assignment

Weirdness #1 Parallel Assignment

a = 'foo'b = 'bar'c = 'baz'd = 'foobar'

Instead of doing this:You can do:

a, b, c, d = 'foo', 'bar', 'baz', 'foobar'

this:but just because you can doesn’t mean you should: readability is bad

a = 'foo'b = 'bar'

a, b = b, a

good 1: swap variable assignment

def multi_return [1, 2]end

a, b = multi_return

good 2: multiple return values from a method

Naming

Weirdness #2 Method names can end with ?s

they return a boolean

examples• String#empty?

• String#include?

• String#start_with?

• String#end_with?

• Array#empty?

• Array#include?

• Range#include?

• Object#respond_to?

• Object#nil?

• Object#is_a?

Obejct#is_a? synonymous kind_of?/instance_of?

Control Expressions

Weirdness #3 everything has a Boolean value

Every expression in Ruby evaluates to an object, and every object has a Boolean value of either true or false? true and false are objects

if 0 puts “0 is true”else puts “0 is false”end

what is the output?

Only two objects has a false value, nil and false itself

Every expression in Ruby evaluates to an object, and every object has a Boolean value of either true or false? true and false are objects

Weirdness #4 if statements return a value

if(condition1) { result = x;} else if(condition2) { result = y;} else { result = z;}

In Java

if condition1: result = xelif condition2: result = yelse: result = z

In Python

In Ruby if statements return a value

The evaluation of the last executed statement.

result = if condition1 x elsif condition2 y else: z end

In Ruby

Exercise

what is the value of result?result = if true puts “hello” “hello” else “world” end

“hello”

what is the value of result?result = if false “hello” else “world” puts “world” end

nil

The evaluation of the last executed statement.

Weirdness #5 the unless keyword

if !condition do_somethingend

negative condition unless

unless condition do_somethingend

Observation: Ruby cares about readability

so much so that (Weirdness #6)

Ruby has modifier if/unless

so this is not good enough

if !condition do_somethingend

negative condition unless

unless condition do_somethingend

so this is not good enough

do_something if !condition

negative condition unless

do_something unless condition

this isQuestion: which one is better? Choose unless over if with negative condition

Weirdness #7 iterators

iterators help you iterate

how to do an infinite loop?

iterators help you iterate

while(true) { doSomething(); if(condition1) { break; }

if(condition2) { continue;}

}

In Java

while True: do_something() if condition1: break if condition2: continue

In Python

loop do do_something break if condition1 next if condition2end

In Ruby

loop is a method, not a keyword

loop do do_something break if condition1 next if condition2end

Kernel#loop repeatedly executes the block.We call this kind of ruby methods iterators. They take a block, and execute the block repeatedly.

how to do something a certain number of times?

iterators help you iterate

for(int i = 0; i < 10; i++) { doSomething();}

In Java

for i in range(10): do_something()

In Python

10.times do somethingend

In Ruby

10.times do |i| puts iend

5.upto(10) do |i| puts iend

10.downto(1) do |i| puts iend

Weirdness #8 iterators - Array and String

how to iterate an array?

iterators help you iterate

for(int i : a) { doSomething(i);}

In Java

for i in a: do_something(i)

In Python

a.each do |i| do_something(i)end

In Ruby

demoalso demo each_with_index

how to iterate a String?

iterators help you iterate

In Java

String s = “hello";

for(int i = 0; i < s.length(); i++) { System.out.println(s.charAt(i));}

In Python

s = “hello"

for c in s: print c

In Ruby

s = “hello"

s.each_char do |char| puts charend

demoalso demo: how to print index of each char

Methods

Weirdness #9 method calls

parenthesis are optional when calling methods

puts “hello” puts(“hello”)

Omit parentheses when:Omit parentheses around parameters for methods that are part of an internal DSL (e.g. Rake, Rails, RSpec), methods that have "keyword" status in Ruby (e.g. attr_reader, puts) and attribute access methods. Use parentheses around the arguments of all other method invocations.

omit parentheses when:

• there are no arguments

• the method is part of internal DSL

• the method has “keyword status”

attr_reader, puts, print

Omit parentheses when:Omit parentheses around parameters for methods that are part of an internal DSL (e.g. Rake, Rails, RSpec), methods that have "keyword" status in Ruby (e.g. attr_reader, puts) and attribute access methods. Use parentheses around the arguments of all other method invocations.

Weirdness #10 methods can take blocks

a lot of ruby methods take blocks

add 1 to every element in an array

In Java

int[] a = {1, 2, 3};

for(int i = 0; i < a.length; i++) { a[i]++;}

In Python

a = [1, 2, 3]

for i in range(len(a)): a[i] += 1

In Ruby

a = [1, 2, 3]

a = a.map { |i| i + 1 }

DemoArray#collect = Array#mapInvokes the given block once for each element of self.change every int to string

get the sum of all elements in an array

In Java

int[] a = {1, 2, 3};

int sum = 0;for(int i = 0; i < a.length; i++) { sum += a[i];}

In Python

a = [1, 2, 3]

sum = sum(a)

In Ruby

a = [1, 2, 3]

sum = a.inject { |a, e| a + e }

DemoEnumerable#reduce = Enumerable#injectshortcut: inject(:+)

Rails flavoured Minitest cases

class SomeControllerTest < ActionController::TestCase test “should do stuff” do assert_equal 2, 1 + 1 end def test_should_do_stuff assert_equal 2, 1 + 1 endend

Weirdness #11 implicit return in methods

a lot of ruby methods take blocks

the evaluated object of the last executed expression in a method is implicitly returned to the caller

Every expression in Ruby evaluates to an object,

def greet puts “hello” “hello”end

what is returned?

def greet “hello” puts “hello”end

def greet return “hello” puts “hello”end

References:

The Well-Grounded Rubyist by David A. Black

Ruby Style Guidehttps://github.com/bbatsov/ruby-style-guide

Thanks@ZhifuGe

codingdojo.io