This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Hydrotronics's profile picture

performing a sum that's stored in a string

Started by Hydrotronics, 12 June 2016 - 12:29 PM
Hydrotronics #1
Posted 12 June 2016 - 02:29 PM
So, I'm trying to create a calculator which allows you to say the sum in chat and then it works it out for you and replies in chat

I have the detect and reply system working, using Computronics. I dont have the middle bit where it calculates the sum. Is there a way of doing this?

So far my code looks something like this:


-- The code to break down the message to just the sum is up here
-- sum is the variable name given to the string
if string.find(sum, "+") then
  symbolLoc = string.find(sum, "+")
  symbol = +
elseif string.find(sum, "-" then
 symbrolLoc = string.find(sum, "-")
  symbol = -
end
if string.find(sum, "?") then
questionLoc = string.find(sum, "?")
else
sum = sum.."?"
questionLoc = string.find(sum, "?")
no1 = tonumber(string.sub(sum, 1, symbolLoc - 2))
no2 = tonumber(string.sub(sum, symbolLoc + 2, questionLoc))
answer = math.floor(no1 symbol no2)

The error it's giving is "Trying to add nil and nil" or something along those lines.
I have confirmed it is receiving the message properly, so that's not the problem
TheRockettek #2
Posted 12 June 2016 - 02:38 PM
Try puting the + and - as strings
KingofGamesYami #3
Posted 12 June 2016 - 04:19 PM
print( loadstring( "1 + 1" ) )

On mobile, sorry for lack of explanation.
Emma #4
Posted 12 June 2016 - 05:06 PM
Towards KingofGamesYami
print( loadstring( "1 + 1" ) )

On mobile, sorry for lack of explanation.

For one, it would have to be this:
print( loadstring( "return 1 + 1")() )
This is because loadstring returns a lua chunk, which has to then be called as if it was a function.

Anyways in this case, loadstring is not necessary. Loadstring should only be used in cases where it is absolutely necessary and there is no other way to accomplish your task.
In the code the OP is asking, it looks like they only want addition and subtraction, in which case we can just use if blocks.

First of all, when you are detecting the symbol, you cannot simply say this:

symbol = +
This is because the '+' (or the '-') token is an operator, and you cannot set a variable to an operator, only to constants or other variables.
What you can do is something like this:

symbol = "+"
This sets the variable symbol to the string "+", allowing you to perform equality checks later on in the logic.

At the bottom where you calculate the answer, you cannot just have the different variables together without some sort of stitch.
There are two ways to do this, use loadstring as KingofGamesYami suggested, which is not the most efficient solution, but it works.
It is not very efficient because using loadstring triggers the Lua interpreter on the supplied string, which is not fast.
The better solution is to use an if/elseif block like so:

if symbol == "+" then
	answer = math.floor(no1 + no2)
elseif symbol == "-" then
	answer = math.floor(no1 - no2)
end
You can then extend this for other operators such as the multiplicative token '*', or the divisor token '/', or even applying powers with '^'.

NOTE: The reason you got the error "Trying to add nil and nil" is because of the "symbol = +" line, it expected operands on either side of the '+' and the '-', since you supplied none, it assumed both were nil, and you cannot add nil to anything.
Edited on 18 June 2016 - 01:47 AM
Hydrotronics #5
Posted 16 June 2016 - 05:45 PM
I'll look into Inc's answer later, but what does loadstring do? I tried it but it didn't work :/ Also, I want it to be more than just addition and subtraction, those were just examples :P/>
I was gonna add factorial, roots, powers, multiplication and division, but your way would work either way, but it's long and takes time to type so I was kinda hoping for a shorter method
Edited on 16 June 2016 - 03:48 PM
valithor #6
Posted 16 June 2016 - 05:50 PM
I'll look into Inc's answer later, but what does loadstring do? I tried it but it didn't work :/

The loadstring example should have actually been something like this.

print(loadstring("return 1+1")())

You can think of the string that is being passed to loadstring as being converted to a function. In the example right there it is essentially saying:

(function()
  return 1+1
end)()
Emma #7
Posted 18 June 2016 - 03:47 AM
I'll look into Inc's answer later, but what does loadstring do? I tried it but it didn't work
–snip–

Yeah, sorry, the fix for the loadstring was in the "towards kingofgamesyami" spoiler, should have put it outside as well (and thanks for catching my mistake val), but as valithor said, the correct way to use loadstring is as follows:

print(loadstring("return 1+1")())
This is because loadstring basically wraps the code you input as a function and gives you that function as its return argument, for example:

local myFunc = loadstring("return 1+1")
-- This becomes
local myFunc = function()
     return 1+1
end
Then, you have to call it to actually get the answer.
Hydrotronics #8
Posted 16 July 2016 - 08:04 AM
Ah! Thank you!! I'll have a shot at it! Thank you for help! :)/>

Edit: Ok, so I'm getting an error that is trying to do math on a number and a nil?

This is my code:
message you say to trigger this piece of code: "What is 1+1"

--Somewhere up here I'm converting the message to caps
if string.find(message,"WHAT IS") then
if tonumber(string.find(message, 8, 9)) then
  sleep(1)
  chat.say("Beginning Calculations")
  if string.find(message, "?") then
	chat.say("Please don't add a question mark to the sum")
	os.reboot()
  end
  local sumRaw = string.sub(message,7)
  local calculate = loadstring("return "..sumRaw)
  chat.say(sumRaw.." = "..calculate)
end
end

Second Edit: Oops! I put string.find instead of string.sub! My bad :P/> Thx Bomb Bloke for pointing this out
Edited on 21 July 2016 - 03:30 PM
Bomb Bloke #9
Posted 16 July 2016 - 10:13 AM
Can't see how that code could give that error. It's got other issues.

string.find(message, 8, 9)

Here you're passing the number 8 where you should be passing in a string to look for. Lua will translate that automatically, but your string doesn't contain the character "8", so find will still return nil.

I think you meant string.sub(message, 9, 11), but "1+1" won't tonumber(), and even if it did - what if the user enters more than two digits, or adds additional spaces, etc?

local sumRaw = string.sub(message,7)

Assuming this line were reached, sumRaw would end up as "S 1+1". You presumably meant 9.

chat.say(sumRaw.." = "..calculate)

loadstring assigned calculate a function pointer. Here you meant to call that function, using "calculate()".

Really you should be checking that "calculate" is a function before you attempt to call it (what if loadstring() failed to make any sense of the expression?), and pcall'ing it if it compiled (in case it fails to execute). Even then you should really be applying patterns to make sure the expression is purely mathematical - while loadstring() probably is the simplest way to do this, what you don't want is people asking "what is fs.delete("startup") os.reboot()".
The Crazy Phoenix #10
Posted 17 July 2016 - 04:06 PM
The correct way of doing this would be to declare a function for each operator.

local operations = {
    ["+"] = function(a, b) return a + b end,
    ["-"] = function(a, b) return a - b end
    --# Etc
}
Then you can call them using operations[op](a, b), where op is the string of the operation, such as "-".
Edited on 17 July 2016 - 02:07 PM
Hydrotronics #11
Posted 21 July 2016 - 05:34 PM
-snip-

I think you meant string.sub(message, 9, 11), but "1+1" won't tonumber(), and even if it did - what if the user enters more than two digits, or adds additional spaces, etc?

local sumRaw = string.sub(message,7)
-snip

just to clarify, what I'm attempting to do there is just check the first digit of the first number is infact a number, which isn't a bullet proof method of checking but I honestly couldn't be bothered to improve upon it. I just wanted a program that could answer maths question for you XD
Lupus590 #12
Posted 21 July 2016 - 06:00 PM
-snip-

I think you meant string.sub(message, 9, 11), but "1+1" won't tonumber(), and even if it did - what if the user enters more than two digits, or adds additional spaces, etc?

local sumRaw = string.sub(message,7)
-snip

just to clarify, what I'm attempting to do there is just check the first digit of the first number is infact a number, which isn't a bullet proof method of checking but I honestly couldn't be bothered to improve upon it. I just wanted a program that could answer maths question for you XD

once you have separated it you could use tonumber(string) if the string/char didn't have a number than it returns nil
Edited on 21 July 2016 - 04:01 PM