I have an assignment to build a tic-tac-toe game using ruby classes.
I'm new to programming and self taught so far, but was accepted into a program and need to polish up on some concepts to be ahead of the game.
I understand most concepts and got the majority of spec files to work for my game, but I did need to reference the solution code a few times to help solve the last bit of the problem.
In creating the board class, two methods were created that were defined using empty arrays. I have never seen this before and wanted to know what was going on. When I went into my IDE and created a method with the name [](empty array) and two parameters, I'd get an error (syntax error, expecting end of input) trying to run it. It seems this must be something you can only do while setting up a class?
I'm assuming these are getter and setter methods?
def [](pos)
row, col = pos
grid[row][col]
end
def []=(pos, value)
row, col = pos
grid[row][col] = value
end
In the above code, grid is an instance variable of the board class. Why can you use an instance variable in a method without putting the "#" symbol in front of it - (#grid, instead of grid). This is a little confusing because with normal methods, if you define a variable outside of the method, the method doesn't recognize it. Why is it different inside of classes?
#example
x = 6
def add(b)
x + b
end
=> will return an error - local variable x is undefined.
Below is the full board class in case it'll make better sense understanding and answering the questions. Thank you!
class Board
attr_reader :grid, :marks
def initialize(grid = [])
if grid.empty?
#grid = Array.new(3) { Array.new(3) }
else
#grid = grid
end
#marks = [:X, :O]
end
def place_mark(pos, mark)
grid[pos[0]][pos[1]] = mark
end
def [](pos)
row, col = pos
grid[row][col]
end
def []=(pos, value)
row, col = pos
grid[row][col] = value
end
def empty?(pos)
grid[pos[0]][pos[1]].nil? ? true : false
end
def winner
(grid + grid.transpose + diagnol).each do |win|
return :X if win == [:X,:X,:X]
return :O if win == [:O,:O,:O]
end
nil
end
def diagnol
diag1 = [[0, 0], [1, 1], [2, 2]]
diag2 = [[0, 2], [1, 1], [2, 0]]
[diag1, diag2].map do |diag|
diag.map {|row, col| grid[row][col]}
end
end
def over?
return true if grid.flatten.compact.size == 9 || winner
return false if grid.flatten.compact.size == 0 || winner.nil?
end
end
Yes, that is a getter and setter for an array object on Board. (FWIW I think that it's poor Ruby style to do this, so I wouldn't use this in the future in your own code. I think that's why your IDE is having issues with this method as well.
You can use grid without the # because of the attr_reader declaration at the top of your class. This creates a read-only variable for the instance variable that is public on the class. It effectively creates a method called:
def grid
#grid
end
You would not be able to do grid = [] because attr_reader only creates a read only method. To create a read-write accessor, you would use attr_accessor. Keep in mind, using attr_ methods make the variable in question public on the class, so if you wanted to keep something internal, you would not use them.
A bit late but I was also looking into this and found this on the web. Apparently, it is syntactic sugar for classes with grid-like instance variables.
The Syntactic Sugar
These are all equivalent ways to get the bottom-left square:
board.grid[2][0]
board.[](2, 0)
board[2, 0] # syntactic sugar
The syntactic sugar allows us to call the Board#[] method with our
arguments inside of the square brackets themselves rather than in
parentheses following the square brackets.
Similarly, the following are equivalent ways to set the top-right
square:
board.grid[0][2] = :x
board.[]=(0, 2, :x)
board[0, 2] = :x # syntactic sugar
Naturally, if we bother to set up the special [] and []= methods,
we'll use the syntactic sugar way. :)
More information can be found from this link:
https://github.com/emgreen33/Practice/blob/master/W2D4/bracket-methods.md
In JavaScript the following idiom is sometimes used to contain scope
// JavaScript
(function() {
var x = 0;
// do stuff
})(); // execute anonymous function in-place
// x is undefined (or its previous value)
And you see this in Perl:
{
local $/ = undef;
$file_contents = <FILE>;
}
# $/ == "\n"
Is there something similar in Ruby? The closest I could come up with was:
Proc.new
x = 123
puts x
end.call
# x is undefined
Is there another, more common way to do this in Ruby or is this how it's best done?
Your example won’t work if x is already defined before the block:
x = 7
Proc.new do
x = 123
puts x
end.call
# x is now 123
Ruby does allow you to specify block local variables in the block argument list with this rather obscure syntax:
x = 7
Proc.new do |;x| # declare x as block local
x = 123
puts x
end.call
# x is still 7
Any variables after the ; are treated as local to that block and don’t effect similarly named variables in the enclosing scope.
Closest solution would be to use stabby lambda notation:
-> {
x = 123
puts x
}.call
It is not very common in Ruby to use anonymous procs in such context. The most ruby-way of which I can think of is enclosing each trial in small, lightweight class.
Using a proc
proc {
...
}[]
is already pretty minimal, though not very idiomatic. You can write your own wrapper, which you might find more elegant as it avoids the creation of an anonymous function
def wrap
yield
end
wrap do
...
end
However, as #matt pointed out, this doesn't prevent you from accessing variables defined outside the block.
The behavior: Ruby 1.9.2p180 fails with 'Illegal Instruction' and no other details. Ruby 1.9.1p378 runs with no problems at all.
The failure happens in the line pin = fronto.index(k), on only some iterations.
from and into are both arrays of objects, by is an attribute (either x or y) of that object.
The code:
def add_from_to_by from, into, by
nto = into.sort_by{|k| k.send(by)}
fronto = (from + nto).sort_by{|k| k.send(by)}
dict = {}
nto.each{|k| dict[k] = []}
nto.each do |k|
pin = fronto.index(k)
up = pin+1
down = pin-1
while up < fronto.length and ((fronto[pin].send(by)) - (fronto[up].send(by))).abs <= $sensor_range
if fronto[up].kind_of?(BasicNode) then
dict[k].push(fronto[up])
end
up += 1
end
while down >= 0 and ((fronto[pin].send(by)) - (fronto[down].send(by))).abs <= $sensor_range
if fronto[down].kind_of?(BasicNode)
dict[k].push(fronto[down])
end
down -= 1
end
end
return dict
end
I'm using rvm to manage ruby versions on Mac 10.6.6. Any idea why this is happening?
REVISION:
If the code above is reduced to this:
def add_from_to_by from, into, by
nto = into.sort_by{|k| k.send(by)}
fronto = (from + nto).sort_by{|k| k.send(by)}
dict = {}
nto.each{|k| dict[k] = []}
x = nto.select{|k| !fronto.include?(k)}
end
This reproduces the bug on the last line.
In the input that crashes, into and from are disjoint sets of points. A class definition that should work is:
class BasicNode
attr_reader :x, :y
def initialize x, y
#x = x
#y = y
end
end
where x and y are numbers. In the test that crashes there are 15 nodes in into and 5 nodes in from.
EDIT:
I do get a stack level too deep (System Stack Error) when I isolate the code somewhat. However, I'm not sure why this should be, since there are no recursive calls in this code or in the C implementation for array index.
ADDENDUM: The complete source code for this question can be found here: http://code.google.com/p/graphcomplexity/
repository: rvertex
branch: default
test file: test/test_deeps_hypersim.rb
using 1.9.2-p180 on linux, I haven't been able to reproduce your problem. here's my test setup:
$sensor_range=5
list1=Array.new(1000) {|i| BasicNode.new(rand(100),rand(100))}
list2=Array.new(1000) {|i| BasicNode.new(rand(100),rand(100))}
res=add_from_to_by(list1,list2,:x);
does your bug still occur with that set of instructions? If you're still getting the bug, but not with those instructions, could you provide some example data and function call that demonstrates the problem? (if it's huge, you can use a service like pastebin.com)
also, I'm not 100% sure if it's exactly the same, but this might be a more straightforward way to write the same function (your program might be easier to debug with simpler code):
def add_from_to_modified(from,into,sensor_range,&block)
into.inject({}) do |result,key|
result.merge({key=>(into+from).select {|check| (yield(check)-yield(key)).abs <= sensor_range}})
end
end
add_from_to_modified(list1,list2,5,&:x)
it can be rewritten with the yield()s outside of the loop if that's too inefficient. this implementation also lets you pass an arbitrary block instead of just a function to call
add_from_to_modified(list1,list2,5) {|node| node.x*3-node.y}
i've been messing around with ruby and opengl for entertainment purposes, and i decided to write some 3d vector/plane/etc classes to pretty up some of the math.
simplified example:
class Vec3
attr_accessor :x,:y,:z
def *(a)
if a.is_a?(Numeric) #multiply by scalar
return Vec3.new(#x*a, #y*a, #z*a)
elsif a.is_a?(Vec3) #dot product
return #x*a.x + #y*a.y + #z*a.z
end
end
end
v1 = Vec3.new(1,1,1)
v2 = v1*5 #produces [5,5,5]
which all fine and dandy, but i also want to be able to write
v2 = 5*v1
which requires adding functionality to Fixnum or Float or whatever, but i couldn't find a way to overload or extend fixnum's multiplication without replacing it entirely. is this possible in ruby? any tips?
(obviously i can just write all my multiplications in the correct order if i need to)
Using coerce is a MUCH better approach than monkey-patching a core class:
class Vec3
attr_accessor :x,:y,:z
def *(a)
if a.is_a?(Numeric) #multiply by scalar
return Vec3.new(#x*a, #y*a, #z*a)
elsif a.is_a?(Vec3) #dot product
return #x*a.x + #y*a.y + #z*a.z
end
end
def coerce(other)
return self, other
end
end
if you define v as v = Vec3.new then the following will work: v * 5 and 5 * v
The first element returned by coerce (self) becomes the new receiver for the operation, and the second element (other) becomes the parameter, so 5 * v is exactly equivalent to v * 5
I believe the following will do what you want, though banister's suggestion to use coerce instead of monkey-patching Numeric is a preferred method. Use this method only if necessary (for example if you only want some binary operands to be transitive).
Fixnum.class_eval do
original_times = instance_method(:*)
define_method(:*) do |other|
if other.kind_of?(Vec3)
return other * self
else
return original_times.bind(self).call(other)
end
end
end
What does the following code mean in Ruby?
||=
Does it have any meaning or reason for the syntax?
a ||= b is a conditional assignment operator. It means:
if a is undefined or falsey, then evaluate b and set a to the result.
Otherwise (if a is defined and evaluates to truthy), then b is not evaluated, and no assignment takes place.
For example:
a ||= nil # => nil
a ||= 0 # => 0
a ||= 2 # => 0
foo = false # => false
foo ||= true # => true
foo ||= false # => true
Confusingly, it looks similar to other assignment operators (such as +=), but behaves differently.
a += b translates to a = a + b
a ||= b roughly translates to a || a = b
It is a near-shorthand for a || a = b. The difference is that, when a is undefined, a || a = b would raise NameError, whereas a ||= b sets a to b. This distinction is unimportant if a and b are both local variables, but is significant if either is a getter/setter method of a class.
Further reading:
http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html
This question has been discussed so often on the Ruby mailing-lists and Ruby blogs that there are now even threads on the Ruby mailing-list whose only purpose is to collect links to all the other threads on the Ruby mailing-list that discuss this issue.
Here's one: The definitive list of ||= (OR Equal) threads and pages
If you really want to know what is going on, take a look at Section 11.4.2.3 "Abbreviated assignments" of the Ruby Language Draft Specification.
As a first approximation,
a ||= b
is equivalent to
a || a = b
and not equivalent to
a = a || b
However, that is only a first approximation, especially if a is undefined. The semantics also differ depending on whether it is a simple variable assignment, a method assignment or an indexing assignment:
a ||= b
a.c ||= b
a[c] ||= b
are all treated differently.
Concise and complete answer
a ||= b
evaluates the same way as each of the following lines
a || a = b
a ? a : a = b
if a then a else a = b end
-
On the other hand,
a = a || b
evaluates the same way as each of the following lines
a = a ? a : b
if a then a = a else a = b end
-
Edit: As AJedi32 pointed out in the comments, this only holds true if: 1. a is a defined variable. 2. Evaluating a one time and two times does not result in a difference in program or system state.
In short, a||=b means: If a is undefined, nil or false, assign b to a. Otherwise, keep a intact.
Basically,
x ||= y means
if x has any value leave it alone and do not change the value, otherwise
set x to y
It means or-equals to. It checks to see if the value on the left is defined, then use that. If it's not, use the value on the right. You can use it in Rails to cache instance variables in models.
A quick Rails-based example, where we create a function to fetch the currently logged in user:
class User > ActiveRecord::Base
def current_user
#current_user ||= User.find_by_id(session[:user_id])
end
end
It checks to see if the #current_user instance variable is set. If it is, it will return it, thereby saving a database call. If it's not set however, we make the call and then set the #current_user variable to that. It's a really simple caching technique but is great for when you're fetching the same instance variable across the application multiple times.
To be precise, a ||= b means "if a is undefined or falsy (false or nil), set a to b and evaluate to (i.e. return) b, otherwise evaluate to a".
Others often try to illustrate this by saying that a ||= b is equivalent to a || a = b or a = a || b. These equivalencies can be helpful for understanding the concept, but be aware that they are not accurate under all conditions. Allow me to explain:
a ||= b ⇔ a || a = b?
The behavior of these statements differs when a is an undefined local variable. In that case, a ||= b will set a to b (and evaluate to b), whereas a || a = b will raise NameError: undefined local variable or method 'a' for main:Object.
a ||= b ⇔ a = a || b?
The equivalency of these statements are often assumed, since a similar equivalence is true for other abbreviated assignment operators (i.e. +=,-=,*=,/=,%=,**=,&=,|=,^=,<<=, and >>=). However, for ||= the behavior of these statements may differ when a= is a method on an object and a is truthy. In that case, a ||= b will do nothing (other than evaluate to a), whereas a = a || b will call a=(a) on a's receiver. As others have pointed out, this can make a difference when calling a=a has side effects, such as adding keys to a hash.
a ||= b ⇔ a = b unless a??
The behavior of these statements differs only in what they evaluate to when a is truthy. In that case, a = b unless a will evaluate to nil (though a will still not be set, as expected), whereas a ||= b will evaluate to a.
a ||= b ⇔ defined?(a) ? (a || a = b) : (a = b)????
Still no. These statements can differ when a method_missing method exists which returns a truthy value for a. In this case, a ||= b will evaluate to whatever method_missing returns, and not attempt to set a, whereas defined?(a) ? (a || a = b) : (a = b) will set a to b and evaluate to b.
Okay, okay, so what is a ||= b equivalent to? Is there a way to express this in Ruby?
Well, assuming that I'm not overlooking anything, I believe a ||= b is functionally equivalent to... (drumroll)
begin
a = nil if false
a || a = b
end
Hold on! Isn't that just the first example with a noop before it? Well, not quite. Remember how I said before that a ||= b is only not equivalent to a || a = b when a is an undefined local variable? Well, a = nil if false ensures that a is never undefined, even though that line is never executed. Local variables in Ruby are lexically scoped.
If X does NOT have a value, it will be assigned the value of Y. Else, it will preserve it's original value, 5 in this example:
irb(main):020:0> x = 5
=> 5
irb(main):021:0> y = 10
=> 10
irb(main):022:0> x ||= y
=> 5
# Now set x to nil.
irb(main):025:0> x = nil
=> nil
irb(main):026:0> x ||= y
=> 10
x ||= y
is
x || x = y
"if x is false or undefined, then x point to y"
||= is a conditional assignment operator
x ||= y
is equivalent to
x = x || y
or alternatively
if defined?(x) and x
x = x
else
x = y
end
unless x
x = y
end
unless x has a value (it's not nil or false), set it equal to y
is equivalent to
x ||= y
Suppose a = 2 and b = 3
THEN, a ||= b will be resulted to a's value i.e. 2.
As when a evaluates to some value not resulted to false or nil.. That's why it ll not evaluate b's value.
Now Suppose a = nil and b = 3.
Then a ||= b will be resulted to 3 i.e. b's value.
As it first try to evaluates a's value which resulted to nil.. so it evaluated b's value.
The best example used in ror app is :
#To get currently logged in iser
def current_user
#current_user ||= User.find_by_id(session[:user_id])
end
# Make current_user available in templates as a helper
helper_method :current_user
Where, User.find_by_id(session[:user_id]) is fired if and only if #current_user is not initialized before.
||= is called a conditional assignment operator.
It basically works as = but with the exception that if a variable has already been assigned it will do nothing.
First example:
x ||= 10
Second example:
x = 20
x ||= 10
In the first example x is now equal to 10. However, in the second example x is already defined as 20. So the conditional operator has no effect. x is still 20 after running x ||= 10.
a ||= b
Signifies if any value is present in 'a' and you dont want to alter it the keep using that value, else if 'a' doesnt have any value, use value of 'b'.
Simple words, if left hand side if not null, point to existing value, else point to value at right side.
a ||= b
is equivalent to
a || a = b
and not
a = a || b
because of the situation where you define a hash with a default (the hash will return the default for any undefined keys)
a = Hash.new(true) #Which is: {}
if you use:
a[10] ||= 10 #same as a[10] || a[10] = 10
a is still:
{}
but when you write it like so:
a[10] = a[10] || 10
a becomes:
{10 => true}
because you've assigned the value of itself at key 10, which defaults to true, so now the hash is defined for the key 10, rather than never performing the assignment in the first place.
It's like lazy instantiation.
If the variable is already defined it will take that value instead of creating the value again.
Please also remember that ||= isn't an atomic operation and so, it isn't thread safe. As rule of thumb, don't use it for class methods.
This is the default assignment notation
for example: x ||= 1
this will check to see if x is nil or not. If x is indeed nil it will then assign it that new value (1 in our example)
more explicit:
if x == nil
x = 1
end
b = 5
a ||= b
This translates to:
a = a || b
which will be
a = nil || 5
so finally
a = 5
Now if you call this again:
a ||= b
a = a || b
a = 5 || 5
a = 5
b = 6
Now if you call this again:
a ||= b
a = a || b
a = 5 || 6
a = 5
If you observe, b value will not be assigned to a. a will still have 5.
Its a Memoization Pattern that is being used in Ruby to speed up accessors.
def users
#users ||= User.all
end
This basically translates to:
#users = #users || User.all
So you will make a call to database for the first time you call this method.
Future calls to this method will just return the value of #users instance variable.
As a common misconception, a ||= b is not equivalent to a = a || b, but it behaves like a || a = b.
But here comes a tricky case. If a is not defined, a || a = 42 raises NameError, while a ||= 42 returns 42. So, they don't seem to be equivalent expressions.
irb(main):001:0> a = 1
=> 1
irb(main):002:0> a ||= 2
=> 1
Because a was already set to 1
irb(main):003:0> a = nil
=> nil
irb(main):004:0> a ||= 2
=> 2
Because a was nil
This ruby-lang syntax. The correct answer is to check the ruby-lang documentation. All other explanations obfuscate.
Google
"ruby-lang docs Abbreviated Assignment".
Ruby-lang docs
https://docs.ruby-lang.org/en/2.4.0/syntax/assignment_rdoc.html#label-Abbreviated+Assignment
a ||= b is the same as saying a = b if a.nil? or a = b unless a
But do all 3 options show the same performance? With Ruby 2.5.1 this
1000000.times do
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
a ||= 1
end
takes 0.099 Seconds on my PC, while
1000000.times do
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
a = 1 unless a
end
takes 0.062 Seconds. That's almost 40% faster.
and then we also have:
1000000.times do
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
a = 1 if a.nil?
end
which takes 0.166 Seconds.
Not that this will make a significant performance impact in general, but if you do need that last bit of optimization, then consider this result.
By the way: a = 1 unless a is easier to read for the novice, it is self-explanatory.
Note 1: reason for repeating the assignment line multiple times is to reduce the overhead of the loop on the time measured.
Note 2: The results are similar if I do a=nil nil before each assignment.