What is the highest level in the object model? (Junior)
Which core object includes the "Kernel" module? (Junior)
What can you say about an identifier that begins with a capital letter? (Junior)
Why Ruby is known as a language of flexibility? (Junior)
Is there an equivalent of “continue” in Ruby? (Junior)
Is everything in Ruby an object? (Junior)
Explain redo statement in Ruby (Mid)
Why are symbols typically used as hash keys instead of strings? (Mid)
How might you specify a default value for a hash? (Mid)
What is the difference between nil and false in Ruby? (Mid)
Why might you use Hash#fetch
over Hash#[]
when querying values in a hash? (Mid)
Explain some differences between Ruby and Python (Mid)
What are two uses of the splat operator? (Mid)
What is the difference between an instance variable and a class variable? (Mid)
What is the return value for ... (Mid)
What is the difference between #==
and #===
? (Mid)
How do you remove nil
values in array using ruby? (Mid)
Can you call a private method outside a Ruby class using its object? (Mid)
What will be the values of ... (Mid)
Explain each of the following operators and how and when they should be used (Mid)
Write a function that sorts the keys in a hash by the length of the key as a string. (Mid)
Which of the expressions listed below will result in "false"? (Mid)
Why might you use #each
instead of for/in
? (Mid)
There are three ways to invoke a method in ruby. Can you give me at least two? (Mid)
What is a module? Can you tell me the difference between classes and modules? (Mid)
What is a DSL and how does it pertain to Ruby? (Mid)
What is duck typing and how does it pertain to Ruby? (Mid)
Is Ruby a statically typed or a dynamically typed language? (Mid)
Are instance methods public or private? (Mid)
What is a predicate in the context of Ruby method naming conventions? (Mid)
Is Ruby a strongly typed or a weakly typed language? (Mid)
Check if a value exists in an array in Ruby (Mid)
What is the difference between private and protected methods? (Mid)
Are class variables inherited? (Mid)
What is the difference between a class variable and a class instance variable? (Mid)
What does it mean to coerce an object? Why would you do it? (Mid)
What will val1 and val2 equal after the code below is executed? Explain your answer. (Senior)
Explain redo vs. retry usage (Senior)
Why might you want to avoid using string literals within loops? (Senior)
What is the difference between Proc invocation and lambda invocation? (Senior)
What is the main difference between procs and lambdas? (Senior)
Why can you safely use a string as a hash key, even though a string is mutable? (Senior)
What are two uses of ranges? (Senior)
What is the difference between Module#remove_method
and Module#undef_method
? (Senior)
Which operator must be defined in order to implement the Comparable
module? (Senior)
What is the difference between Kernel#require
and Kernel#load
? (Senior)
Why might you want to alias a method? (Senior)
What will be the value of ... (Senior)
What does a bang !
at the end of a method signify? (Senior)
What is the value of the variable "upcased" in the below piece of code? (Senior)
How does block invocation differ from method invocation? (Senior)
What is the difference between #==
and #equal?
? (Senior)
Explain this ruby idiom: a ||= b (Senior)
What is the difference between #==
and #eql?
? (Senior)
Describe a closure in Ruby (Senior)
What is the difference between Array#map
and Array#each
? (Senior)
What is the difference between throw/catch
and raise/rescue
? (Senior)
What are some disadvantages of a case statement versus repeated elsif
statements? (Senior)
What is the difference between calling "super" and calling "super()" (Senior)
When might you use the do
/end
syntax versus using the curly bracket syntax for a block? (Senior)
Explain the difference between (Senior)
What happens if a block is passed two arguments but only accepts one argument? (Expert)
How exactly does it work? (Expert)
Is the line of code below valid Ruby code? If so, what does it do? (Expert)
What will be the result of each of the following lines of code (Expert)
What happens to a constant which is not assigned? (Expert)
Is a block an object? (Expert)
What is the primary difference in these two code snippets? (Expert)
Why doesn't Ruby support method overloading? (Expert)
Is a method an object? (Expert)
What is the difference between BasicObject#instance_eval
and BasicObject#instance_exec
? (Expert)
What is the difference between Object#dup
and #clone
? (Expert)
What is an eigenclass? (Expert)
When might you encounter a LocalJumpError
? (Expert)
What is the differnece between extend
and include
in ruby? (Expert)
BasicObject
Object
It is a constant.
Ruby is known as a language of flexibility because it facilitates its author to alter the programming elements. Some specific parts of the language can be removed or redefined. Ruby does not restrict the user. For example, to add two numbers, Ruby allows to use +
sign or the word plus
. This alteration can be done with Ruby's built-in class Numeric.
An instance of a class. To some, it's also the root class in ruby (Object). Classes themselves descend from the Object root class.
Classes hold data, have methods that interact with that data, and are used to instantiate objects.
class WhatAreClasses
def initialize
@data = "I'm instance data of this object. Hello."
end
def method
puts @data.gsub("instance", "altered")
end
end
object = WhatAreClasses.new
object.method
#=> I'm altered data of this object. Hello.
rubygems is package manager software for ruby libraries (i.e. gems). The package manager has basic CRUD operations, dependency trees, and supports asynchronous communication between multiple gem servers.
Yes, it's called next
.
for i in 0..5
if i < 2
next
end
puts "Value of local variable is #{i}"
end
Methods are not objects. Blocks are not objects. Keywords are not objects. However, there exist Method objects and Proc objects, and some keywords refer to objects.
Ruby redo
statement is used to repeat the current iteration of the loop. The redo statement is executed without evaluating loop's condition.
Strings are mutable while symbols are immutable. Though Ruby internally makes an immutable copy of a string when used as a hash key, comparing two symbols is faster than comparing two String
objects. This is also a convention.
Pass the default values as arguments to ::new
on initialization or change the default directly with the method Hash#default
. You may also provide a default at the time of query with Hash#fetch
.
nil:
- nil cannot be a value
- nil is returned where there is no predicate
- nil is not a boolean data type
- nil is an object of nilclass
false:
- false can be a value
- in case of a predicate, true or false is returned by a method
- false is a boolean data type
- false is an object of falseclass
Hash#fetch
provides options for handling the case where a key does not exist in the hash.
Similarities:
- High level language
- Support multiple platforms
- Use interactive prompt called irb
- Server side scripting language
Differences:
- Ruby is fully object oriented while Python is not.
- Ruby supports EclipseIDE while Python supports multiple IDEs.
- Ruby use Mixins while Python doesn't.
- Ruby supports blocks, procs and lambdas while Python doesn't.
- Explode or expand the elements of an array.
- Collect arguments of a parameter list into an array.
A class variable is evaluated in reference to the class object created by the enclosing class definition while an instance variable is evaluated in reference to self
. Instance variables cannot be referenced outside of instance methods.
All the statements for the invocation of the xyz method through the object are valid.
When run through IRB
:
irb(main):001:0> ABC::new::xyz
xyz in ABC
=> nil
irb(main):002:0> ABC::new.xyz
xyz in ABC
=> nil
irb(main):003:0> ABC.new::xyz
xyz in ABC
=> nil
irb(main):004:0> ABC.new.xyz
xyz in ABC
=> nil
#==
performs the generic comparison while #===
performs case equality comparison and is useful for providing meaningful semantics in case statements.
Array#compact
removes nil
values.
>> [nil,123,nil,"test"].compact
=> [123, "test"]
Yes, with the help of the send
method.
Given the class Test
:
class Test
private
def method
p "I am a private method"
end
end
We can execute the private method using send
:
>> Test.new.send(:method)
"I am a private method"
- var1 will be equal to
nil
- var2 will be equal to
4
A conditional statement in Ruby is an expression that returns nil
if the conditional is false
. Ruby methods return the last expression in the method body.
-
==
– Checks if the value of two operands are equal (often overridden to provide a class-specific definition of equality). -
===
– Specifically used to test equality within thewhen
clause of acase
statement (also often overridden to provide meaningful class-specific semantics in case statements). -
eql?
– Checks if the value and type of two operands are the same (as opposed to the==
operator which compares values but ignores types). For example,1 == 1.0
evaluates totrue
, whereas1.eql?(1.0)
evaluates tofalse
. -
equal?
– Compares theidentity
of two objects; i.e., returnstrue
iff both operands have the same object id (i.e., if they both refer to the same object). Note that this will returnfalse
when comparing two identical copies of the same object.
As is always true in programming, there are in fact multiple ways to accomplish this. The most straightforward answer would be of the form:
hsh.keys.map(&:to_s).sort_by(&:length)
or:
hsh.keys.collect(&:to_s).sort_by { |key| key.length }
Alternatively, Ruby’s Enumerable
mixin provides many methods to operate on collections. The key here is to turn the hash keys into a collection, convert them all to strings, then sort the array.
def key_sort hsh
hsh.keys.collect(&:to_s).sort { |a, b| a.length <=> b.length }
end
An equivalent call of the collect
method is done with the usual block syntax of:
collect { |x| x.to_s }
In Ruby, the only values that evaluate to false are false
and nil
. Everything else – even zero (0) and an empty array ([]) – evaluates to true.
This comes as a real surprise to programmers who have previously been working in other languages like JavaScript.
It's the "Ruby way" - an example of how Ruby defines methods that mimic natural language concepts. Iterator methods such as #each
read more naturally. #each
is a block so it defines a new variable scope. for/in
depends on the existence of #each
which implies that #each
is a more fundamental aspect of the language.
We are looking for the dot operator (or period operator), the Object#send method, or method(:foo).call
object = Object.new
puts object.object_id
#=> 282660
puts object.send(:object_id)
#=> 282660
puts object.method(:object_id).call # (Kudos to Ezra)
#=> 282660
Modules serve as a mechanism for namespaces.
module ANamespace
class AClass
def initialize
puts "Another object, coming right up!"
end
end
end
ANamespace::AClass.new
#=> Another object, coming right up!
Also, modules provide as a mechanism for multiple inheritance via mix-ins and cannot be instantiated like classes can.
module AMixIn
def who_am_i?
puts "An existentialist, that's who."
end
end
# String is already the parent class
class DeepString < String
# extend adds instance methods from AMixIn as class methods
extend AMixIn
end
DeepString.who_am_i?
#=> An existentialist, that's who.
AMixIn.new
#=> NoMethodError: undefined method ‘new’ for AMixIn:Module
A Domain Specific Language is an API that allows a developer to solve a problem or represent data more naturally than they might otherwise. The flexible nature of Ruby's syntax and the ability to alias and alter existing methods and classes makes it conducive to creating rich DSL's.
That an object may be acted upon even if it isn't the expected type as long as it looks and behaves like the expected object. This is a characteristic of Ruby because the lack of type checking of parameters makes this an effective programming technique.
Dynamically typed since type checking is done at runtime.
They are public by default. You can change their visibility using Module#private
, Module#protected
, or back again using Module#public
.
A method that answers a question posed by the method invocation or method name. Predicates typically return a boolean.
$ irb
> 5.odd?
=> true
> 5.even?
=> false
> 5.between?(1, 10)
=> true
> 5.between?(11, 20)
=> false
Strongly typed since an object's type is checked before an operation is performed on it.
You're looking for include?:
>> ['Cat', 'Dog', 'Bird'].include? 'Dog'
=> true
A private method can only be called by any instance methods of the defining class or any subclasses and must be invoked in a functional style and not explicitly on self
such as with self.my_method
. A protected method may be explicitly invoked by any instance of the defining class, and is not restricted to implicit invocation on self
.
No. The behavior is different than inheritance. Any alteration of a class variable by a subclass affects that class variable in the superclass and all other subclasses of the superclass.
Class instance variables are instance variables of a class. Class instance variables cannot be used within instance methods.
To coerce an object means to force it into an expected type. One might do this in order to try and force an unknown object type into the expected type or format required by the operation. This is a common practice involved in duck typing.
Although these two statements might appear to be equivalent, they are not, due to the order of operations. Specifically, the and
and or
operators have lower precedence than the =
operator, whereas the &&
and ||
operators have higher precedence than the =
operator, based on order of operations.
To help clarify this, here’s the same code, but employing parentheses to clarify the default order of operations:
(val1 = true) and false # results in val1 being equal to true
val2 = (true && false) # results in val2 being equal to false
This is, incidentally, a great example of why using parentheses to clearly specify your intent is generally a good practice, in any language. But whether or not you use parentheses, it’s important to be aware of these order of operations rules and to thereby ensure that you are properly determining when to employ and
/ or
vs. &&
/ ||
.
redo
and retry
are both used to re-execute parts of a loop. But they differ in how much they re-execute:
redo
only repeats the current iteration, whileretry
repeats the whole loop from the start.
A new object is created for every string literal even when the values are identical. Consider using variables or symbols instead.
A block must be associated with lambda invocation. Lambdas must be invoked with the exact number of arguments such as is required by method invocation, whereas procs are more flexible in receiving arguments.
Calling a lambda is more akin to invoking a method where a return statement in a lambda will return from the lambda itself, instead of returning from the lexically enclosing method, as procs do. Adding to this notion, lambdas must be invoked with the exact number of arguments such as is required by method invocation, whereas procs are more flexible in receiving arguments.
Because the interpreter makes a private copy of a string used as a hash key.
- comparison
- iteration
Module#undef_method
prevents any invocation of the method through an instance of the class, while Module#remove_method
will remove the method definition from the class, but not prevent inherited methods of the same name from being invoked.
<=>
Kernel#require
can load binary extensions. Kernel#require
does not require a filename extension. Kernel#require
prevents multiple loads of the same file path. Kernel#load
loads the specified file at the current $SAFE
level while Kernel#require
loads the specified file with a $SAFE
level of 0.
How is the invocation of a private method different than the invocation of a public method from within its defining class? (Senior)
It must be referenced in a functional manner without an explicit receiver object and not on the class object itself or on the current object self
.
To create a synonym for an existing method that is more readable or appropriate in the context of some problems or to add functionality to an existing method.
defined? foo
#=> "local-variable"
defined? bar
#=> nil
foo
has been at least read by the interpreter, therefore it is defined and assigned a nil
value. However, since bar
has never been written, it was never defined in the first place.
That it should be with caution. Methods with this naming convention typically perform a *mutation on the receiver object.
Let’s take a look at puts
as below:
>> puts "Hi"
Hi
=> nil
Note the nil
at the end: that’s the return value from puts
. After all, puts
is a method
, so it has to return something. As it happens, it always returns nil
. The printing out of the string is an action the method performs.
Similarly, evaluating the code in question we can understand that while it’s a common learner mistake to expect the result to be ["ONE", "TWO", "THREE"]
. In fact, it’s [nil, nil, nil]
. Each time through the block, the block evaluates to the return value of puts
to be nil
.
Ruby will throw an exception if more than the expected number of arguments are passed to a method. A block will simply ignore the extra values.
Can you tell me the three levels of method access control for classes and modules? What do they imply about the method? (Senior)
All methods, no matter the access control, can be accessed within the class. But what about outside callers?
- Public methods enforce no access control -- they can be called in any scope.
- Protected methods are only accessible to other objects of the same class.
- Private methods are only accessible within the context of the current object.
class AccessLevel
def something_interesting
another = AccessLevel.new
another.public_method
another.protected_method
another.private_method
end
def public_method
puts "Public method. Nice to meet you."
end
protected
def protected_method
puts "Protected method. Sweet!"
end
private
def private_method
puts "Incoming exception!"
end
end
AccessLevel.new.something_interesting
#=> Public method. Nice to meet you.
#=> Protected method. Sweet!
#=> NoMethodError: private method ‘private_method’ called for
#=> #<AccessLevel:0x898c8>
#==
performs the generic comparison and is implemented differently across classes while #equal?
is defined on BasicObject
and compares object identity. Therefore, #equal?
should not be overridden in subclasses.
Is it a common idiom that strong ruby developers will use all the time.
# a = b when a == false
# otherwise a remains unchanged
a || a = b # (Kudos to Markus Prinz)
a = 1
b = 2
a ||= b #=> a = 1
a = nil
b = 2
a ||= b #=> a = 2
a = false
b = 2
a ||= b #=> a = 2
self
always refers to the current object. But this question is more difficult than it seems because Classes are also objects in ruby.
class WhatIsSelf
def test
puts "At the instance level, self is #{self}"
end
def self.test
puts "At the class level, self is #{self}"
end
end
WhatIsSelf.test
#=> At the class level, self is WhatIsSelf
WhatIsSelf.new.test
#=> At the instance level, self is #<WhatIsSelf:0x28190>
This short snippet indicates two things:
- at the class level, self is the class, in this case WhatIsSelf.
- at the instance level, self is the instance in context, in this case the instance of WhatIsSelf at memory location 0x28190.
Essentially, Procs are anonymous methods (or nameless functions) containing code. They can be placed inside a variable and passed around like any other object or scalar value. They are created by Proc.new, lambda, and blocks (invoked by the yield keyword).
Note: Procs and lambdas do have subtle, but important, differences in ruby v1.8.6. However, I wouldn't expect a candidate talk about these nitty-gritty details during an interview. (Kudos to Noah Thorp)
# wants a proc, a lambda, AND a block
def three_ways(proc, lambda, &block)
proc.call
lambda.call
yield # like block.call
puts "#{proc.inspect} #{lambda.inspect} #{block.inspect}"
end
anonymous = Proc.new { puts "I'm a Proc for sure." }
nameless = lambda { puts "But what about me?" }
three_ways(anonymous, nameless) do
puts "I'm a block, but could it be???"
end
#=> I'm a Proc for sure.
#=> But what about me?
#=> I'm a block, but could it be???
#=> #<Proc:0x00089d64> #<Proc:0x00089c74> #<Proc:0x00089b34>
#eql?
is sometimes an alternate equality. Hash
uses #eql?
to test for hash key equality. Numeric
types perform type conversion across #==
but not across #eql?
, thus #eql?
performs a stricter comparison than #==
in that case.
A closure is an object that is both an invocable function together with a variable binding. The object retains access to the local variables that were in scope at the time of the object definition.
A closure in Ruby retain variables by reference; the closure also extends the lifetimes of its variables. A closure's reference to its variables is dynamically bound that means the values of the variables are resolved when the Proc
object is executed.
It also possible to alter a closure. The binding of a closure can be altered using #binding
.
Array#each
method iterates over the elements of the array and executes the provided block each time. However, it returns the original array unaffected.Array#map
will return a new array of elements containing the values returned by the block it is provided. It also does not affect the original array
An object that allows traversal of the elements of the container. In Ruby, an iterator is typically considered any method that uses the yield statement.
throw
and catch
accept matching symbols as arguments and should be considered a control-flow structure where raise
and rescue
is used to raise and handle exceptions. throw
and catch
are not commonly used while exception handling with raise
and rescue
is used often.
The statement is typically resistant to modification without a complete refactoring of the entire control structure. The case statement can be confusing if multiple comma-separated expressions are associated with a single when clause.
-
A call to
super
invokes the parent method with the same arguments that were passed to the child method. An error will therefore occur if the arguments passed to the child method don’t match what the parent is expecting. -
A call to
super()
invokes the parent method without any arguments, as presumably expected. As always, being explicit in your code is a good thing.
The do
/end
syntax for a block is commonly used for multi-line statements. An alternate convention is to use curly bracket syntax for blocks that return a value while using do
/end
syntax for blocks that change the state of the system somehow and do not return a value.
The +=
operator re-initializes the variable with a new value, so a += b
is equivalent to a = a + b
.
Therefore, while it may seem that +=
is mutating the value, it’s actually creating a new object and pointing the the old variable to that new object.
This is perhaps easier to understand if written as follows:
foo = "foo"
foo2 = foo
foo.concat "bar"
puts foo
=> "foobar"
puts foo2
=> "foobar"
foo += "baz"
puts foo
=> "foobarbaz"
puts foo2
=> "foobar"
(Examining the object_id
of foo
and foo2
will also demonstrate that new objects are being created.)
The difference has implications for performance and also has different mutation behavior than one might expect.
Nothing. Only the first argument will be passed to the block.
When a parameter is passed with &
in front of it (indicating that is it to be used as a block), Ruby will call to_proc
on it in an attempt to make it usable as a block. Symbol#to_proc
quite handily returns a Proc
that will invoke the method of the corresponding name on whatever is passed to it, thus enabling our little shorthand trick to work.
Yes, it’s valid. Here’s how to understand what it does:
The ->
operator creates a new Proc, which is one of Ruby’s function types. (The ->
is often called the “stabby proc”. It’s also called the “stabby lambda”, as it creates a new Proc instance that is a lambda. All lambdas are Procs, but not all Procs are lambdas. There are some slight differences between the two.)
This particular Proc takes one parameter (namely, a
). When the Proc is called, Ruby executes the block p a
, which is the equivalent of puts(a.inspect)
(a subtle, but useful, difference which is why p
is sometimes better than puts
for debugging). So this Proc simply prints out the string that is passed to it.
You can call a Proc by using either the call
method on Proc, or by using the square bracket syntax, so this line of code also invokes the Proc and passes it the string “Hello World”.
So putting that all together, this line of code (a) creates a Proc that takes a single parameter a
which it prints out and (b) invokes that Proc and passes it the string “Hello world”. So, in short, this line of code prints “Hello World”.
The first three lines of code will all print out 10, as expected. The next two lines of code will both print out 3, as expected.
However, the last line of code (i.e., sum (1,2)
) will result in the following:
syntax error, unexpected ',', expecting ')'
sum (1, 2)
^
The problem is the space between the method name and the open parenthesis. Because of the space, the Ruby parser thinks that (1, 2)
is an expression that represents a single argument, but (1, 2)
is not a valid Ruby expression, hence the error.
Note that the problem does not occur with single argument methods (as shown with our timesTwo
method above), since the single value is a valid expression (e.g., (5)
is a valid expression which simply evaluates to 5).
It does not exist.
No. A block is a syntactic structure of the interpreter. A block can be converted to a Proc object.
-
The Java method only accepts Strings as arguments and only returns a boolean while...
-
The ruby method accepts any Object and could return anything, but in this case will return a boolean if executed without exceptions.
Write a single line of Ruby code that prints the Fibonacci sequence of any length as an array. (Expert)
There are multiple ways to do this, but one possible answer is:
(1. .20).inject([0, 1]) { | fib | fib << fib.last(2).inject(: +)}
As you go up the sequence fib
, you sum, or inject(:+)
, the last two elements in the array and add the result to the end of fib
.
Note: inject
is an alias of reduce
Overloading is a term that simply doesn't even make sense in Ruby. It is basically a synonym for "static argument-based dispatch", but Ruby doesn't have static dispatch at all. So, the reason why Ruby doesn't support static dispatch based on the arguments, is because it doesn't support static dispatch, period. It doesn't support static dispatch of any kind, whether argument-based or otherwise.
No, however, a Method
object is of course, an object.
BasicObject#instance_exec
can only accept a block, not a string, and it can accept arguments and pass them to the block, allowing the block to be evaluated in the context of the receiver object with parameters whose values come from the block.
#clone
copies the frozen state of an object and any singleton methods of an object while Object#dup
does neither.
An anonymous class associated with an object. An object's singleton methods are instance methods of its associated eigenclass.
You might typically encounter this exception when attempting to yield when no block is given. You might also encounter this exception when attempting to return from a method that has already returned such as if you attempt to return from a Proc
object whose lexically enclosing method has already returned.
include
mixes in specified module methods as instance methods in the target classextend
mixes in specified module methods as class methods in the target class
Given the following class definitions:
module ReusableModule
def module_method
puts "Module Method: Hi there! I'm a module method"
end
end
class ClassThatIncludes
include ReusableModule
end
class ClassThatExtends
extend ReusableModule
end
Here’s how ClassThatIncludes
behaves:
# A class method does not exist
>> ClassThatIncludes.module_method
NoMethodError: undefined method `module_method' for ClassThatIncludes:Class
# A valid instance method exists
>> ClassThatIncludes.new.module_method
Module Method: Hi there! I'm a module method
=> nil
Here’s how ClassThatExtends
behaves:
# A valid class method exists
>> ClassThatExtends.module_method
Module Method: Hi there! I'm a module method
=> nil
# An instance method does not exist
ClassThatExtends.new.module_method
NoMethodError: undefined method `module_method' for #<ClassThatExtends:0x007ffa1e0317e8>
We should mention that object.extend ExampleModule
makes ExampleModule
methods available as singleton methods in the object.