What I wanted was a way to pass arguments into functions which resembled a ruby hash map. Although maybe this is a bad fit for Erlang, I'm not sure yet
In Ruby I often used hashes like:
{"a"=>100, "b"=>200}
: What is the closest thing in Erlang?
Update:
I have since found this:
http://20bits.com/articles/erlang-an-introduction-to-records/
Is using records a good candidate?
proplists, dicts, or gb_trees.
Erlang R17A will include map data structure.
ETS and DETS tables are true hash tables unlike a dict. DETS are for disks storage while ETS are in memory. They are the building blocks for the Mnesia database.
Here You are: dict - Key-Value Dictionary
Post scriptum: I have googled this within 30s so I think You could avoid this asking question ;-)
Edit: To defend my answer:
from_list(List) -> Dict
Types:
List = [{Key, Value}]
Dict = dictionary()
This function converts the key/value list List to a dictionary.
This is a quotation from my link. So You can create hashes exactly the same way as when You use proplists.
Related
I use Array.wrap(x) all the time in order to ensure that Array methods actually exist on an object before calling them.
What is the best way to similarly ensure a Hash?
Example:
def ensure_hash(x)
# TODO: this is what I'm looking for
end
values = [nil,1,[],{},'',:a,1.0]
values.all?{|x| ensure_hash(x).respond_to?(:keys) } # true
The best I've been able to come up with so far is:
Hash::try_convert(x) || {}
However, I would prefer something more elegant.
tl; dr: In an app with proper error handling, there is no "easy, care-free" way to handle something that may or may not be hashy.
From a conceptual standpoint, the answer is no. There is no similar solution as Array.wrap(x) for hashes.
An array is a collection of values. Single values can be stored outside of arrays (e.g. x = 42) , so it's a straight-forward task to wrap a value in an array (a = [42]).
A hash is a collection of key-value pairs. In ruby, single key-value pairs can't exist outside of a hash. The only way to express a key-value pair is with a hash: h = { v: 42 }
Of course, there are a thousand ways to express a key-value pair as a single value. You could use an array [k, v] or a delimited string `"k:v" or some more obscure method.
But at that point, you're no longer wrapping, you're parsing. Parsing relies on properly formatted data and has multiple points of failure. No matter how you look at it, if you find yourself in a situation where you may or may not have a hash, that means you need to write a proper chunk of code for data validation and parsing (or refactor your upstream code so that you can always expect a hash).
I'm new to ruby, and apologies in advance as I strongly suspect I'm missing something really obvious here. But..
I'm trying to create objects dynamically, based on an array of hashes. But how do I store the objects?
If I was creating just one, I'd do a variable assignment like so:
h = PuppetNode.new(hash)
print h.hostname # foo.bar.com
but what about here?:
array_of_hashes.each { | hash |
h = PuppetNode.new(hash)
}
This will result in the 'h' object being overwritten won't it?
I suppose I could try to extract something from the hash to name the variable dynamically, but it seems like it is unnecessary as various instance variables mark out the unique-ness of each object.
Do I really need to use a variable at all? If not, how do I create/store the objects. If so, how can I dynamically set the variable name without painful regex use?
Thanks in advance
If you want to store multiple objects, you can use a collection object to do that. Ruby comes with two kinds of collection objects built into the core library: Array (a linear sequence of elements addressable by numeric index) and Hash (a mapping from key objects to value objects, addressable by key). In the standard library, there are additional kinds of collection objects such as Set (a collection that tracks membership of values) and SortedSet.
Initial note: I'm working in Julia, but this question probably applies to many languages.
Setup: I have a composite type as follows:
type MyType
x::Vector{String}
end
I write some methods to act on MyType. For example, I write a method that allows me to insert a new element in x, e.g. function insert!(d::MyType, itemToInsert::String).
Question: Should MyType be mutable or immutable?
My understanding: I've read the Julia docs on this, as well as more general (and highly upvoted) questions on Stackoverflow (e.g. here or here), but I still don't really have a good handle on what it means to be mutable/immutable from a practical perspective (especially for the case of an immutable composite type, containing a mutable array of immutable types!)
Nonetheless, here is my attempt: If MyType is immutable, then it means that the field x must always point to the same object. That object itself (a vector of Strings) is mutable, so it is perfectly okay for me to insert new elements into it. What I am not allowed to do is try and alter MyType so that the field x points to an entirely different object. For example, methods that do the following are okay:
MyType.x[1] = "NewValue"
push!(MyType.x, "NewElementToAdd")
But methods that do the following are not okay:
MyType.x = ["a", "different", "string", "array"]
Is this right? Also, is the idea that the object that an immutable types field values are locked to are those that are created within the constructor?
Final Point: I apologise if this appears to duplicate other questions on SO. As stated, I have looked through them and wasn't able to get the understanding that I was after.
So here is something mind bending to consider (at least to me):
julia> immutable Foo
data::Vector{Float64}
end
julia> x = Foo([1.0, 2.0, 4.0])
Foo([1.0,2.0,4.0])
julia> append!(x.data, x.data); pointer(x.data)
Ptr{Float64} #0x00007ffbc3332018
julia> append!(x.data, x.data); pointer(x.data)
Ptr{Float64} #0x00007ffbc296ac28
julia> append!(x.data, x.data); pointer(x.data)
Ptr{Float64} #0x00007ffbc34809d8
So the data address is actually changing as the vector grows and needs to be reallocated! But - you can't change data yourself, as you point out.
I'm not sure there is a 100% right answer is really. I primarily use immutable for simple types like the Complex example in the docs in some performance critical situations, and I do it for "defensive programming" reasons, e.g. the code has no need to write to the fields of this type so I make it an error to do so. They are a good choice IMO whenever the type is a sort of an extension of a number, e.g. Complex, RGBColor, and I use them in place of tuples, as a kind of named tuple (tuples don't seem to perform well with Julia right now anyway, wheres immutable types perform excellently).
I am looking to make an efficient function to clear out a redis-based cache.
I have a method call that returns a number of keys from redis:
$redis.keys("foo:*")
That returns all the keys that start with "foo:". Next, I'd like to delete all the values for these keys.
One (memory-intensive) way to do this is:
$redis.keys("foo:*").each do |key|
$redis.del(key)
end
I'd like to avoid loading all the keys into memory, and then making numerous requests to the redis server.
Another way that I like is to use the splat operator:
keys = $redis.keys("foo:*")
$redis.del(*keys)
The problem is that I don't know what the maximum arity of the $redis.del method, nor of any ruby method, I can't seem to find it online.
What is the maximum arity?
#muistooshort in the comments had a good suggestion that turned out to be right, the redis driver knows what to do with an array argument:
# there are 1,000,000 keys of the form "foo:#{number}"
keys = $redis.keys("foo:*")
$redis.del(keys) # => 1000000
Simply pass an array of keys to $redis.del
Whenever I see Ruby code that says:
arrayNames.collect { ... }
I forget what collect is and have to look up what it is, and find that it is the same as map().
Map, I can understand, mapping 1 byte to a pixel, and function is to map an x to a y, a 2 to a 4, a 5 to a 25, etc. But where does the name "collect" come from? Maybe that will help to remember what a "collect" method is.
It comes from Smalltalk old days. Smalltalk used collect and select instead of map and filter (as used in many other languages) for iterating on its collections.
To add to the other answers, it is kind of an inside-joke in Smalltalk:
inject:into:
collect:
select:
reject:
detect:
Spot the pattern?
kriss is right that the method name has its origins in Smalltalk but to help remember what it does when you see it used you can think of it as "collecting the results from the block in a new array".