|
| 1 | +# Should be able to evaluate all statements. |
| 2 | + |
| 3 | +# From https://www.ruby-lang.org/en/about/ |
| 4 | +# - Seeing Everything as an Object |
| 5 | +5.times { print "We *love* Ruby -- it's outrageous!" } |
| 6 | + |
| 7 | +# This should result in an error; undefined method 'plus' |
| 8 | +5.plus 3 |
| 9 | + |
| 10 | +5+ 3 # 8 |
| 11 | +5 + 3 # 8 |
| 12 | + |
| 13 | +# form-node? can handle nested binary expressions but you must put |
| 14 | +# your cursor on the right-most number or operator. |
| 15 | +5 + 4 + 3 + 2 + 1 # 15 |
| 16 | +0.5 + 4 + 3 + 2 + 1 # 10.5 |
| 17 | + |
| 18 | +2 * 7 / 3 + 9 # 13 |
| 19 | + |
| 20 | +x = 2 * 7 / 3 + 9 # (out) x = 2 * 7 / 3 + 9 |
| 21 | +# => 13 |
| 22 | +puts 2 * 7 / 3 + 9 |
| 23 | + |
| 24 | + |
| 25 | +aNum = Numeric.new |
| 26 | + |
| 27 | +# This should result in an error; undefined method '+' |
| 28 | +aNum + 2 |
| 29 | + |
| 30 | +# After assignment, the '+' method is available. |
| 31 | +aNum = 2 # 2 |
| 32 | + |
| 33 | +aNum + 2.0 # 4.0 |
| 34 | +aNum + 2 # 4 |
| 35 | + |
| 36 | +# - Ruby’s Flexibility |
| 37 | +# Add a new method to an existing class. |
| 38 | +class Numeric |
| 39 | + def plus(x) |
| 40 | + self.+(x) |
| 41 | + end |
| 42 | +end # :plus |
| 43 | + |
| 44 | +# 'plus' and '+' are methods of a Numeric. |
| 45 | +y = 5.plus 6 |
| 46 | +5.plus 6 # 11 |
| 47 | +5.+ 6 # 11 |
| 48 | + |
| 49 | +# form-node? recognizes the arguments of a function. |
| 50 | +6 * 17.2 / 0.2 # 515.9999999999999 |
| 51 | +y = 5.plus 6 * 17.2 / 0.2 |
| 52 | +# y = 520.9999999999999 |
| 53 | + |
| 54 | +aNum |
| 55 | +# => 2 |
| 56 | +aNum.plus 3 # 5 |
| 57 | + |
| 58 | +# - Blocks: a Truly Expressive Feature |
| 59 | +search_engines = |
| 60 | + %w[Google Yahoo MSN].map do |engine| |
| 61 | + "http://www." + engine.downcase + ".com" |
| 62 | + end |
| 63 | +# search_engines = ["http://www.google.com", "http://www.yahoo.com", "http://www.msn.com"] |
| 64 | + |
| 65 | +# - Ruby and the Mixin |
| 66 | +# Modules are collections of methods. |
| 67 | +class MyArray |
| 68 | +end |
| 69 | + |
| 70 | +MyArray.methods() |
| 71 | +# [:allocate, |
| 72 | +# :superclass, |
| 73 | +# :subclasses, |
| 74 | +# :attached_object, |
| 75 | +# ... |
| 76 | +# :!=, |
| 77 | +# :__id__, |
| 78 | +# :instance_eval, |
| 79 | +# :instance_exec] |
| 80 | +MyArray.methods(false) # [] |
| 81 | + |
| 82 | +MyArray.instance_methods() |
| 83 | +# [:pretty_print_cycle, |
| 84 | +# :pretty_print_instance_variables, |
| 85 | +# :pretty_print_inspect, |
| 86 | +# ... |
| 87 | +# :!=, |
| 88 | +# :__id__, |
| 89 | +# :instance_eval, |
| 90 | +# :instance_exec] |
| 91 | +MyArray.instance_methods(false) # [] |
| 92 | + |
| 93 | +# Mixin some stuff. |
| 94 | +class MyArray |
| 95 | + include Enumerable |
| 96 | +end |
| 97 | + |
| 98 | +# Can we tell how many methods are added when we include from mixin? |
| 99 | +Enumerable.methods(false) # [] |
| 100 | +Enumerable.instance_methods(false) |
| 101 | +# [:drop, |
| 102 | +# :drop_while, |
| 103 | +# :cycle, |
| 104 | +# ... |
| 105 | +# :zip, |
| 106 | +# :take, |
| 107 | +# :take_while] |
| 108 | + |
| 109 | +MyArray.methods() |
| 110 | +# [:allocate, |
| 111 | +# :superclass, |
| 112 | +# :subclasses, |
| 113 | +# ... |
| 114 | +# :!=, |
| 115 | +# :__id__, |
| 116 | +# :instance_eval, |
| 117 | +# :instance_exec] |
| 118 | +MyArray.methods(false) # [] |
| 119 | +MyArray.instance_methods() |
| 120 | +# [:drop, |
| 121 | +# :drop_while, |
| 122 | +# :cycle, |
| 123 | +# ... |
| 124 | +# :zip, |
| 125 | +# :take, |
| 126 | +# :take_while, <<--- From here and above are from Enumerable. |
| 127 | +# :pretty_print_cycle, |
| 128 | +# :pretty_print_instance_variables, |
| 129 | +# :pretty_print_inspect, |
| 130 | +# ... |
| 131 | +# :!=, |
| 132 | +# :__id__, |
| 133 | +# :instance_eval, |
| 134 | +# :instance_exec] |
| 135 | +MyArray.instance_methods(false) # [] |
| 136 | + |
| 137 | +# End of From https://www.ruby-lang.org/en/about/ |
| 138 | + |
| 139 | + |
| 140 | +# Incorrect array expression |
| 141 | +3 4 5] |
| 142 | +# => (error) <internal:kernel>:168:in 'Kernel#loop': (irb):89: syntax errors found (SyntaxError) |
| 143 | + |
| 144 | +[3 4 5] |
| 145 | +# => (error) <internal:kernel>:168:in 'Kernel#loop': (irb):90: syntax errors found (SyntaxError) |
| 146 | + |
| 147 | +# Correct array expression |
| 148 | +[3, 4, 5] # [3, 4, 5] |
| 149 | + |
| 150 | + |
| 151 | +# Block comments |
| 152 | +# - https://docs.ruby-lang.org/en/master/syntax/comments_rdoc.html |
| 153 | +=begin |
| 154 | + This is commented out. |
| 155 | +
|
| 156 | + class Foo |
| 157 | + end |
| 158 | +
|
| 159 | +=end |
| 160 | + |
| 161 | +# =begin and =end can not be indented, so this is a syntax error: |
| 162 | +class Foo |
| 163 | + =begin |
| 164 | + Will not work |
| 165 | + =end |
| 166 | +end |
| 167 | + |
| 168 | +# frozen strings |
| 169 | +# https://stackoverflow.com/a/37799399 |
| 170 | +# `# frozen_string_literal: true` is supposed to make all string literals frozen. |
| 171 | +# This works only if the magic comment is in the first comment section of a file. |
| 172 | +var = 'hello' |
| 173 | +var.frozen? # false |
| 174 | +var.freeze() |
| 175 | +var.frozen? # true |
| 176 | +var << " not" # (error) (irb):29:in '<main>': can't modify frozen String: "hello" (FrozenError) |
| 177 | + |
| 178 | +var2 = -var |
| 179 | +var2.frozen? # true |
| 180 | +var2 << " not" # (error) (irb):111:in '<main>': can't modify frozen String: "hello" (FrozenError) |
| 181 | + |
| 182 | +var3 = +var |
| 183 | +var3.frozen? # false |
| 184 | +var3 << " not" # "hello not" |
| 185 | + |
| 186 | + |
| 187 | +# From Ruby in Twenty Minutes |
| 188 | +# - https://www.ruby-lang.org/en/documentation/quickstart/ |
| 189 | + |
| 190 | +puts "Hello World" |
| 191 | + |
| 192 | +3 ** 2 |
| 193 | + |
| 194 | +Math.sqrt(9) |
| 195 | + |
| 196 | +a = 3 ** 2 |
| 197 | +b = 4 ** 2 |
| 198 | +Math.sqrt(a+b) |
| 199 | + |
| 200 | +def hi |
| 201 | + puts "Hello World!" |
| 202 | +end |
| 203 | + |
| 204 | +# - The Brief, Repetitive Lives of a Method |
| 205 | +hi # eval word or selection |
| 206 | + |
| 207 | +hi() # eval current-form |
| 208 | + |
| 209 | +def hi(name) |
| 210 | + puts "Hello #{name}!" |
| 211 | +end |
| 212 | + |
| 213 | +hi("Matz") |
| 214 | + |
| 215 | +# - Holding Spots in a String |
| 216 | +def hi(name = "World") |
| 217 | + puts "Hello #{name.capitalize}!" |
| 218 | +end |
| 219 | + |
| 220 | +# Eval these with selections: |
| 221 | +hi "chris" |
| 222 | +# (out) hi "chris" |
| 223 | + |
| 224 | +hi |
| 225 | +# (out) Hello World! |
| 226 | + |
| 227 | +# - Evolving Into a Greeter |
| 228 | +class Greeter |
| 229 | + def initialize(name = "World") |
| 230 | + @name = name |
| 231 | + end |
| 232 | + def say_hi |
| 233 | + puts "Hi #{@name}!" |
| 234 | + end |
| 235 | + def say_bye |
| 236 | + puts "bye #{@name}, come back soon." |
| 237 | + end |
| 238 | +end |
| 239 | + |
| 240 | +greeter = Greeter.new("Pat") |
| 241 | +greeter.say_hi |
| 242 | +greeter.say_bye |
| 243 | +# This should be an error. |
| 244 | +greeter.@name |
| 245 | + |
| 246 | +# - Under the Object’s Skin |
| 247 | +Greeter.instance_methods |
| 248 | +Greeter.instance_methods() |
| 249 | + |
| 250 | +Greeter.instance_methods(false) # [:say_hi, :say_bye] |
| 251 | + |
| 252 | +greeter.respond_to?("name") # false |
| 253 | +greeter.respond_to?("say_hi") # true |
| 254 | +greeter.respond_to?("to_s") # true |
| 255 | + |
| 256 | +# - Altering Classes—It’s Never Too Late |
| 257 | +class Greeter |
| 258 | + attr_accessor :name |
| 259 | +end |
| 260 | + |
| 261 | +greeter = Greeter.new("Andy") |
| 262 | +# Access attribute |
| 263 | +greeter.respond_to?("name") # true |
| 264 | +# Set attribute |
| 265 | +greeter.respond_to?("name=") # true |
| 266 | +# Same as when evaluated with "()". |
| 267 | +greeter.say_hi |
| 268 | +# This should update the name attribute. |
| 269 | +greeter.name="Betty" |
| 270 | +greeter |
| 271 | +greeter.name |
| 272 | +greeter.say_hi |
| 273 | + |
| 274 | +# - Cycling and Looping—a.k.a. Iteration |
| 275 | +class MegaGreeter |
| 276 | + attr_accessor :names |
| 277 | + |
| 278 | + # Create the object |
| 279 | + def initialize(names = "World") |
| 280 | + @names = names |
| 281 | + end |
| 282 | + |
| 283 | + # Say hi to everybody |
| 284 | + def say_hi |
| 285 | + if @names.nil? |
| 286 | + puts "..." |
| 287 | + elsif @names.respond_to?("each") |
| 288 | + # @names is a list of some kind, iterate! |
| 289 | + @names.each do |name| |
| 290 | + puts "Hello #{name}!" |
| 291 | + end |
| 292 | + else |
| 293 | + puts "Hello #{@names}!" |
| 294 | + end |
| 295 | + end |
| 296 | + |
| 297 | + # Say bye to everybody |
| 298 | + def say_bye |
| 299 | + if @names.nil? |
| 300 | + puts "..." |
| 301 | + elsif @names.respond_to?("join") |
| 302 | + # Join the list elements with commas |
| 303 | + puts "Goodbye #{@names.join(", ")}. Come back soon!" |
| 304 | + else |
| 305 | + puts "Goodbye #{@names}. Come back soon!" |
| 306 | + end |
| 307 | + end |
| 308 | +end |
| 309 | + |
| 310 | +mg = MegaGreeter.new |
| 311 | + |
| 312 | +# Evaluate with selection: |
| 313 | +mg.say_hi |
| 314 | +# (out) Hello World! |
| 315 | +# => nil |
| 316 | + |
| 317 | +mg.say_bye |
| 318 | +# (out) Goodbye World. Come back soon! |
| 319 | +# => nil |
| 320 | + |
| 321 | +mg.names # "World" |
| 322 | +mg.names.respond_to?("each") # false |
| 323 | +mg.names.respond_to?("join") # false |
| 324 | + |
| 325 | +# Change the name to an array of names |
| 326 | +mg.names = ["Albert", "Brenda", "Charles", "Dave", "Engelbert"] |
| 327 | + |
| 328 | +# Evaluate with selection: |
| 329 | +mg.say_hi |
| 330 | +# (out) Hello Albert!↵Hello Brenda!↵Hello Charles!↵Hello Dave!↵Hello Engelbert! |
| 331 | +# => ["Albert", "Brenda", "Charles", "Dave", "Engelbert"] |
| 332 | +# |
| 333 | +mg.say_bye |
| 334 | +# (out) Goodbye Albert, Brenda, Charles, Dave, Engelbert. Come back soon! |
| 335 | +# => nil |
| 336 | + |
0 commit comments