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

Returning A Custom Error Message

Started by campicus, 16 October 2013 - 09:08 PM
campicus #1
Posted 16 October 2013 - 11:08 PM
Hello geniuses!

Lets say I have a table:

args = {[1]="1",[2]="right",[3]="left",}

What I want to do is return an error message when [1] is not a number. I already get an error message if [1] is not a number:

attempt to perform arithmetic __div on nil and number

however I want the error to return a different error message (which looks a bit neater).

Is this possible?
LBPHacker #2
Posted 17 October 2013 - 12:32 AM
Yup, totally
error("something bad happened here")
Cutomize that string up there. If this is a common function of sorts, you can call error so the line number won't point to this function but to the one that called it:
error("wasn't me", 2)
theoriginalbit #3
Posted 17 October 2013 - 12:47 AM
As LBPHacker said it is possible. To expand on his second code example you can also provide a level of 0 to have it not print the filename or line number, only the message.

Here is a tutorial I wrote about errors, error handling and custom errors.

It should be noted that custom errors should not be a replacement for writing code correctly, in the example you've provided, this is a time you shouldn't do it, you should detect whether it's a number and then error if it's not, not wait for Lua to error and then format the message. An example would be

function someApiFunction(num)
  if type(num) ~= "number" then
    error("Expected number for arg #1, got "..type(num), 2) --# to understand what the 2 is for, read my tutorial
  end
end
campicus #4
Posted 17 October 2013 - 01:42 AM
Thanks guys. I tried to do what you suggest theoriginalbit:

if type(arg[1]) ~= "number" then
  error("Expected number for arg #1, got "..type(num), 2)
end

however, i think that arg[1] is always a string (as it is defined args = {…}). Then I tried doing this:


if type(tonumber(arg[1])) ~= "number" then
  error("Expected number for arg #1, got "..type(num), 2)
end

but that did not work either. Take a look at my code if you would like clarification.

http://pastebin.com/VgpzHi37
theoriginalbit #5
Posted 17 October 2013 - 02:13 AM
"unknown paste id"

you can however do

if not tonumber(arg[1]) then
  error("Expected number, got "..type(arg[1]), 2)
end

--# it was either a number, or could become a number, so lets make it a number permanently
arg[1] = tonumber(arg[1]) 
campicus #6
Posted 17 October 2013 - 09:59 AM
Fixed the link.

That solution does not work for me, it seems like anything can be changed into a number?
ElvishJerricco #7
Posted 17 October 2013 - 10:10 AM
Fixed the link.

That solution does not work for me, it seems like anything can be changed into a number?

Considering your paste was removed and we don't have enough of your code, it'll be hard to help you. But why store the numbers as strings when you want them as numbers? Do you also need them as strings elsewhere? If that's the case then what bit proposed wouldn't work, since it changes the string to a number permanently. You need to cast between string and number as you see fit. You can either store as one, and use tonumber(args[1]) or tostring(args[1]) when you need it as the other, or you can store it as either and use tonumber and tostring every time you need it so that you're certain you have the right data type.

Of course 99% of the time, if you want to turn a number into a string, Lua will handle that for you. "a" .. 3 is the same as "a3". It'd probably be wise to store the values as numbers because you won't have to worry about casting between data types unless you specifically need args[1] to be a string, without any other manipulation.
campicus #8
Posted 17 October 2013 - 10:28 AM
http://pastebin.com/VgpzHi37

Sorry for the confusion guys, hopefully this link works.

I use all strings except for tArgs[1], which needs to be numerical. I have commented out the code that does not function (in the pastebin link) and provided an explanation of what goes wrong.
The code as is works, it just doesn't throw the errors I want it to if the user inputs incorrect parameters.

As always, your help is appreciated

EDIT: I should mention I am using CCDesk to test my code, hopefully it isn't an issue with that :s
TheOddByte #9
Posted 17 October 2013 - 11:04 AM
Well.. Have you tested it in regular MC, It can still be some bugs in CCDesk and I just tested it and it seemed to work fine..( I tested it with CCEmu )
campicus #10
Posted 17 October 2013 - 06:57 PM
It hasn't been possible for me to test it on minecraft unfortunately :(/>

So if you entered something like:

pulser right left 1
it threw the correct error message ("Pulse interval must be numerical")?

The program itself works fine (the pulsing part). Where I run into issues is when the user enters something like "pulser left right", my custom error message wont pick up that "left" is not a number. These are the two parts of code that are not working (and are commented out in that pastebin link):


if not tonumber(tArgs[1]) then
    print("Pulse interval must be numerical.")
    error("Usage: <pulse interval> <side1> <side2>...", 0)
end
^That code should let me know when the first argument is not a number but it doesn't.


for i,v in ipairs(tArgs) do
    if i > 1 then
        if tArgs[i] ~= ("left" or "right" or "top" or "bottom" or "front" or "back") then
            error("Side must be top, bottom, left, right, back or front", 0) 
        end
    end
end
That code should let me know if tArgs[2] and above are not a valid side, this also does not work.

If you are saying that you ran my code in minecraft, with those bits of code being called (as currently they are not called, they are comments), and it worked, well then that is good, I shall test it in minecraft tonight/tomorrow.
theoriginalbit #11
Posted 18 October 2013 - 12:55 AM

if not tonumber(tArgs[1]) then
	print("Pulse interval must be numerical.")
	error("Usage: <pulse interval> <side1> <side2>...", 0)
end
That should work fine, if you want you can put newlines in error messages

if not tonumber(tArgs[1]) then
  error("Pulse interval must be numerical.\nUsage: <pulse interval> <side1> <side2> ...", 0)
end


for i,v in ipairs(tArgs) do
	if i > 1 then
		if tArgs[i] ~= ("left" or "right" or "top" or "bottom" or "front" or "back") then
			error("Side must be top, bottom, left, right, back or front", 0)
		end
	end
end
This would not work, and you immediately need to get yourself out of this habit. The section

("left" or "right" or "top" or "bottom" or "front" or "back")
does not work how you think it does, what it does it it resolves all the values, and in Lua a non-nil or non-false will resolve to true, so the statement would end up looking like so

if tArgs[i] ~= (true or true or true or true or true or true) then
now with Boolean OR logic we can see that all those true's resolve down to a single true

true OR true = true
true OR false = true
false OR true = true
false OR false = false
Once Lua has resolved them (since you places brackets around them, it will now compare against tArgs[1]. Resulting in the if statement

if tArgs[i] ~= true then
causing it to error as tArgs will not be true

There are two ways you can do what you wish to do…

#1

if tArgs[i] ~= "left" and tArgs[i] ~= "right" and tArgs[i] ~= "top" and tArgs[i] ~= "bottom" and tArgs[i] ~= "back" and tArgs[i] ~= "back" then
Note we use and here, since we want it to error if all of them don't match.
Boolean AND logic

true AND true = true
true AND false = false
false AND true = false
false AND false = false

#2
The other way, is we can setup a lookup table and check against it like so

local validSides = {
  left = true, --# note it can be any value here except false or nil, it doesn't need to be true
  right = true,
  top = true,
  bottom = true,
  front = true,
  back = true,
}

--# the later when validating
if not validSides[tArgs[i]] then
  error("Not a valid side", 0)
end
campicus #12
Posted 18 October 2013 - 06:25 AM
Everything seems to be working now :)/> Not only that, I know lots more about programming :D/>

If you're ever in Adelaide, Australia TheOriginalBIT, I owe you a beer.
theoriginalbit #13
Posted 18 October 2013 - 06:28 AM
That's good.

Haha. well I'm not that far away, I'm in Melbourne :P/>
campicus #14
Posted 19 October 2013 - 09:37 AM
#2
The other way, is we can setup a lookup table and check against it like so

local validSides = {
  left = true, --# note it can be any value here except false or nil, it doesn't need to be true
  right = true,
  top = true,
  bottom = true,
  front = true,
  back = true,
}

--# the later when validating
if not validSides[tArgs[i]] then
  error("Not a valid side", 0)
end

Apparently it does need to be true haha

You're an Aussie too!! :D/>
theoriginalbit #15
Posted 19 October 2013 - 09:48 AM
Apparently it does need to be true haha
Nope not at all, in Lua nil and false resolve to false, any other value resolves to true.

If you still don't believe me, here is an image for you. http://puu.sh/4TUFq.png