views:

229

answers:

4

In Matlab, I recall being able to declare an array and initialize it and it resides in memory during the entire Matlab session. I could copy it, modify it, and run it through tests. Is this option available in Ruby? Basically I want to create and populate an array of 12 million 32-bit integers. Then I want to run code that accesses that memory. I don't want to have to re-initialize that array every time I tweak/debug my ruby code.

+3  A: 

If you are using the interactive ruby console (irb) then you can declare a global variable which contains your data.

$my_data = [1,2,3,4,5,6.....12000000]

then in your text editor of choice work on your code and require it into your irb session. This would let you work the way you want.

Daniel
+3  A: 

The global variable is one way but a bit cumbersome I'd say.

That means you want persistence of objects as you want it to be available across modifications of your code. You then need to initialize your data and save it in a file. You have several possibilities, something like YAML/JSON or, in a binary but more efficient way, Marshalling.

If you have a data structure, you can save it in YAML with this

require "yaml"

foo = SomeObject.new
File.open("bar.yaml", "w") do |fh|
  YAML.dump(foo, fh)
end

JSON is pretty much the same. Using Marshal.dump is equivalent.

Then you can have a method in your code that read in the data.

File.open(fname) do |fh|
  foo = YAML.load(fh)
end
Keltia
A: 

I assume that with session, you mean an open irb (interactive ruby), but this suggestion not limited to that.

The first thing to do is to initialize your data. It does not matter if you store the data as a global variable or as a local one that you pass around as parameters, because ruby passes parameters as references. When you change the code that works with the data, you should use the 'load' statement instead of 'require', because load forces ruby to parse the file again.

For example, lets say you have initialize your data in your irb

> data = (1..120).to_a
=> [1, 2, ...]

(Note that irb prints the array to the shell, so that initializing a large array with give you a lot of numbers running across your screen.) And your code that uses that data in a file called loadable.rb

def some_number(data)
  data[100]
end

Now you can load that file into irb and call the function.

> require 'loadable'
=> true
> some_number(data)
=> 101

When you change the code in loadable.rb to (let say) return the entry 10 instead of 100, reload the file, and call the function again, you will get different results for require and load.

> require 'loadable'
=> false
> some_number(data)
=> 101

With require, you get the old (wrong) result.

> load 'loadable.rb'
=> true
> some_number(data)
=> 11

With load you get the desired results. Note that you need to call load with the complete filename, including the '.rb'.

You could do this even without irb, by having one ruby program that initializes the data and then waits for changes in the other files in a loop, loads them again, and calls their functions.

jgre
A: 

Just create an array and refer to it. Simple as that. How and where you should create this array depends on your code. I'd say a constant makes most sense, because the array is constant, not variable.

THE_ARRAY = []

Add numbers to THE_ARRAY, and then use it. THE_ARRAY is a pointer, so when you call it, Ruby will get the same array from the same memory location every time.

August Lilleaas