This question already has answers here:
What does ||= (or-equals) mean in Ruby?
(23 answers)
Closed 8 years ago.
In my readings about structuring methods with options hashes for ruby, I've run into a coding "motif" a few times that I can't explain. Since I don't know what it's called, I'm having a lot of difficulty looking it up to learn more about it.
Here's an example:
1 def example_method(input1, options={})
2
3 default_options = {
4 :otherwise => "blue",
5 :be_nil => nil
6 }
7
8 options[:be_nil] ||= options[:otherwise]
9
10 # other code goes down here
11 end
So above, on line 8, you can see what I'm talking about. From what I can put together, the line of code acts similarly to a tertiary operator. Under one condition, it sets a variable to one value... under a different condition, it sets the variable to a different value. In this case, however, the code updates a hash that's stored in the "options" variable. Is that a correct assumption? Furthermore, what is this style/operator/functionality called?
THis is a conditional assignment. The variable on the left will be assigned a value if it is nil or false. This is the short for of saying:
unless options[:be_nil]
options[:be_nil] = options[:otherwise]
end
Related
This question already has answers here:
Concatenation of tables in Lua
(13 answers)
Closed 7 years ago.
Is there an easy way to concatenate two tables which are sequences? For example
a = {1, 2, 3}
b = {5, 6, 7}
c = cat(a,b)
where c would be the table {1,2,3,5,6,7}?
function cat(t, ...)
local new = {unpack(t)}
for i,v in ipairs({...}) do
for ii,vv in ipairs(v) do
new[#new+1] = vv
end
end
return new
end
It uses iteration to add the elements of each array to a new one.
It's also worth noting that {unpack(t)} will only work if you have less than a specific number of elements, due to how tuples work in Lua. This varies across versions and depending on what you're doing, but if it's small you probably have nothing to worry about.
This question already has answers here:
Lua for loop reduce i? Weird behavior [duplicate]
(3 answers)
Closed 7 years ago.
im trying this in lua:
for i = 1, 10,1 do
print(i)
i = i+2
end
I would expect the following output:
1,4,7,10
However, it seems like i is getting not affected, so it gives me:
1,2,3,4,5,6,7,8,9,10
Can someone tell my a bit about the background concept and what is the right way to modify the counter variable?
As Colonel Thirty Two said, there is no way to modify a loop variable in Lua. Or rather more to the point, the loop counter in Lua is hidden from you. The variable i in your case is merely a copy of the counter's current value. So changing it does nothing; it will be overwritten by the actual hidden counter every time the loop cycles.
When you write a for loop in Lua, it always means exactly what it says. This is good, since it makes it abundantly clear when you're doing looping over a fixed sequence (whether a count or a set of data) and when you're doing something more complicated.
for is for fixed loops; if you want dynamic looping, you must use a while loop. That way, the reader of the code is aware that looping is not fixed; that it's under your control.
When using a Numeric for loop, you can change the increment by the third value, in your example you set it to 1.
To see what I mean:
for i = 1,10,3 do
print(i)
end
However this isn't always a practical solution, because often times you'll only want to modify the loop variable under specific conditions. When you wish to do this, you can use a while loop (or if you want your code to run at least once, a repeat loop):
local i = 1
while i < 10 do
print(i)
i = i + 1
end
Using a while loop you have full control over the condition, and any variables (be they global or upvalues).
All answers / comments so far only suggested while loops; here's two more ways of working around this problem:
If you always have the same step size, which just isn't 1, you can explicitly give the step size as in for i =start,end,stepdo … end, e.g. for i = 1, 10, 3 do … or for i = 10, 1, -1 do …. If you need varying step sizes, that won't work.
A "problem" with while-loops is that you always have to manually increment your counter and forgetting this in a sub-branch easily leads to infinite loops. I've seen the following pattern a few times:
local diff = 0
for i = 1, n do
i = i+diff
if i > n then break end
-- code here
-- and to change i for the next round, do something like
if some_condition then
diff = diff + 1 -- skip 1 forward
end
end
This way, you cannot forget incrementing i, and you still have the adjusted i available in your code. The deltas are also kept in a separate variable, so scanning this for bugs is relatively easy. (i autoincrements so must work, any assignment to i below the loop body's first line is an error, check whether you are/n't assigning diff, check branches, …)
This question already has answers here:
What does ||= (or-equals) mean in Ruby?
(23 answers)
Closed 8 years ago.
I've been recently allocated to a new Rails project in which I could see assignments to variables are made using ||= instead of =. Can any one help me understand if this is a correct way or a good practice in Rails and the advantages/disadvantages of using it?
e.g.
a ||= b + c
(b and c are integers)
Thanks for any help :)
With:
a = b + c
a gets set to the sum of b and c no matter what.
With:
a ||= b + c
it only gets set to the sum if it's currently set to nil or false.
It's a subtle difference but one that Ruby bods should learn. People coming from C-like languages often see a ||= x as:
a = a || x
but that's not actually the case. Instead, it's:
a || a = x
(no assignment is actually done if a is already set to a non-nil/false value).
Ruby Inside goes into some more depth on the matter here.
This question already has answers here:
Ruby: How to iterate over a range, but in set increments?
(4 answers)
Closed 8 years ago.
I would like to get a range of numbers but only by 5. Is there method for this? Perhaps something like: (0..100).by(5) (I feel like I've seen this done somewhere...)
I know I can do this: (0..100).select{|x| x if x % 5 == 0} Can you suggest alternatives?
Look at the method Numeric#step. I am sure it is what, you want.
0.step(25,5).to_a
# => [0, 5, 10, 15, 20, 25]
You want #step .
(0..100).step(5)....
This question already has answers here:
Search for an item in a Lua list
(12 answers)
Lua find a key from a value
(3 answers)
Closed 9 years ago.
I have this table:
maps = {4707191, 4747722, 1702169, 3994471, 4708958, 4008546, 4323335, 4516043, 4612295, 3469987, 4337892, 238378, 3088188, 329627, 3526384, 433483}
How can I make a script so if 1702169 (for example) is picked from the table, it prints ''That's the number''?
The easiest way to do what (i think) you want is with pairs() function. This is a stateless iterator which you can read more about here: http://www.lua.org/pil/7.3.html
If you simply want to scan through the entire table and see if it contains a value, then you can use this simple code:
local maps = {4707191, 4747722, 1702169, 3994471, 4708958, 4008546, 4323335, 4516043, 4612295, 3469987, 4337892, 238378, 3088188, 329627, 3526384, 433483}
local picked = 1702169
for i, v in pairs(maps) do
if v == picked then
print("That's the number")
break
end
end
The above code will iterate through the whole table where i is the key and v is the value of the table[key]=value pairs.
I am slightly unclear about your end goal, but you could create this into a function and/or modify it to your actual needs. Feel free to update your original post with more information and I can provide you with a more specific answer.