Short circuit evaluation causing an invalid assignment location error - julia

The docs for Julia indicate that a valid short-cut to writing out an if statement is the syntax
<cond> && <statement>
I've used this a lot for error messages, e.g. length(x) < N && error("x is too short"), and it works as expected. However, the following does not work:
x = 3
x < 4 && x = 5
I get an error of the form syntax: invalid assignment location. What is going on here?
What I'm trying to do is check if x is less than 4, and if it is, then set x to 5. Should I do the following?
if x < 4
x = 5
end
Is there a valid short-circuit method for this situation?

Your error is caused because the && operator has higher precedence than the assignment operator = so your line of code is executed as if you would write (x < 4 && x) = 5.
For a solution you have to add parantheses.
x < 4 && (x = 5)
See my code running in the browser

Related

Check multiple conditions on the same function output in Julia

Is there a way to check multiple Boolean conditions against a value (to achieve the same as below) without computing sum twice or saving the result to a variable?
if sum(x) == 1 || sum(x) > 3
# Do Something
end
You can use one of several options:
Anonymous function:
if (i->i>3||i==1)(sum(x))
# Do Something
end
Or,
if sum(x) |> i->i>3||i==1
# Do Something
end
DeMorgan's theorem:
if !(3 >= sum(x) != 1)
# Do Something
end
And if used inside a loop:
3 >= sum(x) != 1 && break
# Do Something
or as function return:
3 >= sum(x) != 1 && return false
But using a temporary variable would be the most readable of all:
s = sum(x)
if s > 3 || s == 1
# Do Something
end
Syntactically, a let is valid in that position, and the closest equivalent to AboAmmar's variant with a lambda:
if let s = sum(x)
s == 1 || s > 3
end
# do something
end
I'd consider this rather unidiomatic, though.

sum function in Julia is giving error if the array is empty

I am trying to create a code which identifies if the elements in an array are monotonic or not.
I wrote the below code and got the error -
function isMonotonic(array)
if length(array) <= 2
return true
end
check_up = []
check_down = []
for i in range(2, length(array))
if array[i] <= array[i-1]
append!(check_up, 1)
end
if array[i] >= array[i - 1]
append!(check_down, 1)
end
end
if sum(check_up) == length(array) - 1 || sum(check_down) == length(array) - 1
return true
else
return false
end
end
isMonotonic([1, 2, 3, 4, 5, 6 , 7])
I am getting the below error
Error: Methoderror: no method matching zero(::Type{Any})
I think it is because I am trying to sum up the empth array, I want to understand how to overcome this problem in general, I have a solution for the above code, but in genral I want to know the reason and how to use it. I do not want to first check if the array is empty or not and then do the sum.
If you wanted to save yourself lots of effort, the simplest solution would just be:
my_ismonotonic(x) = issorted(x) || issorted(x ; rev=true)
This will return true if x is sorted either forwards, or in reverse, and false otherwise.
We could maybe make it a little more efficient using a check so we only need a single call to issorted.
function my_ismonotonic(x)
length(x) <= 2 && return true
for n = 2:length(x)
if x[n] > x[1]
return issorted(x)
elseif x[n] < x[1]
return issorted(x ; rev=true)
end
end
return true
end
# Alternatively, a neater version using findfirst
function my_ismonotonic(x)
length(x) <= 2 && return true
ii = findfirst(a -> a != x[1], x)
isnothing(ii) && return true # All elements in x are equal
if x[ii] > x[1]
return issorted(x)
else
return issorted(x ; rev=true)
end
end
The loop detects the first occurrence of an element greater than or less than the first element and then calls the appropriate issorted as soon as this occurs. If all elements in the array are equal then the loop runs over the whole array and returns true.
There are a few problems of efficiency in your approach, but the reason you are getting an actual error message is because given the input, either this expression sum(check_up) or this expression sum(check_down) will effectively result in the following call:
sum(Any[])
There is no obvious return value for this since the array could have any type, so instead you get an error. If you had used the following earlier in your function:
check_up = Int[]
check_down = Int[]
then you shouldn't have the same problem, because:
julia> sum(Int[])
0
Note also that append! is usually for appending a vector to a vector. If you just want to add a single element to a vector use push!.

R best way to use quote and unquote macro variable

I have the following code to check if the dataset existed and if the dataset has data, and the problem is coming from the double quote around the macro variable.
check_data_ready <- defmacro(tracking_sheet,table_df,table_name,
expr={if (exists(table_df) && is.data.frame(get(table_df)) && dim(table_df)==NULL) {`tracking_sheet$DataReady[tracking_sheet$Table==table_name]<-'Ready'
} else {tracking_sheet$DataReady[tracking_sheet$Table==table_name]<-'Check!'}
})
check_data_ready(tracking_sheet,"df","Table")
the error msg is
Error in if (exists("df") && is.data.frame(get("df")) && dim("df") ==
So apparently dim("df") is not working, which should be dim(df). I try to substr the double quote from 2 to 3, but looks like it recognize d as 1 and f as 2, it doesn't count the double quote. I am lost here, how do I make the code working like this
if (exists("df") && is.data.frame(get("df")) && dim(df) ==

R function length error message

I made a function to to compute the sum of I(Xi
my.ecdf<- function(x,y) {
if(!is.null(dim(y)))
stop("y has more than one dimension")
n<-length(x)
i<-1:n
p<-if(x[i]<y) 1 else {
0
}
(sum(p))/n
}
But when I run it with input (rnorm(11),6), I get this error:
Warning message:
In if (x[i] < y) 1 else { :
the condition has length > 1 and only the first element will be used
Any ideas? I'm new to r so sorry if it's something obvious. (Also I don't want to use the for loop)
There are a number of issues in your code:
1) Whats the point of x[1:length(x)] in the if statement? Right now these are meaningless and can be dropped:
n<-length(x)
i<-1:n
x[i]
2) If statement accepts a logical argument not a vector of logical, you can consider adding all() any() etc like
if(all(x < y)) 1 else {0}
or use ifelse() statement for the assignment
3) Finally from what I can understand you overcomplicate things and the whole thing can be written as one-liner:
sum(x < y)/length(x)
This is a logical vector of the same length as y
is.null(dim(y))
You're using it as a logical test. An object with a length greater than 1 can't be unambiguously interpreted by the if statement. Consider if (TRUE FALSE FALSE TRUE) <do something>. When should you do that thing?
If you want to make sure y doesn't have more than one dimension, do
if(length(dim(y)) > 1){
stop("message")
}

Error message in Bubble sort code in R language

I did some programming work on R language to do the bubble sort. Sometimes it works perfectly without any error message, but sometimes, it shows "Error in if (x[i] > x[i + 1]) { : argument is of length zero". Can any one help me check whats wrong with it? I have attached my code below
example <- function(x) {
n <- length(x)
repeat {
hasChanged <- FALSE
n <- n - 1
for(i in 1:n) {
if ( x[i] > x[i+1] ) {
temp <- x[i]
x[i] <- x[i+1]
x[i+1] <- temp
hasChanged <- TRUE
cat("The current Vector is", x ,"\n")
}
}
if ( !hasChanged ) break;
}
}
x <-sample(1:10,5)
cat("The original Vector is", x ,"\n")
example(x)
The error occurs because you are iteratively decreasing n. Depending on the original vector's order (or lack thereof), n can reach the value of 1 after the last change. In that case, a further reduction of n in the next iteration step addresses the value x[0], which is undefined.
With a minimal correction your code will work properly, without giving error messages. Try to replace the line
if ( !hasChanged ) break;
with
if ( !hasChanged | n==1 ) break
Basically you have two termination criteria: Either nothing has been changed in the previous iteration or n is equal to one. In both cases, a further iteration won't change the vector since it is already ordered.
By the way, in R programming you don't need a semicolon at the end of a command. It is tolerated/ignored by the interpreter, but it clutters the code and is not considered good programming style.
Hope this helps.

Resources