Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there something like JavaScript hoisting in Ruby?

Tags:

ruby

I am wondering if variables and methods can be used before declaration in Ruby. Is there something like hoisting in JavaScript?

def calcArea
  getWidth * getHeight
end

def getWidth
  @w
end
def getHeight
  @h
end
@w = 10
@h = 20

p calcArea
like image 548
PJCHENder Avatar asked Dec 05 '22 15:12

PJCHENder


1 Answers

I am wondering if variables and methods can be used before declaration in Ruby.

Variables don't need to be declared in Ruby, so that part of the question doesn't make sense. Variables come into existence when they are first assigned, or, in the case of local variables, when their first assignment is parsed.

Methods are defined, not declared. A method definition is a piece of code just like any other piece of code. It needs to be executed to take effect. You cannot call a method that doesn't exist, and a method only exists after its definition has executed.

Is there something like hoisting in JavaScript?

No.

def calcArea
  getWidth * getHeight
end

def getWidth
  @w
end
def getHeight
  @h
end
@w = 10
@h = 20

p calcArea

This works just fine, but it has nothing to do with hoisting. You only call calcArea after it has been defined, so that's perfectly okay. calcArea calls getWidth and getHeight, but only when calcArea itself gets called, which is after all methods have been defined, so that's okay. getWidth and getHeight access @w and @h, but again, at the point that getWidth and getHeight are called, @w and @h have already been assigned, so that's okay, too. (And even if they hadn't been assigned, accessing them is still not an error, accessing an non-existent instance variable just evaluates to nil; obviously, you would then get a NoMethodError for trying to call * on nil, but that's very different from getting a NameError for a non-existent variable.)

Some notes on coding style:

  • Ruby uses snake_case for methods, parameters, local variables, instance variables, class variables, and global variables.
  • Ruby doesn't use a get prefix for getters.
  • Trivial getters should be named the same as the instance variable.
  • Also, calcArea is basically a getter for the area, so it, too, should be named without a prefix.
  • There should be a blank line after a method definition.

So, according to Ruby community style, your code should look like this:

def area
  width * height
end

def width
  @width
end

def height
  @height
end

@width  = 10
@height = 20

p area

If this were part of a module or class definition, then you could use attr_reader to auto-generate the getters, and attr_writer to generate setters:

class Rectangle
  attr_reader :width, :height

  def area
    width * height
  end

  private

  attr_writer :width, :height

  def initialize(width, height)
    self.width, self.height = width, height
  end
end

rect = Rectangle.new(10, 20)

p rect.area
like image 172
Jörg W Mittag Avatar answered Jan 07 '23 20:01

Jörg W Mittag