I like that idea. I think the current behavior is not a huge problem, but I often run into a situation where I code up a method that modifies something and shouldn’t return anything, and then I forget to add a blank return statement at the end (*) and the function returns just something arbitrary, which can be confusing, especially in interactive sessions a la IJulia.
Cheers,
David
(*) ``return`` and ``return nothing`` and ``nothing`` on the last line are all equivalent, right?
I like that idea.
BUT, if this was to adopted, please do it soon :) These are the kind of breaking code changes that should get fewer and fewer as 1.0 moves closer.
I think that is a way too complicated rule, no one will know anymore what is happening.
From: julia...@googlegroups.com [mailto:julia...@googlegroups.com] On Behalf Of Jeffrey Sarnoff
Sent: Tuesday, May 24, 2016 12:58 PM
To: julia-users <julia...@googlegroups.com>
Subject: Re: [julia-users] Lack of an explicit return in Julia, heartache or happiness?
Rather than impose `return nothing` on all unshortly functions that do not provide an explicit return,
function fna{T}(x::T)::T
result = zero(T)
# this and that
result # fna(x) intends that `result` be returned
end
function fnb{T}(x::T)::T
# this and that
fna(x) # fnb(x) intends that the computed value `fna(x)` be returned
end
function fnc{T}(x::T)
result = zero(T)
# this and that
result += fna(x)
result # returns result
end
function fnd{T}(x::T)
result = zero(T)
# this and that
x * fna(x) # returns this
end
function fne{T}(x::T)
result = zero(T)
# this and that
result = x * fna(x)
show(result) # return nothing; (autoinserted before end)
end
As Jeff says, the current behavior is consistent in that a block like begin...end has a value equal to its last expression in any other context, so it would be odd if begin...end in a function body did not have the same behavior. I mostly like the style of explicit "return" statements in functions, but I think this should be more of a linting thing.
function f(args...)
# stuff
end
function f(args...)# stuffreturnend
function f(args...)# stuffg()end
With the change I proposed, we can statically tell the difference between an accidental return and an intentional one.
+1. While I like it, I’m not sure it is worth the cost. If there is a decision to go ahead with it, it would be good to do so rather sooner than later, just to make that breakage a little less worse…
From: julia...@googlegroups.com [mailto:julia...@googlegroups.com] On Behalf Of Steven G. Johnson
Sent: Tuesday, May 24, 2016 4:13 PM
To: julia-users <julia...@googlegroups.com>
if g() returns `nothing` then this code is fine; if g() returns a value, then we are accidentally returning it.
That way unless you put an explicit return in a long form function, it automatically returns nothing, avoiding accidentally returning the value of the last expression.
I don't think we should make ::Void a special case.
foo() = 5
>>foo() -> Int
Now you can just easily check what actually your function does.
foo(a) = "fits on one line"
bar{maybe_many_parameters}(lots_of_long_arguments) =
"too long for one line, but fits on two lines"
function baz(b)
func1(b) ?
func2(other_func(b)) :
func3(b)
end
function compute_val(dim)
if dim == 1
return "boink"
elseif dim == 2
return "bink"
elseif dim == 3
return "bank"
end
end
julia> compute_val(1)
ERROR: ArgumentError: typeassert: too few arguments (expected 2)
in compute_val(::Int64) at ./REPL[2]:1
in eval(::Module, ::Any) at ./boot.jl:225
in macro expansion at ./REPL.jl:92 [inlined]
in (::Base.REPL.##1#2{Base.REPL.REPLBackend})() at ./event.jl:46