In Julia, I might want to write a function that returns 0 if the input is less than 1, or returns 2 if the input is greater than or equal to 1. This is a pretty simple function, and the verbosity of a five-line if else construct is probably excessive. So I'm trying to turn it into a one-line function. The best I can come up with is as follows:
f(x::Number) = begin (x < 1) && return(0); return(2); end
or
f(x::Number) = begin x < 1 ? (y=0) : (y=2); return(y); end
Are there any simpler ways to define this function?
julia> f(x::Number) = x < 1 ? 0 : 2
f (generic function with 1 method)
julia> f(0)
0
julia> f(1)
2
julia> f(0.99)
0
Alternative solution:
f(x::Number) = if (x < 1) 0 else 2 end
The if-elseif-else syntax in Julia will return the value of the expression that gets executed, which imho makes the C-like ternary operator rather superfluous. As in, all of its functionality is encompassed by a more readable alternative.
Looking at your previous attempts, I think it is worth mentioning that unlike in say Python, you rarely need to explicitly use return(). Often you can just return whatever your if-elseif-else blocks return, much like you would in most lisp dialects. Explicit return is like goto or break, something that you use to break control flow in exceptional cases.
Related
I hate that ranges include the end. Here is an example where I've deliberately removed the end of the range.
N = 100
for x in 0.0 : 2*pi/N : 2*pi*(N-1)/N
println(x)
end
Is there any way to avoid the ugliness of this for loop?
Yes, there is
N = 100
for x in range(0; step=2π/N, length=N)
println(x)
end
Maybe not the most elegant way... take the first n-1 elements
r = 0.0 : 2*pi/N : 2*pi
r = Iterators.take(r,length(r)-1)
Unfortunately, inclusive ranges (and 1-based indexing) is baked into the idioms of Julia at a fundamental level.
However, for this specific case, do note that stepping with floating point values can be problematic, as adding N values might be less than, equal to, or greater than the final value, giving different results for the for loop. Although julia tries really hard, there's no way to quite do the right thing in all circumstances. As a bonus, working in integer values only for the ranges simplifies things. You might want to consider:
for ix in 0:N-1
x = ix * 2 * pi / N
println(x)
end
Alternatively, the range() function has a form with a len parameter:
for x in range(0, 2*pi*(N-1)/N, length=n)
println(x)
end
Or indeed, combining this with the other answer of only taking (N-1) could work.
You could actually define your own operator such as:
▷(a,b) = a:b-1
Now you can write:
julia> 3▷6
3:5
Julia also natively supports custom indices for arrays. There is a package CustomUnitRanges that is maybe an overkill here.
I am currently trying some functionalities of Julia regarding symbolic expressions. Coming from Matlab I searched the documentation for symbolic something with little success until I found some info about the expr = :(<content>) notation.
I started with the declaration of my first function : fun1 = :(1-x) which works fine. However, I need to reuse my expression or manipulations of it afterwards.
After searching a bit, I still did not find a way to say e.g fun2 = -fun1. How does one manipulate expressions once they are declared?
EDIT My example statement being a bit restrictive, an additional case would be the construction of a array of expression using pre-declared expresions as in exprarray = [fun1 0 -2*fun2+3]
you can interpolate expressions with $:
julia> fun1 = :(1-x)
:(1 - x)
julia> fun2 = :(-$fun1)
:(-((1 - x)))
EDIT
The same works for the array :
julia> exprarray = :([$fun1 0 -2*$fun2+3])
:([1 - x 0 -2 * -((1 - x)) + 3])
I'm currently working on a side project that deals with a lot of recursive calls. I'm not a computer scientist, so I'm not exactly sure how to optimize my code. I know that recursive functions are not very efficient and I've heard that you can often replace it with tail calls, but I'm not exactly sure how to go about doing this. This function takes in three arrays: appendList, sequence, and used. The other arguments, base, length, index and last word are integers.
function Recursion(appendList, base, length, sequence, used, lastWord, index)
#Global variables:
global G_Seq_List
global G_Seq_Index
used = ones(UInt8, 1, base^length)
used[1] = 0
if index == base^length
check = zeros(UInt8, base^length, 1)
for i = 1 : base^length
index = 1
for j = 1 : length
k = mod(i+j-1,base^length)
index = index + base^(length - j)*sequence[k+1]
end
check[index] = check[index] + 1
if check[index] != 1
return
end
end
G_Seq_List[G_Seq_Index,:] = sequence[:]
G_Seq_Index = G_Seq_Index + 1
return
end
#Builds Sequence
for i = 1 : base^length
if appendList[i , mod(lastWord - 1, base^(length - 1)) + 1] == 1
if used[i] == 1
tempUsed = used
tempUsed[i] = 0
tempCounter = index + 1
tempSequence = sequence
tempSequence[tempCounter] = mod(i - 1, base)
Recursion(appendList, base, length, tempSequence, tempUsed, i, tempCounter)
end
end
end
end
Is it a quick fix to turn this recursion into a tail call? If not, what kind of things can I do to optimize this function?
In general, any recursion can be converted to a loop, and a loop will generally have better performance, since it has similar algorithmic performance without the need to allocate new frames and store extra information.
"Tail call optimization" is something the compilers (or runtimes) do, which is to automatically convert the recursion to a loop if the recursive call is a last call in the function (hence the name - "tail call"), typically by reusing the same call frame instead of allocating a new one. Reusing the frame is okay since if all you do with the result of the recursive call is return it, you don't need anything else from the enclosing function invocation, so there's no reason to keep the frame alive in the first place.
So, what you need to check is:
Whether your compiler supports tail-call optimization.
What you have to do in order to allow the compiler to do so - usually the straightforward return f(...) pattern will work, but sometimes the compiler can support more complex code.
Both depend on your specific compiler, so I would look up documentation about it - I could not tell what it is from your question.
Python, Java and Scala have ternary operators. What is the equivalent in Julia?
You may be referring to this.
a = true
b = 1
c = 2
julia>a ? b : c
1
a = false
julia>a ? b : c
2
For inline use, a ? b : c exists, as mentioned by the previous answer. However it is worth noting that if-else-end in Julia works just like (if cond expr1 expr2) in most Lisp dialects which acts both as the if-clause and as the ternary operator. As such, if-then-else returns the return value of the expression that gets executed.
Meaning that you can write things like
function abs(x)
if x > 0
x
else
-x
end
end
and this will return what you want. You do not have to use a return statement to break the function block, you just return the value returned by the if-block.
Inline, you can write
if (x > 0) x else -x end
which will return the same thing as the ternary operator expression (x > 0) ? x : -x , but has the benefit of avoiding perl-ish ?: symbols and is generally more readable, but less chainable.
Most languages have a ternary operator separate from if-then-else because if clauses are statements, while in lisp-like languages they are expressions just like everything else and have a return value.
Yes! Julia has a ternary operator. Here is a quick example from the Julia documentation:
The so-called "ternary operator", ?:, is closely related to the if-elseif-else syntax, but it is used where a conditional choice between single expression values is required, as opposed to conditional execution of longer blocks of code. It gets its name from being the only operator in most languages taking three operands:
a ? b : c
The expression a, before the ?, is a condition expression, and the ternary operation evaluates the expression b, before the :, if the condition a is true or the expression c, after the :, if it is false. Note that the spaces around ? and : are mandatory: an expression like a?b:c is not a valid ternary expression (but a newline is acceptable after both the ? and the :).
The easiest way to understand this behavior is to see an example. In the previous example, the println call is shared by all three branches: the only real choice is which literal string to print. This could be written more concisely using the ternary operator. For the sake of clarity, let's try a two-way version first:
julia> x = 1; y = 2;
julia> println(x < y ? "less than" : "not less than")
less than
julia> x = 1; y = 0;
julia> println(x < y ? "less than" : "not less than")
not less than
I have an application in which I need to define a piecewise function, IE, f(x) = g(x) for [x in some range], f(x)=h(x) for [x in some other range], ... etc.
Is there a nice way to do this in Julia? I'd rather not use if-else because it seems that I'd have to check every range for large values of x. The way that I was thinking was to construct an array of functions and an array of bounds/ranges, then when f(x) is called, do a binary search on the ranges to find the appropriate index and use the corresponding function (IE, h(x), g(x), etc.
It seems as though such a mathematically friendly language might have some functionality for this, but the documentation doesn't mention piecewise in this manner. Hopefully someone else has given this some thought, thanks!
with a Heaviside function you can do a interval function:
function heaviside(t)
0.5 * (sign(t) + 1)
end
and
function interval(t, a, b)
heaviside(t-a) - heaviside(t-b)
end
function piecewise(t)
sinc(t) .* interval(t,-3,3) + cos(t) .* interval(t, 4,7)
end
and I think it could also implement a subtype Interval, it would be much more elegant
I tried to implement a piecewise function for Julia, and this is the result:
function piecewise(x::Symbol,c::Expr,f::Expr)
n=length(f.args)
#assert n==length(c.args)
#assert c.head==:vect
#assert f.head==:vect
vf=Vector{Function}(n)
for i in 1:n
vf[i]=#eval $x->$(f.args[i])
end
return #eval ($x)->($(vf)[findfirst($c)])($x)
end
pf=piecewise(:x,:([x>0, x==0, x<0]),:([2*x,-1,-x]))
pf(1) # => 2
pf(-2) # => 2
pf(0) # => -1
Why not something like this?
function piecewise(x::Float64, breakpts::Vector{Float64}, f::Vector{Function})
#assert(issorted(breakpts))
#assert(length(breakpts) == length(f)+1)
b = searchsortedfirst(breakpts, x)
return f[b](x)
end
piecewise(X::Vector{Float64}, bpts, f) = [ piecewise(x,bpts,f) for x in X ]
Here you have a list of (sorted) breakpoints, and you can use the optimized searchsortedfirst to find the first breakpoint b greater than x. The edge case when no breakpoint is greater than x is also handled appropriately since length(breakpts)+1 is returned, so b is the correct index into the vector of functions f.