# Method variable that retains value between calls?

**URL:** <https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722>\
**Category:** Uncategorized\
**Created:** [August 17, 2021, 1:40pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722 "2021-08-17T13:40:23Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![thelmalu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c6cbf5/32.png) [@thelmalu](https://www.ruby-forum.com/u/thelmalu)\
**Post date:** [August 17, 2021, 1:40pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/1 "2021-08-17T13:40:24Z")

</div>

I’ve been unable to find this in searching. If it doesn’t exist, how do I approximate it?

---

<div class="post-metadata">

**Author:** ![G4143](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a88e57/32.png) [@G4143](https://www.ruby-forum.com/u/G4143)\
**Post date:** [August 17, 2021, 2:29pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/2 "2021-08-17T14:29:01Z")

</div>

Could you elaborate on what you mean? Maybe post some pseudo code.

---

<div class="post-metadata">

**Author:** ![thelmalu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c6cbf5/32.png) [@thelmalu](https://www.ruby-forum.com/u/thelmalu)\
**Post date:** [August 17, 2021, 3:41pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/3 "2021-08-17T15:41:08Z")

</div>

```
  def some_code(akey,aval)
   if !defined?(ahash)
      ahash=Hash.new(0) 
      anum = 1
   end
   puts "anum and ahash: #{anum} #{ahash}"

  ahash[akey] += aval*anum
  anum*=3
  return ahash.sum { |k,v| v }

```

end

some\_code(‘a’,4)  
some\_code(‘b’,6)  
puts “Total of ‘a’ ‘b’ ‘c’: #{some\_code(‘c’,10)}”

I’ve forgotten how to specify that I’m inserting code, so please excuse the formatting.

---

<div class="post-metadata">

**Author:** ![G4143](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a88e57/32.png) [@G4143](https://www.ruby-forum.com/u/G4143)\
**Post date:** [August 18, 2021, 2:44pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/4 "2021-08-18T14:44:25Z")

</div>

You use 3 apostrophes to delimit posted code.

I can’t see why this would be a problem… Can’t you just use an instance variable to maintain the state between calls?

Are you sure you don’t want a closure?

```auto
#! /usr/bin/env ruby
# frozen_string_literal: true

class MyFuncs
  def self.get_num()
    num = 0
    Proc.new {|x| num += 1; num}
  end
end

func2 = MyFuncs.get_num()
func3 = MyFuncs.get_num()

puts func2.call()
puts func2.call()
puts func2.call()
puts func3.call()

```

---

<div class="post-metadata">

**Author:** ![thelmalu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c6cbf5/32.png) [@thelmalu](https://www.ruby-forum.com/u/thelmalu)\
**Post date:** [August 18, 2021, 3:29pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/5 "2021-08-18T15:29:01Z")

</div>

Thank you.  
I will do that if it’s really necessary.  
I’m an old lady whose first language was Fortran and I was hoping to avoid setting up a class…

I’m doing the problems in the Exercism Ruby Track purely for amusement, not aiming for mastery, but I’m glad that there are people out here to help.

---

<div class="post-metadata">

**Author:** ![G4143](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/a88e57/32.png) [@G4143](https://www.ruby-forum.com/u/G4143)\
**Post date:** [August 18, 2021, 5:11pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/6 "2021-08-18T17:11:03Z")

</div>

The only exposure I had with Fortran was Problem Solving and Structured Programming in WATFIV(35 years ago). Still have the book.

---

<div class="post-metadata">

**Author:** ![topos](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/f0a364/32.png) [@topos](https://www.ruby-forum.com/u/topos)\
**Post date:** [August 19, 2021, 1:00pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/7 "2021-08-19T13:00:44Z")

</div>

Generally, changing variables outside the scope of a method is considered as bad practice.

If you want to handle a stativ-variable, why not use an instance var?

```ruby
def ahash
  if @ahash.nil?
     @ahash=Hash.new(0) 
     anum = 1
  end
  @ahash
end
def ahash= val
  @ahash = val
end
def some_code(akey,aval)
    puts "anum and ahash: #{anum} #{ahash}"
    ahash[akey] += aval*anum
    anum*=3
    ahash.sum { |k,v| v }
 end
```

---

<div class="post-metadata">

**Author:** ![Ludovic](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/7ab992/32.png) [@Ludovic](https://www.ruby-forum.com/u/Ludovic)\
**Post date:** [August 20, 2021, 7:58pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/8 "2021-08-20T19:58:31Z")

</div>

Hi @thelmalu,

As said, Ruby is object oriented, class is something you will use a lot 🙂

The difficulty here is you miss a concept: the scopes. I hope this post will help you:  
“[Variable Scope and Visibility](https://sodocumentation.net/ruby/topic/4094/variable-scope-and-visibility)”.

To summarize, you have 4 scopes in Ruby:

- Global: variable start with ‘$’. Visible across all your application. Be aware than constants (start with a capital) are global. If you wonder why a class or module start with a capital, it’s because Ruby assign it to a constant.
- Instance: variable start with ‘@’. Visible into a living object (as an instance of a class).
- Locale: any other variables. Only visible within the current context.

The last is the class variable, start with ‘@@’ and can be a nightmare because its use-case is special. Don’t use it for now.

Okay, now your example.

You try to reuse a locale variable into your method. But this variable will be gone when the method returns. You will create a new local variable for each call.

The best solution for you is to use an object to track the content of your “ahash” and “anum” values.

If you think an object is overkill for you, you can use an anonymous function. Perhaps it’s a bit premature to introduce you to this, but it’s really a simple concept. We call it a “lambda”.

The advantage of a lambda is than you have the same rule as with a method but a lambda live in the context of where it was created. So, you can access any variable declared beforehand.

Because lambda is an object, you can’t call it directly as with a method. You must use “.call” to fire the code into it.

Ready for a try? Open an irb console and copy-past the code:

```auto
ahash = Hash.new(0) 
anum = 1

some_code = lambda do |akey, aval|
  puts "anum and ahash: #{anum} #{ahash}"

  ahash[akey] += aval*anum
  anum*=3
  ahash.sum { |k,v| v }
end

```

Now, test our code. Don’t foget a lambda (or a proc) need to use the method `call`:

```auto
some_code.call("a", 4)
# anum and ahash: 1 {}
# => 4

some_code.call("b", 6)
# anum and ahash: 3 {"a"=>4}
# => 22

ahash
# => {"a"=>4, "b"=>18}

```

That’s it.

But the most usual way is to play with object. It’s not much efforts:

```auto

class MyObject
  def initialize
    @ahash = Hash.new(0) 
    @anum = 1
  end

  def some_code(akey, aval)
    puts "anum and ahash: #{@anum} #{@ahash}"

    @ahash[akey] += aval*@anum
    @anum*=3
    @ahash.sum { |k,v| v }
  end
end

```

And play with it:

```auto
my_object = MyObject.new

my_object.some_code("a", 4)
# anum and ahash: 1 {}
# => 4

my_object.some_code("b", 6)
# anum and ahash: 3 {"a"=>4}
# => 22

```

It’s ok too. What is the internal state of your object?

```auto
puts my_object.inspect
# <MyObject:0x000055984d84e690 @ahash={"a"=>4, "b"=>18}, @anum=9>

```

> Keep in mind than any method / lambda / proc / block will return the last expression. No need to explicitly use `return` because your last line will always return.

Have enjoy in your coding 🙂

---

<div class="post-metadata">

**Author:** ![thelmalu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/c6cbf5/32.png) [@thelmalu](https://www.ruby-forum.com/u/thelmalu)\
**Post date:** [August 20, 2021, 11:41pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/9 "2021-08-20T23:41:53Z")

</div>

Thank you. This is very clear and helpful. I knew about lambda, but didn’t realize it could be used in this way.  
I will, however, take everyone’s advice, and create a class object. Otherwise, what I’m really doing is trying to reduce Ruby to an emulation of my mid-1960’s Fortran.

---

<div class="post-metadata">

**Author:** ![Cufe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/96bed5/32.png) [@Cufe](https://www.ruby-forum.com/u/Cufe)\
**Post date:** [September 2, 2021, 7:58pm UTC](https://www.ruby-forum.com/t/method-variable-that-retains-value-between-calls/261722/10 "2021-09-02T19:58:24Z")

</div>

Maybe this will help? In this code I’m using readline instead of the gets method for a basic repl.

CODE:  
require ‘readline’

def phase\_color(circuit)  
a = circuit.to\_i % 6  
if a == 0  
puts “blue/yellow”  
end

```
 if a == 1
 puts "black/brown"
 end

 if a == 2
 puts "black/brown"
 end
 
 
 if a == 3
 puts "red/orange"
 
 end
 if a == 4
 puts "red/orange"
 end
  if a ==5
  puts "blue/yellow"
  end
  
  if a == 6
  puts "blue/yellow"
  end
 
puts a

```

end

This method is very basic. I had to use multiple if statments because I used dcoder on my phone.

This program I made to help me identify phase colors in the American standard. The formula is simple. The circuit number divided by 6. I don’t need anything but the remainder. So circuit.to\_i % 6 will divide my input number and only return the remainder value.

The second half of the code:

while input = Readline.readline("circuit number: ")  
phase\_color(input)  
exit(0)  
break if input == “exit”

end

This part of the code gives the user a prompt. This case, a numeric input. It takes the user input and updates the circuit argument for phase\_color, then runs the algorithm within the a variable of the method. Depending on the return of variable a, the if statement that is true will be returned.
