Technically, one does not actually ever need to use the function
or end
keywords in julia. For instance, here’s random chunk of julia code I had laying around which uses a wide range of language constructs:
function f(p=0,q=1) # define the function
if rand() < 0.5 # flip a coin.
if p < (q - 1) # if the coin gives heads, check if p < (q - 1)
while gcd(p+=1, q) != 1 # increment p while the greatest common divisor or p+1 and q is not equal to 1
end
return f(p, q) # recursively call f(p, q) (where p has been incremented)
else
return f(1, q+1) # if p is not greater than q - 1, we recursively call f(1, q+1)
end
else
return p//q # If the coin flip gives tails, we return the Rational number p//q
end
end
let
data = [f() for _ in 1:10_000_000]
for frac in [(0//1), (1//2), (1//3), (2//3), (1//4), (3//4), (1//5), (2//5), (3//5), (4//5), (1//6), (5//6)]
freq = count(x -> x == frac, data)/length(data)
println("P($(frac)) ≈ $freq")
end
end
Now here is me rewriting it without using function
or end
and I’ll let you be the judge of whether this is preferable:
eval(Expr(:macro, Expr(:call, :while, :cond, :body), :(nothing; esc(Expr(:while, cond, body)))))
eval(Expr(:macro, Expr(:call, :while, :cond ), :(nothing; esc(Expr(:while, cond, nothing)))))
eval(Expr(:macro, Expr(:call, :for, :iter, :body), :(nothing; esc(Expr(:for, iter, body)))))
eval(Expr(:macro, Expr(:call, :let, :body), :(nothing; esc(Expr(:let, Expr(:block), body)))))
f(p=0,q=1) =
(rand() < 0.5 ? # flip a coin.
(p < (q - 1) ? # if the coin gives heads, check if p < (q - 1)
(@while(gcd(p+=1, q) != 1); # increment p while the greatest common divisor or p+1 and q is not equal to 1
f(p, q)) # recursively call f(p, q) (where p has been incremented)
: f(1, q+1)) # if p is not greater than q - 1, we recursively call f(1, q+1)
: p//q) # If the coin flip gives tails, we return the Rational number p//q
@let((data = (_ -> f()).(1:10_000_000);
@for(frac = [(0//1), (1//2), (1//3), (2//3), (1//4), (3//4), (1//5), (2//5), (3//5), (4//5), (1//6), (5//6)],
(freq = count(x -> x == frac, data)/length(data);
println("P($(frac)) ≈ $freq")))))
The eval
expressions at the beginning were for creating the macros @while
, @for
and @let
which allowed me to create while
, for
and let
blocks without using the end
keyword.
If you don’t like the keywords while
, for
and let
, you could call them @w
, @f
, and @l
.
It should go without saying that writing this sort of code is not a good idea if you want to share it with or get help from anyone who doesn’t share your sensibilities, but I just wanted to demonstrate that this is actually not too hard to do in julia.