Skip to content

Instantly share code, notes, and snippets.

@jnv
Created June 4, 2014 13:27
Show Gist options
  • Save jnv/93ddc7c1c34b134e84c2 to your computer and use it in GitHub Desktop.
Save jnv/93ddc7c1c34b134e84c2 to your computer and use it in GitHub Desktop.
Example IPython notebook with Ruby
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"language": "ruby",
"name": "",
"signature": "sha256:c08c33e4f6dd12b30ceea2cd7fa67d7010622164b0dbc2e596193669e7bb4f0a"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "heading",
"level": 1,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"2. Building Stones"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"## Source code\n",
"\n",
" git clone https://github.com/deric/mi-rub.git"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Methods and Messages"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"* In Ruby, every object can receive a *message*\n",
"* *Invoking a method* on an object means *sending a message* \u2013 with method name and optional arguments \u2013 to an object"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Calling public instance method\n",
"\"I just met you\".length"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 1,
"text": [
"14"
]
}
],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Dynamic invocation\n",
"what = :length\n",
"\"And this is crazy\".send(what)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 2,
"text": [
"17"
]
}
],
"prompt_number": 2
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# String also works\n",
"\"Here's my object\".send('length')"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 3,
"text": [
"16"
]
}
],
"prompt_number": 3
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Method Instantiation"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"* A method is also an object"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Let's instantiate a Method Object and call it\n",
"s = \"So call me, maybe\"\n",
"method_object = s.method(:length)\n",
"method_object.call\n",
"method_object.class"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 4,
"text": [
"Method"
]
}
],
"prompt_number": 4
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Also, pass an argument to call\n",
"method_object = s.method(:include?)\n",
"#method_object.call('maybe')\n",
"s.include? 'maybe'"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 5,
"text": [
"true"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "notes"
}
},
"source": [
"What happens if the string is changed?"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"s = 'meh'\n",
"# Still bound to original string\n",
"method_object.call('meh')"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 6,
"text": [
"false"
]
}
],
"prompt_number": 6
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Pure Object Approach"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"#### Java\u2122 Way\n",
"\n",
"```java\n",
"double value = -0.5;\n",
"Math.abs(value);\n",
"```"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"source": [
"Ruby Way"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"value = -0.5\n",
"value.abs"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 7,
"text": [
"0.5"
]
}
],
"prompt_number": 7
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"(-0.5).abs\n",
"-0.5.abs"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 8,
"text": [
"0.5"
]
}
],
"prompt_number": 8
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Available methods:\n",
"42.methods.count"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 9,
"text": [
"138"
]
}
],
"prompt_number": 9
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Strings"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"## Single quotes\n",
"\n",
"* Create `string` object\n",
"* Only `'` can be escaped\n",
"* Slightly faster"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"str = 'I\\'m sorry, I\\'m so sorry!'"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 10,
"text": [
"\"I'm sorry, I'm so sorry!\""
]
}
],
"prompt_number": 10
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Double quotes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* More powerful"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"str = \"I'm sorry, I'm so sorry!\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 11,
"text": [
"\"I'm sorry, I'm so sorry!\""
]
}
],
"prompt_number": 11
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Escape sequences\n",
"puts \"Also:\\ntabs!\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Also:\n",
"tabs!\n"
]
}
],
"prompt_number": 12
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Evaluated expression\n",
"\"I had #{'none'.upcase} beers\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 13,
"text": [
"\"I had NONE beers\""
]
}
],
"prompt_number": 13
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Escape sequences\n",
"\n",
"| sequence | meaning |\n",
"| ------------:| ------------------------ |\n",
"| `\\n` | new line |\n",
"| `\\t` | tab |\n",
"| `\\s` | space |\n",
"| `#{expression}` | evaluate Ruby expression |"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"String Interpolation"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"problems_count = 99\n",
"puts \"I got #{problems_count} problems\""
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"I got 99 problems\n"
]
}
],
"prompt_number": 14
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# C-like sprintf formatting\n",
"puts \"I got %s problems\".%(problems_count)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"I got 99 problems\n"
]
}
],
"prompt_number": 15
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"String Concatenation"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"str = \"Hello\"\n",
"name = \"Dave\"\n",
"puts \"#{str}, #{name}!\"\n",
"# Variables are converted to String (#to_s)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello, Dave!\n"
]
}
],
"prompt_number": 16
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"class Duck\n",
" def to_s\n",
" \"quack\"\n",
" end\n",
"end\n",
"puts \"#{Duck.new}\""
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"quack\n"
]
}
],
"prompt_number": 17
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Append-Concatenate\n",
"who = \"world\"\n",
"str = \"Hello \" << who\n",
"puts str"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Hello world\n"
]
}
],
"prompt_number": 18
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Integers are converted into Char!\n",
"i = 8173112\n",
"puts \"i = #{i}\"\n",
"puts \"i = \" << i"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"i = 8173112\n"
]
},
{
"ename": "RangeError",
"evalue": "invalid codepoint 0x7CB638 in UTF-8",
"output_type": "pyerr",
"traceback": [
"\u001b[31mRangeError\u001b[0m: invalid codepoint 0x7CB638 in UTF-8",
"\u001b[37m<main>:3:in `<main>'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/backend.rb:8:in `eval'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/backend.rb:8:in `eval'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/kernel.rb:110:in `execute_request'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/kernel.rb:62:in `run'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/command.rb:29:in `run_kernel'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/command.rb:15:in `run'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/bin/iruby:6:in `<top (required)>'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/bin/iruby:23:in `load'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/bin/iruby:23:in `<main>'\u001b[0m"
]
}
],
"prompt_number": 19
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### String Concat. with `+`\n",
"\n",
"Creates new String \u2013 can be slooow, esp. in cycles."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"\"Hello\" + \" \" + \"world\"\n",
"123.to_s + \"\\n\""
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 20,
"text": [
"\"123\\n\""
]
}
],
"prompt_number": 20
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Numbers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```\n",
"123 1_234 # Integers\n",
"123.45 1.2e-3 # Floating point\n",
"0xffff # Hex\n",
"0b01011 # Binary\n",
"0377 # Octal\n",
"```"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"1_234_56"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 21,
"text": [
"123456"
]
}
],
"prompt_number": 21
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Arithmetic Operators"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a, b = 4, 2"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 22,
"text": [
"[4, 2]"
]
}
],
"prompt_number": 22
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a + b"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 23,
"text": [
"6"
]
}
],
"prompt_number": 23
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a - b"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 24,
"text": [
"2"
]
}
],
"prompt_number": 24
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a * b"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 25,
"text": [
"8"
]
}
],
"prompt_number": 25
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a / b"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 26,
"text": [
"2"
]
}
],
"prompt_number": 26
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"b % a"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 27,
"text": [
"2"
]
}
],
"prompt_number": 27
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a ** b"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 28,
"text": [
"16"
]
}
],
"prompt_number": 28
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Array vs. Hash"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Array"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = Array.new"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 29,
"text": [
"[]"
]
}
],
"prompt_number": 29
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = []"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 30,
"text": [
"[]"
]
}
],
"prompt_number": 30
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Hash"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"h = Hash.new"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 31,
"text": [
"{}"
]
}
],
"prompt_number": 31
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"h = {}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 32,
"text": [
"{}"
]
}
],
"prompt_number": 32
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Double Pipe `||=`"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"if a == false\n",
" a = \"not false\"\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 33
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Conditional assignment: when left side uninitialized or `false`, assign the value from right side."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"a = nil\n",
"b = 20\n",
"a = a ? a : b\n",
"a ||= b\n",
"a"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 34,
"text": [
"20"
]
}
],
"prompt_number": 34
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Equivalent to this\n",
"a || a = b\n",
"# Or this\n",
"a = b if a.nil? || a == false"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [],
"prompt_number": 35
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"References"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo = \"A\"\n",
"foo.object_id"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "-"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 36,
"text": [
"70086912481620"
]
}
],
"prompt_number": 36
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"bar = foo\n",
"bar.object_id == foo.object_id"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 37,
"text": [
"true"
]
}
],
"prompt_number": 37
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo = \"A\"\n",
"bar = foo\n",
"bar = \"B\"\n",
"bar.object_id == foo.object_id\n",
"[foo, bar]"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 38,
"text": [
"[\"A\", \"B\"]"
]
}
],
"prompt_number": 38
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo = \"A\"\n",
"bar = foo.dup\n",
"bar.object_id == foo.object_id"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 39,
"text": [
"false"
]
}
],
"prompt_number": 39
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* `clone` \u2013 shallow copy of the object\n",
"* `dup` \u2013 shallow copy of the object, including its state"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Cloning Object"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Basic types, like `Fixnum`, `Float`, `TrueClass`, `FalseClass`, `NilClass` don't support cloning.\n",
"\n",
"`object_id` should be the same when the value is the same."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
":sym.object_id == :sym.object_id"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 40,
"text": [
"true"
]
}
],
"prompt_number": 40
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"\"A\".object_id == \"A\".object_id"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 41,
"text": [
"false"
]
}
],
"prompt_number": 41
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Mutable String"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo = \"yowzah\"\n",
"bar = foo\n",
"bar.upcase!\n",
"foo"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 42,
"text": [
"\"YOWZAH\""
]
}
],
"prompt_number": 42
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Immutability"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Immutable objects:\n",
"\n",
"* are thread safe\n",
"* make good hash keys \u2013 hash codes won't change\n",
"\n",
"Mutability is property of an *instance*, not of an entire class.\n",
"\n",
"<http://rubylearning.com/satishtalim/mutable_and_immutable_objects.html>"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo = \"yowzah\"\n",
"foo.freeze\n",
"#foo.upcase!\n",
"\n",
"bar = foo.dup\n",
"bar.upcase!"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 43,
"text": [
"\"YOWZAH\""
]
}
],
"prompt_number": 43
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Bang Methods!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo = \"GERONIMO\"\n",
"foo.downcase! # Modifies foo itself"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 44,
"text": [
"\"geronimo\""
]
}
],
"prompt_number": 44
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"foo = \"GERONIMO\"\n",
"bar = foo.downcase\n",
"[foo, bar]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 45,
"text": [
"[\"GERONIMO\", \"geronimo\"]"
]
}
],
"prompt_number": 45
},
{
"cell_type": "heading",
"level": 2,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Blocks"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Blocks\u2026\n",
"\n",
"* are objects (compare with Java)\n",
"* are extra paramaters to methods\n",
"* implement iterators\n",
"* implement closures"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Hello World! (again)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"5.times { print \"Odelay!\" }"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 46,
"text": [
"5"
]
}
],
"prompt_number": 46
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Alternative block syntax\n",
"5.times do\n",
" print \"Odelay!\"\n",
"end"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Odelay!"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 47,
"text": [
"5"
]
}
],
"prompt_number": 47
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Closures"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Closure is a function that refers to free variables in its lexical context\n",
"\n",
"* Blocks\n",
"* Procs\n",
"* Lambdas\n",
"* Method objects\n",
"\n",
"<http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/>"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Remember?\n",
"s = \"So call me, maybe\"\n",
"method_object = s.method(:length)\n",
"method_object.call"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 48,
"text": [
"17"
]
}
],
"prompt_number": 48
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"s = \"meh\"\n",
"puts method_object.call"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"17\n"
]
}
],
"prompt_number": 49
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Each"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Blocks can have parameters\n",
"\n",
"* `each` is the simplest iterator\n",
"* every item from the collection is passed to the block"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"[1, 2, 3].each {|x| print \"#{x}!\\n\" }"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1!\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2!\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3!\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 50,
"text": [
"[1, 2, 3]"
]
}
],
"prompt_number": 50
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Collect (Map)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* same as `each` (each item is passed to the block)\n",
"* result from the block is used to construct a new array"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"[\"H\",\"A\",\"L\"].collect { |x| x.succ}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 51,
"text": [
"[\"I\", \"B\", \"M\"]"
]
}
],
"prompt_number": 51
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Multiple Block Arguments"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"[1, 2, 3].each_with_index do |item, index|\n",
" print \"#{item} at #{index}!\\n\"\n",
"end.each do |item|\n",
" print item\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 at 0!\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2 at 1!\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3 at 2!\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 52,
"text": [
"[1, 2, 3]"
]
}
],
"prompt_number": 52
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Blocks can be stored and called later"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"cooler = Proc.new {|x| print \"#{x}% cooler.\"}\n",
"cooler.call(20)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"20% cooler."
]
}
],
"prompt_number": 53
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Remember kids, block is an object too!\n",
"cooler.methods"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 54,
"text": [
"[:call, :[], :===, :yield, :to_proc, :arity, :clone, :dup, :hash, :to_s, :inspect, :lambda?, :binding, :curry, :source_location, :parameters, :source, :comment, :pry, :__binding__, :pretty_print, :pretty_print_cycle, :pretty_print_instance_variables, :pretty_print_inspect, :nil?, :=~, :!~, :eql?, :<=>, :class, :singleton_class, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :pretty_inspect, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]"
]
}
],
"prompt_number": 54
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Procs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* *Procs* are bound to a set of local variables\n",
"* code may be called in different contexts"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def gen_times(factor)\n",
" Proc.new {|n| n*factor }\n",
"end\n",
"\n",
"# 'factor' is replaced with 3\n",
"times3 = gen_times(3)\n",
"times3.call(3)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 55,
"text": [
"9"
]
}
],
"prompt_number": 55
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"times5 = gen_times(5)\n",
"times5.call(3)"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 56,
"text": [
"15"
]
}
],
"prompt_number": 56
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"times3.call(times5.call(4)) # 3 * 5 * 4"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 57,
"text": [
"60"
]
}
],
"prompt_number": 57
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Yield"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Given block is executed in the method as if it were a method itself."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def twice\n",
" puts \"Method start\"\n",
" yield\n",
" yield\n",
" puts \"End of method\"\n",
"end\n",
"\n",
"twice do\n",
" puts \"In da block\"\n",
"end\n",
" "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Method start\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"In da block\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"In da block\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"End of method\n"
]
}
],
"prompt_number": 58
},
{
"cell_type": "heading",
"level": 4,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Block as an Extra Argument"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def who_says_what\n",
" yield(\"David\", \"Allons-y!\")\n",
" yield(\"Matt\", \"Geronimo!\")\n",
"end\n",
"\n",
"who_says_what do |person, phrase|\n",
" puts \"#{person} says #{phrase}\"\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"David says Allons-y!\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Matt says Geronimo!\n"
]
}
],
"prompt_number": 59
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Yield Fibonacci"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def fibonacci(max=Float::INFINITY)\n",
" return to_enum(__method__, max) unless block_given?\n",
" yield previous = 0\n",
" yield i = 1\n",
" while true\n",
" i, previous = previous + i, i\n",
" break if i > max\n",
" yield i\n",
" end\n",
" previous\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 60,
"text": [
":fibonacci"
]
}
],
"prompt_number": 60
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"fibonacci(100) {|i| puts i}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"8\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"13\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"21\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"34\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"55\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"89\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 61,
"text": [
"89"
]
}
],
"prompt_number": 61
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"1. `yield` keyword transfers control to the block\n",
"2. its argument becomes an argument to the block\n",
"3. once the block has finished, control transfers back to the method\n",
"4. the next line of code is executed"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Proc != Block?"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* Proc is a reusable code\n",
"* Abbreviation of \u201cprocedure\u201d"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def who_am_i(&block)\n",
" block.class\n",
"end\n",
"\n",
"who_am_i {}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 62,
"text": [
"Proc"
]
}
],
"prompt_number": 62
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Block Parameter as an Extra Argument"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def who_says_what(&block)\n",
" block.call(\"David\", \"Allons-y!\")\n",
" block.call(\"Matt\", \"Geronimo!\")\n",
"end\n",
"\n",
"who_says_what do |person, phrase|\n",
" puts \"#{person} says #{phrase}\"\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"David says Allons-y!\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Matt says Geronimo!\n"
]
}
],
"prompt_number": 63
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Callbacks"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def callbacks(procs)\n",
" procs[:starting].call\n",
" p \"Still going\"\n",
" procs[:finishing].call\n",
"end\n",
"callbacks(\n",
" :starting => Proc.new { p \"Start\" },\n",
" :finishing => Proc.new { p \"Finish\" }\n",
" )"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\"Start\""
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\"Still going\""
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\"Finish\""
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 64,
"text": [
"\"Finish\""
]
}
],
"prompt_number": 64
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Blocks vs. Procs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Block\n",
"\n",
"* Breaking code into smaller pieces\n",
"* Run multiple expressions atomically: database migrations, file output etc.\n",
"\n",
"### Proc\n",
"\n",
"* Reuse a block of code multiple times\n",
"* Method will have one or more callbacks"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Lambda Functions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"_Almost_ same as Procs\u2026"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Argument checking\n",
"pnew = Proc.new {|a, b, c| puts \"Gimme #{a}, and #{b}, and #{c.class}\" }\n",
"lamb = lambda {|a, b, c| puts \"Gimme #{a}, and #{b}, and #{c.class}\" }"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 65,
"text": [
"#<Proc:0x007f7cc345c670@<main>:2 (lambda)>"
]
}
],
"prompt_number": 65
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"pnew.call(1, 2) # More arguments, works fine"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Gimme 1, and 2, and NilClass\n"
]
}
],
"prompt_number": 66
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"lamb.call(2, 4) # Gimme an ArgumentError"
],
"language": "python",
"metadata": {},
"outputs": [
{
"ename": "ArgumentError",
"evalue": "wrong number of arguments (2 for 3)",
"output_type": "pyerr",
"traceback": [
"\u001b[31mArgumentError\u001b[0m: wrong number of arguments (2 for 3)",
"\u001b[37m<main>:2:in `block in <main>'\u001b[0m",
"\u001b[37m<main>:in `call'\u001b[0m",
"\u001b[37m<main>:in `<main>'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/backend.rb:8:in `eval'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/backend.rb:8:in `eval'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/kernel.rb:110:in `execute_request'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/kernel.rb:62:in `run'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/command.rb:29:in `run_kernel'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/command.rb:15:in `run'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/bin/iruby:6:in `<top (required)>'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/bin/iruby:23:in `load'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/bin/iruby:23:in `<main>'\u001b[0m"
]
}
],
"prompt_number": 67
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Different return behaviour\n",
"def proc_return\n",
" Proc.new { return \"Look, I am Proc!\" }.call\n",
" return \"This is not reached\"\n",
"end\n",
"puts proc_return"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Look, I am Proc!\n"
]
}
],
"prompt_number": 68
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def lambda_return\n",
" lambda { return \"LOL, lambda\" }.call\n",
" return \"This is printed. QED\"\n",
"end\n",
"puts lambda_return"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is printed. QED\n"
]
}
],
"prompt_number": 69
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Before Lambda\u2026"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Depending on `multiply` variable, we perform an addition or a multiplication of a `number`.\n",
"\n",
"Code is almost identical for both branches\u2026"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"number = 2\n",
"multiply = false\n",
"\n",
"if multiply\n",
" (1..10).collect{|n| n*number}\n",
"else\n",
" (1..10).collect{|n| n+number}\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 70,
"text": [
"[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]"
]
}
],
"prompt_number": 70
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"After Lambda\u2026"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"number = 2\n",
"multiply = false\n",
"\n",
"if multiply\n",
" calc = lambda {|n| n*number}\n",
"else\n",
" calc = lambda {|n| n+number}\n",
"end\n",
"puts (1..10).collect(&calc)"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n"
]
}
],
"prompt_number": 71
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"lamb = -> { puts \"a\" }\n",
"lamb.call"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"a\n"
]
}
],
"prompt_number": 72
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Method Objects"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Method object encapsulates a method.\n",
"\n",
"Behaviour similar to lambda functions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"```ruby\n",
"class Array\n",
" def iterate!(code)\n",
" self.each_with_index do |n, i|\n",
" self[i] = code.call(n)\n",
" end\n",
" end\n",
"end\n",
"\n",
"def square(n)\n",
" n ** 2\n",
"end\n",
"\n",
"array = [1, 2, 3, 4]\n",
"array.iterate!(method(:square))\n",
"```\n",
"\n",
" [1, 4, 9, 16]\n"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Summary: Blocks, Procs, Lambdas & Method Objects"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Proc\n",
"\n",
"* piece of code within a context\n",
"\n",
"### Blocks\n",
"\n",
"* unborned Procs, automatically converted to Proc objects during call\n",
"* an easy way for iteration and callback programming\n",
"\n",
"### Lambdas\n",
"\n",
"* provides function objects\n",
"* similar to anonymous functions\n",
"\n",
"### Method Objects\n",
"\n",
"* envelopes around methods\n",
"* useful for passing methods as parameters"
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Iterators"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Block as an Iterator"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"animals = %w( ant bee cat dog elk )\n",
"animals.each do |animal|\n",
" puts animal\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"ant\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"bee\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"cat\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"dog\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"elk\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 73,
"text": [
"[\"ant\", \"bee\", \"cat\", \"dog\", \"elk\"]"
]
}
],
"prompt_number": 73
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"For Loops Have Many Forms\u2026"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for animal in animals\n",
" puts animal\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"ant\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"bee\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"cat\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"dog\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"elk\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 74,
"text": [
"[\"ant\", \"bee\", \"cat\", \"dog\", \"elk\"]"
]
}
],
"prompt_number": 74
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Java\u2122 Way\n",
"\n",
"```java\n",
"for(int i = 1; i <= 10; i++) {\n",
" System.out.println(i);\n",
"}\n",
"```"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Ruby Way"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in 1..10\n",
" puts i\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"4\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"6\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"7\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"8\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"9\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 75,
"text": [
"1..10"
]
}
],
"prompt_number": 75
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"p [1,2] "
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[1, 2]"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 76,
"text": [
"[1, 2]"
]
}
],
"prompt_number": 76
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Java\u2122 Way\n",
"\n",
"```java\n",
"for(int i = 1; i < 10; i++) {\n",
" System.out.println(i);\n",
"}\n",
"```"
]
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Ruby Way"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"for i in 1...10\n",
" p i\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"4"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"6"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"7"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"8"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"9"
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 77,
"text": [
"1...10"
]
}
],
"prompt_number": 77
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"(1..10).to_a"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 78,
"text": [
"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]"
]
}
],
"prompt_number": 78
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Moar Iterators"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"10.times {|i| print \"#{i} \"}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"0 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"4 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"6 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"7 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"8 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"9 "
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 79,
"text": [
"10"
]
}
],
"prompt_number": 79
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"1.upto(10) {|i| print \"#{i} \"}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"2 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"4 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"6 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"7 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"8 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"9 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"10 "
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 80,
"text": [
"1"
]
}
],
"prompt_number": 80
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"1.step(10, 2) { |i| print \"#{i} \"}"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"1 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"3 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"5 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"7 "
]
},
{
"output_type": "stream",
"stream": "stdout",
"text": [
"9 "
]
},
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 81,
"text": [
"1"
]
}
],
"prompt_number": 81
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Exercise #1 \u2013 Iterators"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* write a method which accepts an array as a parameter and returns a new array of items with odd index\n",
"* if the block was supplied, yield the odd-indexed elements\n",
"* _hint:_ the method `block_given?` returns true if a method was invoked with a block"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def odd_elements(array)\n",
" # ???\n",
"end\n",
"\n",
"puts odd_elements([1,2,3,4,5,6])\n",
"# => [2, 4, 6]\n",
"odd_elements([1,2,3,4,5,6]) {|x| x**2 }\n",
"# => [4, 16, 36]"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"\n"
]
}
],
"prompt_number": 82
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Source Encoding"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If the source file contains non-ASCII characters, you should specify encoding:\n",
"\n",
" coding: UTF-8"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# coding: UTF-8\n",
"# encoding: UTF-8\n",
"# zencoding: UTF-8\n",
"# vocoding: UTF-8\n",
"# fun coding: UTF-8\n",
"# decoding: UTF-8\n",
"# 863280148705622662 coding: UTF-8 0072364213\n",
"\n",
"# It was the night before Christmas and all through\n",
"# the house, not a creature was coding: UTF-8,\n",
"# not even with a mouse."
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 83
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Protip:* Check out [magic_encoding](https://github.com/m-ryan/magic_encoding) gem."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Basic I/O"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I/O methods are implemented in `Kernel` module.\n",
"\n",
"`Kernel` provides these I/O methods: `gets`, `open`, `print`, `printf`, `putc`, `readline`, `readlines`.\n",
"\n",
"Base class for I/O objects i `IO` class."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"# Input from stdin\n",
"print \"Enter your name: \"\n",
"name = gets"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Enter your name: "
]
},
{
"ename": "Errno::ENOENT",
"evalue": "No such file or directory @ rb_sysopen - kernel",
"output_type": "pyerr",
"traceback": [
"\u001b[31mErrno::ENOENT\u001b[0m: No such file or directory @ rb_sysopen - kernel",
"\u001b[37m<main>:2:in `gets'\u001b[0m",
"\u001b[37m<main>:2:in `gets'\u001b[0m",
"\u001b[37m<main>:2:in `<main>'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/backend.rb:8:in `eval'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/backend.rb:8:in `eval'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/kernel.rb:110:in `execute_request'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/kernel.rb:62:in `run'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/command.rb:29:in `run_kernel'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/lib/iruby/command.rb:15:in `run'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/lib/ruby/gems/2.1.0/gems/iruby-0.1.9/bin/iruby:6:in `<top (required)>'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/bin/iruby:23:in `load'\u001b[0m",
"\u001b[37m/home/j/.rbenv/versions/2.1.1/bin/iruby:23:in `<main>'\u001b[0m"
]
}
],
"prompt_number": 84
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Working With Files"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"File is automatically closed when leaving the block."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"File.open(\"testfile\",\"w\") do |f|\n",
" f << \"test line 1\\n\" << \"test line 2\\n\"\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 85,
"text": [
"#<File:testfile (closed)>"
]
}
],
"prompt_number": 85
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"File.open(\"testfile\",\"r\") do |f|\n",
" puts f.readlines.collect {|x| x.chomp}\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[\"test line 1\", \"test line 2\"]\n"
]
}
],
"prompt_number": 86
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f = File.open(\"testfile\",\"r\") do |f|\n",
" puts f.gets\n",
"end"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"test line 1\n",
"\n"
]
}
],
"prompt_number": 87
},
{
"cell_type": "heading",
"level": 4,
"metadata": {},
"source": [
"Manually closing the file"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f = File.open(\"testfile\",\"w\")\n",
"f << \"test line 1\\n\" << \"test line 2\\n\"\n",
"f.close"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 88
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f = File.open(\"testfile\",\"r\")\n",
"puts f.readlines\n",
"f.close"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[\"test line 1\\n\", \"test line 2\\n\"]\n"
]
}
],
"prompt_number": 89
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f = File.open(\"testfile\",\"r\")\n",
"puts f.gets\n",
"f.close"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"test line 1\n",
"\n"
]
}
],
"prompt_number": 90
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Exercise #2 \u2013 Files in Ruby"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* Write a method `sameword(file)` which searches through a file for any potential word duplications such as \u201cthe the\u201d\n",
"* How would you extend this to search for duplications that occured across two lines (\u201c...the<br>the...\u201d)?\n",
"* The method will return a Hash.\n",
" * Key is a line number where the second occurence of a word was found\n",
" * Value is an Array of duplicate words"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def same_word (file)\n",
" # ???\n",
"end\n",
"# simple simple test\n",
"# test done done\n",
"same_word(\"file.txt\")\n",
"# => {1=>[\"simple\"], 2=>[\"test\", \"done\"]}"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 91
},
{
"cell_type": "heading",
"level": 3,
"metadata": {},
"source": [
"Exercise #3 \u2013 Counting Words"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Implement this in Ruby:\n",
"\n",
"```bash\n",
"cat $file | tr -cs A-Za-z \u2019\\n\u2019 | tr A-Z a-z | sort | uniq -c | sort -rn\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Write a method `word_count(file)` which returns a Hash of words and their frequency."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"def word_count (file)\n",
" # ???\n",
"end\n",
"\n",
"# File \"test.txt\":\n",
"# Cat car cat.\n",
"\n",
"word_count(\"test.txt\")\n",
"# => { :cat => 2, :car=>1 }"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 92
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"\"string\".to_sym.class"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 93,
"text": [
"Symbol"
]
}
],
"prompt_number": 93
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 94
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment