I have a string which delimited by \n, and I'm using for to do something with that. But I don't want the for loop to the end of the string, just want the for loop to any times like this code below but it doesn't work.
for w=1,10 in webdata:gmatch("(.-)\n") do
--something
end
There are two different for loops in Lua. You are mixing them together.
Numerical for:
for i=1,10 do -- or e.g. i=10,1,-1
-- do something
end
Generic for:
for k,v in pairs(t) do -- or ipairs, or completely custom functions
-- do something
end
For more information please refer to:
PIL - 4.3.4 – Numeric for
PIL - 4.3.5 – Generic for
Lua Reference Manual - 3.3.5 – For Statement
Your problem
To achieve your goal you could wrap gmatch with another iterator or... just go with the most straight-forward and simple solution: count the lines you have processed:
local n = 1
for l in webdata:gmatch("(.-)\n") do
-- do something
n = n + 1
if n > 10 then
break
end
end
It's not the most elegant one, but it works.
Related
I'm looking to iterate over some similarly named variables. a_1,a_2,a_3=1,2,3
So that instead of using:
if a_1>0 then a_1-=1 end
if a_2>0 then a_2-=1 end
if a_3>0 then a_3-=1 end
I can do something like:
for i=1,3 do
if a_'i'>1 then a_'i'-=1 end --syntax is wrong here
end
Not sure how to go about doing this, as stated there is no access to _G library in pico8. var-=1 is just var=var-1. Given there are functions like tostr() and tonum() was wondering if there was a tovar() kind of trick to this. Basically need a way to convert the i value to a letter in my variable name and concat it to the variable name...in the conditional statement. Or some alternative method if there is one.
In Lua, when in doubt, use a table.
In this case you could put the 3 variable on a table at the start, and unpack them at the end:
local a={a_1,a_2,a_3}
for i=1,3 do
if(a[i]>1) a[i]-=1
end
a_1,a_2,a_3=unpack(a)
Not sure which Lua version does pico 8 use but for LuaJIT, you could try using loadstring and there is load for Lua5.2+ (I know, not the best solution):
for i = 1, 3 do
local x
loadstring("x = a_" .. tostring(i))()
if x > 1 then
x = x - 1
loadstring("a_" .. tostring(i) .. " = x")()
end
end
While trying to completely understand the solution to Lua - generate sequence of numbers, the section 4.3.4 of Programming in Lua is unclear:
for i=1,f(x) do print(i) end
for i=10,1,-1 do print(i) end
The for loop has some subtleties that you should learn in order to
make good use of it. First, all three expressions are evaluated once,
before the loop starts. For instance, in the first example, f(x) is
called only once. Second, the control variable is a local variable
automatically declared by the for statement and is visible only inside
the loop. [...]
The first line of code doesn't work of course.
What is f(x) and where is it defined?
Unfortunately the documentation isn't available as a single page, making it a huge effort to search for the first occurrence. Searching for "lua f(x)" doesn't bear fruit either.
Explanation: now that I have received answers, I realize the problem was a misunderstanding. I incorrectly interpreted "f(x) is called only once" as "the line containing f(x) - for i=1,f(x) do print(i) end - will only return one value" and didn't pay enough attention to "all three expressions are evaluated once, before the loop starts".
This sentence clarifies it: expressions are evaluated once, before the loop starts.
Thus, f(x) is called only once is merely stating that the expressions will not be affected by potential changes in the loop.
For example, the following code (expressions are i=1 and x in the second line):
x=5
for i=1,x do
x = x - 1
print(i, x)
end
print(x)
will produce the following output:
1 4
2 3
3 2
4 1
5 0
0
and will not produce the following output:
1 4
2 3
3 2
2
f(x) is just a function which takes the argument x and returns a value that is used as the upper bound for the loop.
So for example, if the function f(x) calculates x² and you call it as f(3), it would return the value of 9. The resulting for loop would look like this:
for i=1, f(3) do print(i) end
which is exactly the same as
for i=1, 9 do print(i) end
How do I generate a sequence of integer numbers based on first and last number for for to loop over?
The following pseudocode
for i in sequence(4,9) do
print(i)
end
should produce the following output
4
5
6
7
8
9
Please include a short explanation what the solution does in the background and what terminology would have allowed one to find the solution.
Search attempts lead to unsearchable huge pages of documentation.
You can use numeric for loop to do that. You will find details in Programming in Lua section I referenced or the Lua manual section on For statement.
Just for the full record, there are basically 3 ways you could do this loop, one with a slightly different syntax, and 2 with the exact syntax as your pseudocode. Links point to relevant chapters in Programming in Lua (which is a great book to read, by the way).
1) Using a simple numeric for loop - in this case you won't use sequence:
for i=4,9 do
print(i)
end
2) Implement sequence as a closure:
function sequence(from,to)
local i = from - 1
return function()
if i < to then
i = i + 1
return i
end
end
end
for i in sequence(4,9) do print(i) end
3) Implement sequence as a coroutine:
function sequence(from, to)
return coroutine.wrap(function()
for i=from,to do
coroutine.yield(i)
end
end)
end
for i in sequence(4,9) do print(i) end
Is it possible to perform arithmetic on multiple values in Lua.
I am using Lua for windows 5.1.4.
Currently I have to put the multiple values into a table and then unpack them, and I would like to be able to skip that step.
Is it possible.
Here is what I currently have:
function numsToStr(...)
local nums = {}
for i,v in ipairs({...}) do
nums[i] = v + string.byte('A') - 1
end
return string.char(unpack(nums))
end
What I want is to be able to do this
function numsToStr(...)
return string.char(...+string.byte('A')-1)
end
No, it is not possible to do arithmetic on multiple values in Lua.
It's not possible to do "directly", but you can implement "map" function, similar to what you've done. Some relevant resources: Short anonymous functions, thread on Perl-like map/grep functions, and map and other functions. Also take a look at list comprehensions in Penlight.
I would like to evaluate a math string in my corona app. Right now I'm focusing on the trig functions, so let's let the example be the most difficult we're likely to face:
local expr = "2sin(4pi+2)+7"
My goal is for this to somehow be (either) evaluated as is with maybe a pi --> math.pi switch, or to even break it up. The breaking up would be much more difficult, however, since it COULD be as complicated a above, but could also just be sin(1).
So I would prefer to stay as close to the python eval(expr) function as possible, but if that can't happen, I am flexible.
The simplest way would be to replace sin with math.sin (pi with math.pi and so on), add missing multiplications signs, and run it through loadstring, but loadstring is not available in Corona environment.
This means you will need to write your own parser for these expressions. I found a discussion on Corona forums that may help you as a starting point: here, with some details and a demo here
This should do the trick, it is able to use the lua math functions without putting 'math.function' so just sqrt(100) works fine. I threw this together because I have seen this question asked way too many times. Hopes this helps :)
If you have any questions feel free to contact me at rayaman99#gmail.com
function evaluate(cmd,v) -- this uses recursion to solve math equations
--[[ We break it into pieces and solve tiny pieces at a time then put them back together
Example of whats going on
Lets say we have "5+5+5+5+5"
First we get this:
5+5+5+5 + 5
5+5+5 + 5
5+5 + 5
5 + 5
Take all the single 5's and do their opperation which is addition in this case and get 25 as our answer
if you want to visually see this with a custom expression, uncomment the code below that says '--print(l,o,r)'
]]
v=v or 0
local count=0
local function helper(o,v,r)-- a local helper function to speed things up and keep the code smaller
if type(v)=="string" then
if v:find("%D") then
v=tonumber(math[v]) or tonumber(_G[v]) -- This section allows global variables and variables from math to be used feel free to add your own enviroments
end
end
if type(r)=="string" then
if r:find("%D") then
r=tonumber(math[r]) or tonumber(_G[r]) -- A mirror from above but this affects the other side of the equation
-- Think about it as '5+a' and 'a+5' This mirror allows me to tackle both sides of the expression
end
end
local r=tonumber(r) or 0
if o=="+" then -- where we handle different math opperators
return r+v
elseif o=="-" then
return r-v
elseif o=="/" then
return r/v
elseif o=="*" then
return r*v
elseif o=="^" then
return r^v
end
end
for i,v in pairs(math) do
cmd=cmd:gsub(i.."(%b())",function(a)
a=a:sub(2,-2)
if a:sub(1,1)=="-" then
a="0"..a
end
return v(evaluate(a))
end)
end
cmd=cmd:gsub("%b()",function(a)
return evaluate(a:sub(2,-2))
end)
for l,o,r in cmd:gmatch("(.*)([%+%^%-%*/])(.*)") do -- iteration this breaks the expression into managable parts, when adding pieces into
--print(":",l,o,r) -- uncomment this to see how it does its thing
count=count+1 -- keep track for certain conditions
if l:find("[%+%^%-%*/]") then -- if I find that the lefthand side of the expression contains lets keep breaking it apart
v=helper(o,r,evaluate(l,v))-- evaluate again and do the helper function
else
if count==1 then
v=helper(o,r,l) -- Case where an expression contains one mathematical opperator
end
end
end
if count==0 then return (tonumber(cmd) or tonumber(math[cmd]) or tonumber(_G[cmd])) end
-- you can add your own enviroments as well... I use math and _G
return v
end
a=5
print(evaluate("2+2+2*2")) -- This still has work when it comes to pemdas; however, the use parentheses can order things!
print(evaluate("2+2+(2*2)"))-- <-- As seen here
print(evaluate("sqrt(100)"))
print(evaluate("sqrt(100)+abs(-100)"))
print(evaluate("sqrt(100+44)"))
print(evaluate("sqrt(100+44)/2"))
print(evaluate("5^2"))
print(evaluate("a")) -- that we stored above
print(evaluate("pi")) -- math.pi
print(evaluate("pi*2")) -- math.pi