From what I know "<" is inheritance of a class from another class?
but I also see "<<" being used for the same thing from what I am seeing,.
Example:
def catch_alarm(alarm_info, options)
alarms = []
alarms << AlarmMonitor.new({
region_id: region_name,
account_id: '10202'.
alarm_name: alarm_info
},
alarms
end
First of all, < and << are not the same.
Ruby – like many other programming languages – uses the infix notation for binary operators, i.e.:
left-hand side operator right-hand side
For example:
1 + 2
a - b
i >= j
x << y
But unlike many other languages, operators are implemented as methods in Ruby. So it's actually:
receiver method argument
If you want to know, what alarms << AlarmMonitor.new(...) does, you have to know what kind of object alarms is. In your example, it's an array (alarms = []) so the method is Array#<<:
ary << obj → ary
Append—Pushes the given object on to the end of this array. This expression returns the array itself, so several appends may be chained together.
Note that different objects (or classes) can implement the same operator in different ways:
a = [1, 2]
a << 3 # pushes 3 onto the array, i.e. [1, 2, 3]
d = Date.new(2020, 5, 28)
d << 3 # returns a date 3 months earlier, i.e. 2020-02-28
i = 0b00001011
i << 3 # shifts the bits 3 to the left, i.e. 0b01011000
The behavior primarily depends on the receiver.
Let's briefly get back to <. In addition to methods, Ruby has keywords. Keywords sometimes work like methods, but they have their own parsing rules.
For class creation, Ruby has the class keyword:
class MyClass
# ...
end
Which accepts an optional subclass via:
class MySubclass < MyClass
# ...
end
Here, < is not an operator, but part of the class keyword syntax.
However, there's also a < operator for classes: Module#<. It can be used to check whether MySubclass is a subclass of MyClass: (thus mirroring the class creation syntax)
MySubclass < MyClass
#=> true
In this context << is the Array push operator, so isn’t related to the use of < for class inheritance.
Related
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
I am quite new to Ruby and am wondering about the << operator. When I googled this operator, it says that it is a Binary Left Shift Operator given this example:
a << 2 will give 15 which is 1111 0000
however, it does not seem to be a "Binary Left Shift Operator" in this code:
class TextCompressor
attr_reader :unique, :index
def initialize(text)
#unique = []
#index = []
add_text(text)
end
def add_text(text)
words = text.split
words.each { |word| do add_word(word) }
end
def add_word(word)
i = unique_index_of(word) || add_unique_word(word)
#index << i
end
def unique_index_of(word)
#unique.index(word)
end
def add_unique_word
#unique << word
unique.size - 1
end
end
and this question does not seem to apply in the code I have given. So with the code I have, how does the Ruby << operator work?
Ruby is an object-oriented language. The fundamental principle of object orientation is that objects send messages to other objects, and the receiver of the message can respond to the message in whatever way it sees fit. So,
a << b
means whatever a decides it should mean. It's impossible to say what << means without knowing what a is.
As a general convention, << in Ruby means "append", i.e. it appends its argument to its receiver and then returns the receiver. So, for Array it appends the argument to the array, for String it performs string concatenation, for Set it adds the argument to the set, for IO it writes to the file descriptor, and so on.
As a special case, for Fixnum and Bignum, it performs a bitwise left-shift of the twos-complement representation of the Integer. This is mainly because that's what it does in C, and Ruby is influenced by C.
<< is just a method. It usually means "append" in some sense, but can mean anything. For strings and arrays it means append/add. For integers it's bitwise shift.
Try this:
class Foo
def << (message)
print "hello " + message
end
end
f = Foo.new
f << "john" # => hello john
In Ruby, operators are just methods. Depending on the class of your variable, << can do different things:
# For integers it means bitwise left shift:
5 << 1 # gives 10
17 << 3 # gives 136
# arrays and strings, it means append:
"hello, " << "world" # gives "hello, world"
[1, 2, 3] << 4 # gives [1, 2, 3, 4]
It all depends on what the class defines << to be.
<< is an operator that is syntactic sugar for calling the << method on the given object. On Fixnum it is defined to bitshift left, but it has different meanings depending on the class it's defined on. For example, for Array it adds (or, rather, "shovels") the object into the array.
We can see here that << is indeed just syntactic sugar for a method call:
[] << 1 # => [1]
[].<<(1) # => [1]
and thus in your case it just calls << on #unique, which in this case is an Array.
The << function, according to http://ruby-doc.org/core-1.9.3/Array.html#method-i-3C-3C, is an append function. It appends the passed-in value to the array and then returns the array itself. Ruby objects can often have functions defined on them that, in other languages, would look like an operator.
My background is in PHP and C#, but I'd really like to learn RoR. To that end, I've started reading the official documentation. I have some questions about some code examples.
The first is with iterators:
class Array
def inject(n)
each { |value| n = yield(n, value) }
n
end
def sum
inject(0) { |n, value| n + value }
end
def product
inject(1) { |n, value| n * value }
end
end
I understand that yield means "execute the associated block here." What's throwing me is the |value| n = part of the each. The other blocks make more sense to me as they seem to mimic C# style lambdas:
public int sum(int n, int value)
{
return Inject((n, value) => n + value);
}
But the first example is confusing to me.
The other is with symbols. When would I want to use them? And why can't I do something like:
class Example
attr_reader #member
# more code
end
In the inject or reduce method, n represents an accumulated value; this means the result of every iteration is accumulated in the n variable. This could be, as is in your example, the sum or product of the elements in the array.
yield returns the result of the block, which is stored in n and used in the next iterations. This is what makes the result "cumulative."
a = [ 1, 2, 3 ]
a.sum # inject(0) { |n, v| n + v }
# n == 0; n = 0 + 1
# n == 1; n = 1 + 2
# n == 3; n = 3 + 3
=> 6
Also, to compute the sum you could also have written a.reduce :+. This works for any binary operation. If your method is named symbol, writing a.reduce :symbol is the same as writing a.reduce { |n, v| n.symbol v }.
attr and company are actually methods. Under the hood, they dynamically define the methods for you. It uses the symbol you passed to work out the names of the instance variable and the methods. :member results in the #member instance variable and the member and member = methods.
The reason you can't write attr_reader #member is because #member isn't an object in itself, nor can it be converted to a symbol; it actually tells ruby to fetch the value of the instance variable #member of the self object, which, at class scope, is the class itself.
To illustrate:
class Example
#member = :member
attr_accessor #member
end
e = Example.new
e.member = :value
e.member
=> :value
Remember that accessing unset instance variables yields nil, and since the attr method family accepts only symbols, you get: TypeError: nil is not a symbol.
Regarding Symbol usage, you can sort of use them like strings. They make excellent hash keys because equal symbols always refer to the same object, unlike strings.
:a.object_id == :a.object_id
=> true
'a'.object_id == 'a'.object_id
=> false
They're also commonly used to refer to method names, and can actually be converted to Procs, which can be passed to methods. This is what allows us to write things like array.map &:to_s.
Check out this article for more interpretations of the symbol.
For the definition of inject, you're basically setting up chained blocks. Specifically, the variable n in {|value| n = yield(n, value)} is essentially an accumulator for the block passed to inject. So, for example, for the definition of product, inject(1) {|value| n * value}, let's assume you have an array my_array = [1, 2, 3, 4]. When you call my_array.product, you start by calling inject with n = 1. each yields to the block defined in inject, which in turns yields to the block passed to inject itself with n (1) and the first value in the array (1 as well, in this case). This block, {|n, value| n * value} returns 1 == 1 * 1, which is set it inject's n variable. Next, 2 is yielded from each, and the block defined in inject block yields as yield(1, 2), which returns 2 and assigns it to n. Next 3 is yielded from each, the block yields the values (2, 3) and returns 6, which is stored in n for the next value, and so forth. Essentially, tracking the overall value agnostic of the calculation being performed in the specialised routines (sum and product) allows for generalization. Without that, you'd have to declare e.g.
def sum
n = 0
each {|val| n += val}
end
def product
n = 1
each {|val| n *= val}
end
which is annoyingly repetitive.
For your second question, attr_reader and its family are themselves methods that are defining the appropriate accessor routines using define_method internally, in a process called metaprogramming; they are not language statements, but just plain old methods. These functions expect to passed a symbol (or, perhaps, a string) that gives the name of the accessors you're creating. You could, in theory, use instance variables such as #member here, though it would be the value to which #member points that would be passed in and used in define_method. For an example of how these are implemented, this page shows some examples of attr_* methods.
def inject(accumulator)
each { |value| accumulator = yield(accumulator, value) }
accumulator
end
This is just yielding the current value of accumulator and the array item to inject's block and then storing the result back into accumulator again.
class Example
attr_reader #member
end
attr_reader is just a method whose argument is the name of the accessor you want to setup. So, in a contrived way you could do
class Example
#ivar_name = 'foo'
attr_reader #ivar_name
end
to create an getter method called foo
Your confusion with the first example may be due to your reading |value| n as a single expression, but it isn't.
This reformatted version might be clearer to you:
def inject(n)
each do |value|
n = yield(n, value)
end
return n
end
value is an element in the array, and it is yielded with n to whatever block is passed to inject, the result of which is set to n. If that's not clear, read up on the each method, which takes a block and yields each item in the array to it. Then it should be clearer how the accumulation works.
attr_reader is less weird when you consider that it is a method for generating accessor methods. It's not an accessor in itself. It doesn't need to deal with the #member variable's value, just its name. :member is just the interned version of the string 'member', which is the name of the variable.
You can think of symbols as lighter weight strings, with the additional bonus that every equal label is the same object - :foo.object_id == :foo.object_id, whereas 'foo'.object_id != 'foo'.object_id, because each 'foo' is a new object. You can try that for yourself in irb. Think of them as labels, or primitive strings. They're surprisingly useful and come up a lot, e.g. for metaprogramming or as keys in hashes. As pointed out elsewhere, calling object.send :foo is the same as calling object.foo
It's probably worth reading some early chapters from the 'pickaxe' book to learn some more ruby, it will help you understand and appreciate the extra stuff rails adds.
First you need to understand where to use symbols and where its not..
Symbol is especially used to represent something. Ex: :name, :age like that. Here we are not going to perform any operations using this.
String are used only for data processing. Ex: 'a = name'. Here I gonna use this variable 'a' further for other string operations in ruby.
Moreover, symbol is more memory efficient than strings and it is immutable. That's why ruby developer's prefers symbols than string.
You can even use inject method to calculate sum as (1..5).to_a.inject(:+)
I have code:
def make_all_thumbs(source)
sizes = ['1000','1100','1200','800','600']
threads = []
sizes.each do |s|
threads << Thread.new(s) {
create_thumbnail(source+'.png', source+'-'+s+'.png', s)
}
end
end
what does << mean?
It can have 3 distinct meanings:
'<<' as an ordinary method
In most cases '<<' is a method defined like the rest of them, in your case it means "add to the end of this array" (see also here).
That's in your particular case, but there are also a lot of other occasions where you'll encounter the "<<" method. I won't call it 'operator' since it's really a method that is defined on some object that can be overridden by you or implemented for your own objects. Other cases of '<<'
String concatenation: "a" << "b"
Writing output to an IO: io << "A line of text\n"
Writing data to a message digest, HMAC or cipher: sha << "Text to be hashed"
left-shifting of an OpenSSL::BN: bn << 2
...
Singleton class definition
Then there is the mysterious shift of the current scope (=change of self) within the program flow:
class A
class << self
puts self # self is the singleton class of A
end
end
a = A.new
class << a
puts self # now it's the singleton class of object a
end
The mystery class << self made me wonder and investigate about the internals there. Whereas in all the examples I mentioned << is really a method defined in a class, i.e.
obj << stuff
is equivalent to
obj.<<(stuff)
the class << self (or any object in place of self) construct is truly different. It is really a builtin feature of the language itself, in CRuby it's defined in parse.y as
k_class tLSHFT expr
k_class is the 'class' keyword, where tLSHFT is a '<<' token and expr is an arbitrary expression. That is, you can actually write
class << <any expression>
and will get shifted into the singleton class of the result of the expression. The tLSHFT sequence will be parsed as a 'NODE_SCLASS' expression, which is called a Singleton Class definition (cf. node.c)
case NODE_SCLASS:
ANN("singleton class definition");
ANN("format: class << [nd_recv]; [nd_body]; end");
ANN("example: class << obj; ..; end");
F_NODE(nd_recv, "receiver");
LAST_NODE;
F_NODE(nd_body, "singleton class definition");
break;
Here Documents
Here Documents use '<<' in a way that is again totally different. You can define a string that spans over multiple lines conveniently by declaring
here_doc = <<_EOS_
The quick brown fox jumps over the lazy dog.
...
_EOS_
To distinguish the 'here doc operator' an arbitrary String delimiter has to immediately follow the '<<'. Everything inbetween that initial delimiter and the second occurrence of that same delimiter will be part of the final string. It is also possible to use '<<-', the difference is that using the latter will ignore any leading or trailing whitespace.
Mostly used in arrays to append the value to the end of the array.
a = ["orange"]
a << "apple"
puts a
gives this ["orange", "apple"] result.
'a << b' means append b to the end of a
It's the operator which allows you to feed existing arrays, by appending new items.
In the example above you are just populating the empty array threads with 5 new threads.
In ruby you always have more the one way to do things. So, Ruby has some nice shortcuts for common method names. like this one is for .push instead of typing out the .push method name, you can simply use <<, the concatenation operator. in fact in some cases you can use any of these for the same operation .push and + with <<.
Like you can see in this example:
alphabet = ["a", "b", "c"]
alphabet << "d" # Update me!
alphabet.push("e") # Update me!
print alphabet
caption = "the boy is surrounded by "
caption << "weezards!" # Me, too!
caption += " and more. " # Me, too!
# .push can no be uses for concatenate
print caption
so you see the result is:
["a", "b", "c", "d", "e"]
the boy is surrounded by weezards! and more.
you can use the operator << to push a element into an array or to concatenate a string to another.
so, what this is this doing is creating a new element/object Thread type and pushing it into the array.
threads << Thread.new(s) {
create_thumbnail(source+'.png', source+'-'+s+'.png', s)
}
In ruby '<<' operator is basically used for:
Appending a value in the array (at last position)
[2, 4, 6] << 8
It will give [2, 4, 6, 8]
It also used for some active record operations in ruby. For example we have a Cart and LineItem model associated as cart has_many line_items. Cart.find(A).line_items will return ActiveRecord::Associations object with line items that belongs to cart 'A'.
Now, to add (or say to associate) another line_item (X) to cart (A),
Cart.find(A).line_items << LineItem.find(X)
Now to add another LineItem to the same cart 'A', but this time we will not going to create any line_item object (I mean will not create activerecord object manually)
Cart.find(A).line_items << LineItem.new
In above code << will save object and append it to left side active record association array.
And many others which are already covered in above answers.
Also, since Ruby 2.6, the << method is defined also on Proc.
Proc#<< allows to compose two or more procs.
It means add to the end (append).
a = [1,2,3]
a << 4
a = [1,2,3,4]
I've seen how to overload + and * in Ruby, so that
my_obj + other calls my_obj.+(other). In Python, you do this with __add__, and there's a corresponding __radd__ for overloading other + my_obj. Is there really no equivalent right-sided addition/multiplication in Ruby, and does that make it necessary to redefine + for each potential class of other?
In brief: say I have an object X which belongs to some new class defined by me. It's easy to write code for X + 5, but it seems that in order to handle 5 + X I'd need to redefine Fixnum.+. Is this true?
No, you don't need to redefine Fixnum#+ (or any other arithmetic method of ruby's numeric classes). The arithmetic methods of the numeric classes will call coerce if the two operands are not the same class. So if you define a coerce method for your class, 5 + instance_of_your_class will work fine without any changes to Fixnum#+.
Edit: Here's an example of using coerce:
class MyNum
attr_accessor :num
def initialize(num)
#num = num
end
def +(o)
lhs, rhs = coerce(o)
MyNum.new(lhs.num + rhs.num)
end
def coerce(o)
if o.is_a? MyNum
[self, o]
else
[self, MyNum.new(o)]
end
end
end
MyNum.new(5)+3 #=> #<MyNum:0x87fca08 #num=8>
3+MyNum.new(5) #=> #<MyNum:0x8807980 #num=8>
The RHS is coerced and needs to implement the to_i method which needs to return an appropriate value. The Numeric's classes implementation of to_int will end up calling it as part of the process of addition where other classes are involved on the RHS than strict Numeric descendants.
Yes. If you want to alter the behavior on 5 + x, you have to redefine + on whatever 5 is, since you're in fact calling 5.+(x) because of Ruby treating these kinds of operations as mechod calls.