I use Lua in computercraft to automate the mining. But, my turtle whose program worked very well before, stops if it meets a lava/flowing_lava/water/flowing_water source.
Inside my program, I have a lot of function to manage, for example, the fuel management, the tunnel, the collision with gravel, and .. the detection if the turtle meets a "block".
If the block is just an air block, the turtle continues to advance, elseif the block isn't an air block, the turtle digs this block and doesn't move forward if there is still a block in front of her.
The problem? The four sources which I quoted previously are considered as blocks, and the turtle can't move forward.
I try to fix this problem with multi-condition into the if, but it's doesn't work, the turtle moves forward and dig in any direction.
So I think it's because my way of creating the if isn't good, maybe the syntax (for concatenating many or into () ).
How to solve this issue?
function blockDetection(position, justDetection)
success, detectionBlock = nil
block_name = ""
if position == "right" then
turtle.turnRight()
success, detectionBlock = turtle.inspect()
turtle.turnLeft()
if success then
block_name = detectionBlock.name
if justDetection == true and detectionBlock.name == "minecraft:air" then
block_name = true
elseif justDetection == true and detectionBlock.name ~= "minecraft:air" then
block_name = false
else
end
end
end
end
I think your problem is that you forgot to return block_name. If you omit the return statement, you implicitly return 0 arguments, so trying to access any would give nil values. For example
if blockDetection (position,justDetetcion) then --[[something]] end, would never execute the then-end block, since nil is considered false.
You should also one more thing you should change in your code:
You shouldn't use x==true. If x is a boolean, then if x==true then ... is equivalent to if x then ....
So, your code should look a like this:
function blockDetection(position, justDetection)
success, detectionBlock = nil
block_name = ""
if position == "right" then
turtle.turnRight()
success, detectionBlock = turtle.inspect()
turtle.turnLeft()
if success then
block_name = detectionBlock.name
if justDetection and detectionBlock.name == "minecraft:air" then
block_name = true
elseif justDetection and detectionBlock.name ~= "minecraft:air" then
block_name = false
else
end
end
end
return block_name
end
Related
Why is the else statement is not allowed to have a then or other conditions?
Is it because it is the final condition within the else-if conditions it represents?
I am struggling to understand this concept since I'm a beginner who just learned about variables.
I'm asking this because I received an error with my else statement in the code:
message = 0
condition = 30
if condition <=10
message = “try harder”
elseif
condition <=20 then
message = "Almost learning"
else
condition = <=30 **—This is the line where I get the error message**
message = "Now you’re getting it"
end
print(message)
Would appreciate someone breaking down in laymen terms, why else is not allowed to have < or > or then or other conditions.
else condition = <= 30
(which is the way your code was originally formatted) would be a very unusual feature in a language.
The whole point of else on its own is to execute if none of the other conditions were true. So a condition on the else is absolutely useless.
The Programming in Lua book if statement shows the normal usage:
if op == "+" then
r = a + b
elseif op == "-" then
r = a - b
elseif op == "*" then
r = a*b
elseif op == "/" then
r = a/b
else
error("invalid operation")
end
However, your actual code (when formatted correctly) ends up looking like:
else
condition = <=30
which is correct in terms of the else but unfortunately makes the next line a statement. And this statement is very much incorrect syntax.
Now it may be that you meant to assign 30 to condition but, based on your other lines (that sort of match this as a condition), I suspect not. So it's probably best just to remove that line totally.
My current ruby commandline app uses STDIN.ready?. This permits me to capture complex keys such as Meta keys, Function keys, shifted-function keys etc.
I am not finding anything similar in Crystal.
While searching I found STDIN.raw &.read_char.
According to the docs, this should return a nil when there is nothing to read. However, I am not getting a nil. It seems to wait for the next key. The ruby code had a $stdin.getc.
My logic basically keeps reading STDIN as long as it is ready and accumulating key codes. The moment ready? returns false, the key is evaluated.
The logic NOW is:
c = STDIN.raw &.read_char
if c == '\e' # escape char
loop do
k = STDIN.raw &.read_char
if k
# accumulate k into a string
else
# evaluate string and return
end
end #loop
end
# rest of code if not escape.
Currently the else condition does not execute, so I am stuck in the if part. I don't know when to stop reading keys.
Previously, in ruby I had the second getc inside a if STDIN.ready?.
Earlier in ruby:
if c == '\e'
loop
if STDIN.ready?
k = STDIN.getc
accumulate in string
else
evaluation string and return code
end
end
end
EDIT: for me the correct answer lies in the link to 2048.cr suggested below in a comment.
This is not an answer, it is just a workaround if no correct answers here.
def handle_second_key(buffer)
loop do
input = STDIN.raw &.read_char
buffer << input if input
if buffer.size == 2
if buffer[0] == '\e' && buffer[1] == 'q'
puts "Right combination #{buffer[0].dump} + #{buffer[1].dump}"
exit
else
puts "Wrong combination: #{buffer[0].dump} + #{buffer[1].dump}"
break
end
end
end
end
buffer = [] of Char
loop do
input = STDIN.raw &.read_char
buffer << input if input
if buffer[0] == '\e'
handle_second_key(buffer)
buffer.clear
else
buffer.clear if buffer.size > 0
end
end
I have a 'wrapper function' that takes inputs and just runs a lot of functions in turn and spits out a result at the end. A simple example
function wrapper(a,b)
c = first_function(a,b)
d = second_function(c)
if typeof(d) == Int64
e = third_function(d)
f = fourth_function(e)
g = fifth_function(f)
try
h = sixth_function(g)
catch
i = "this has failed"
end
i = seventh_function(h)
else i = "this has failed"
end
return i
end
There are about 5 different places throughout the list of functions that I want to set up 'if - else' statements or 'try - catch' statements. The 'else' part and the 'catch' part are always evaluating the same things. In this example you can see what I mean by seeing that both the else and the catch statements execute i = "this has failed".
Is there a way that I can just define i = "this has failed" at the bottom of the function's code and just tell julia to skip to this line for the 'else' or 'catch' parts ? For example I'd like my above to be something like:
function wrapper(a,b)
c = first_function(a,b)
d = second_function(c)
if typeof(d) == Int64
e = third_function(d)
f = fourth_function(e)
g = fifth_function(f)
try
h = sixth_function(g)
catch
<skip to line 10>
end
i = seventh_function(h)
else <skip to line 10>
end
<line 10> i = "this has failed"
return i
end
You can use the #def macro from this SO post. For example:
#def i_fail_code begin
i = "this has failed"
end
and then you'd do:
function wrapper(a,b)
c = first_function(a,b)
d = second_function(c)
if typeof(d) == Int64
e = third_function(d)
f = fourth_function(e)
g = fifth_function(f)
try
h = sixth_function(g)
catch
#i_fail_code
end
i = seventh_function(h)
else #i_fail_code
end
return i
end
This macro is pretty cool because even though it's essentially just copy/pasting what's in its definition it will even get the line numbers for errors correct (i.e. it will send you to the correct line in the #def definition).
You got some great literal answers answering your literal question, but the real question is why do you need to do it like this in the first place? It sounds like a really bad design decision. Essentially you're reinventing the wheel, badly! You're trying to implement a "subroutine" approach as opposed to a "functional" approach; subroutines have all but disappeared decades ago, for good reason. The fact that your question essentially boils down to "GOTO for Julia" should be a really big red flag.
Why not just define another function that handles your "fail code" and just call it? You can even define the fail function inside your wrapper function; nested functions are perfectly acceptable in julia. e.g.
julia> function outer()
function inner()
print("Hello from inner\n");
end
print("Hello from outer\n");
inner();
end
outer (generic function with 1 method)
julia> outer()
Hello from outer
Hello from inner
So in your case you could simply define a nested handle_failure() function inside your wrapper function and call it whenever you feel like it and that's all there is to it.
PS: Preempting the typical "there are some legit uses for GOTO in modern code" comment: yes; this isn't one of them.
Julia has built in goto support via macros, which may be the simplest option. So something like:
function wrapper(a,b)
c = first_function(a,b)
d = second_function(c)
if typeof(d) == Int64
e = third_function(d)
f = fourth_function(e)
g = fifth_function(f)
try
h = sixth_function(g)
catch
#goto fail
end
i = seventh_function(h)
else
#goto fail
end
return i
#label fail
i = "this has failed"
return i
end
Also note that you almost never want to test the type of a variable in Julia - you should handle that by multiple dispatch instead.
The "single line if statement" exists in C# and VB.NET as in many other programming and script languages in the following format
lunchLocation = (dayOfTheWeek == "Tuesday") ? "Fuddruckers" : "Food Court";
does anyone know if there is even in VBScript and what's the extact syntax?
The conditional ternary operator doesn't exist out of the box, but it's pretty easy to create your own version in VBScript:
Function IIf(bClause, sTrue, sFalse)
If CBool(bClause) Then
IIf = sTrue
Else
IIf = sFalse
End If
End Function
You can then use this, as per your example:
lunchLocation = IIf(dayOfTheWeek = "Tuesday", "Fuddruckers", "Food Court")
The advantage of this over using a single line If/Then/Else is that it can be directly concatenated with other strings. Using If/Then/Else on a single line must be the only statement on that line.
There is no error checking on this, and the function expects a well formed expression that can be evaluated to a boolean passed in as the clause. For a more complicated and comprehensive answer see below. Hopefully this simple response neatly demonstrates the logic behind the answer though.
It's also worth noting that unlike a real ternary operator, both the sTrue and sFalse parameters will be evaluated regardless of the value of bClause. This is fine if you use it with strings as in the question, but be very careful if you pass in functions as the second and third parameters!
VBScript does not have any ternary operator.
A close solution in a single line and without using a user defined function, pure VBScript:
If dayOfTheWeek = "Tuesday" Then lunchLocation = "Fuddruckers" Else lunchLocation = "Food Court"
BTW, you can use JScript in Classic ASP if ternary opertor is so important to you.
edited 2017/01/28 to adapt to some of the non boolean condition arguments
Note: If all you need is to select an string based on an boolean value, please, use the code in the Polinominal's answer. It is simpler and faster than the code in this answer.
For a simple but more "flexible" solution, this code (the original code in this answer) should handle the usual basic scenarios
Function IIf( Expression, TruePart, FalsePart)
Dim bExpression
bExpression = False
On Error Resume Next
bExpression = CBool( Expression )
On Error Goto 0
If bExpression Then
If IsObject(TruePart) Then
Set IIf = TruePart
Else
IIf = TruePart
End If
Else
If IsObject(FalsePart) Then
Set IIf = FalsePart
Else
IIf = FalsePart
End If
End If
End Function
If uses the Cbool function to try to convert the passed Expression argument to a boolean, and accepts any type of value in the TrueValue and FalseValue arguments. For general usage this is fast, safe and fully complies to documented VBScript behaviour.
The only "problem" with this code is that the behaviour of the CBool is not fully "intuitive" for some data types, at least for those of us that constantly change between vbscript and javascript. While numeric values are coherent (a 0 is a False and any other numeric value is a True), non numeric types generate a runtime error (in previous code handled as false), except if it is a string with numeric content or that can be interpreted as true or false value in english or in the OS locale.
If you need it, a VBScript version "equivalent" to the ? javascript ternary operator is
Function IIf( Expression, TruePart, FalsePart )
Dim vType, bExpression
vType = VarType( Expression )
Select Case vType
Case vbBoolean : bExpression = Expression
Case vbString : bExpression = Len( Expression ) > 0
Case vbEmpty, vbNull, vbError : bExpression = False
Case vbObject : bExpression = Not (Expression Is Nothing)
Case vbDate, vbDataObject : bExpression = True
Case Else
If vType > 8192 Then
bExpression = True
Else
bExpression = False
On Error Resume Next
bExpression = CBool( Expression )
On Error Goto 0
End If
End Select
If bExpression Then
If IsObject( TruePart ) Then
Set IIf = TruePart
Else
IIf = TruePart
End If
Else
If IsObject( FalsePart ) Then
Set IIf = FalsePart
Else
IIf = FalsePart
End If
End If
End Function
BUT independently of the version used, be careful, you are calling a function, not using a ternary operator. Any code, or function call you put in TruePart of FalsePart WILL BE EXECUTED independently of the value of the condition. So this code
value = IIf( 2 > 3 , DoSomething(), DontDoSomething() )
WILL EXECUTE the two functions. Only the correct value will be returned to value var.
There's a weird trick possible (hi, Python!) for exact one-liner:
lunchLocation = array("Food Court", "Fuddruckers")(-(dayOfTheWeek = "Tuesday"))
The "magic" works because of a boolean operation specifics in VBScript.
True is actually -1 and False is 0, therefore we can use it as an index for array (just get rid of a minus). Then the first item of array will be a value for False condition and second item for True.
related to #MC_ND answer:
to execute only one function, you can do something like that:
If VarType(TruePart) = vbString and InStr(1,TruePart,"function:") = 1 then
IIf = GetRef(Mid(TruePart,10))()
Else
IIf = TruePart
End If
the same for the FalsePart, and call IIf() it like that:
value = IIf( 2 > 3 , "function:DoSomething", "function:DontDoSomething" )
and will call DoSomething() or DontDoSomething()
So my variable is clearly defined in inputnfo(), why am I getting an undefined error? The try & except perhaps? I've added removed... swapped it all around and cannot seem to find the solution, and answers online seem very situation based... Thanks in advance :)
Super New & improved edit: now getting UnboundLocalError
import random
alpha = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
strgen = []
retry = 0
### Defining
def inputnfo():
global much
much = input('how long do you want your random word/lucky number to be: ')
global which
which = raw_input('would you like letters or numbers?(let,num, or mix?):').lower
def generate():
while much > 0:
if which == 'let':
strgen.append(random.choice(alpha))
much -= 1
print '.'
elif which == 'num':
strgen.append(random.randint(1,9))
much -= 1
print '.'
elif which == 'mix':
mixer = random.choice([0,1])
if mixer == 0:
strgen.append(random.choice(alpha))
much -= 1
print '.'
elif mixer == 1:
strgen.append(random.randint(1,9))
much -= 1
print '.'
def finish():
finito = ''.join(strgen)
print 'Generation Completed!\n'
if which == 'let':
print 'Your randomly generated string is:' + finito
elif which == 'num':
print 'Your randomly generated number is:' + finito
elif which == 'mix':
print 'Your randomly generated Alpha-Numerical string is:' + finito
### Running
inputnfo()
while much != 0:
generate()
finish()
Its because the variable "much" in the function inputnfo() is local to that function alone. that is why you are getting an undefined error in the while loop. there is two solution
1. Make the variable "much" global by including the line
def inputnfo():
global much
try:
and then removing the argument of generate function
Or
2. Let the function inputnfo() return much and use this return value in the while loop and generate function
do the same for variable "which"
and put a line which = "" befor
which = ""
def inputnfo():
global much