Lack of an explicit return in Julia, heartache or happiness?

1,492 views
Skip to first unread message

David Parks

unread,
May 24, 2016, 12:48:19 PM5/24/16
to julia-users
The last line of a function is its implicit return value in Julia.

Can someone tell me why this is a great idea?

I'm realizing a serious downside to it in reading someone else's code. It's not immediately clear to me if a use of a particular function is using the last statement as a return value or not. 

The lack of an explicit return is making the code ambiguous to read, and therefore I'm searching for uses of it to understand the original intent.

Even if the original coder is being perfectly hygienic in their style, I can't make an assumption as such. I've always though explicit over implicit reigned king in code maintainability. Can someone convince me otherwise?



Isaiah Norton

unread,
May 24, 2016, 1:18:00 PM5/24/16
to julia...@googlegroups.com
This is common in more functionally-oriented languages, and facilitates a similar style in Julia. I would probably ban it in an organization-level linting standard, but I do use it myself ;)

Jeff Bezanson

unread,
May 24, 2016, 1:19:40 PM5/24/16
to julia...@googlegroups.com
We did it this way because it's useful in general for the value of a
block to be the value of its last expression (as in lisp `progn` and
scheme `begin`). For example, a macro might want to return some
statements that need to execute before finally computing its value.
The "implicit return" behavior falls out of this. We could maybe add a
check that says "you must write an explicit return", but I find this
to be kind of an arbitrary restriction. It also doesn't fit so well
with other features of the syntax. For example is

f(x) = 2

allowed, or do you have to write

f(x) = return 2

?

True, some constructs have non-obvious return values. For example in

function set1(a)
a[:] = 1
end

some might assume it returns `1`, and others might prefer it to return
`a`. If we gave a "must write a return" error, many would just
reflexively add

function set1(a)
return a[:] = 1
end

which doesn't clarify anything. It seems like a documentation problem
to me. If the meaning of a function's return value isn't clear,
requiring people to add redundant keywords doesn't seem like a real
fix to me.


On Tue, May 24, 2016 at 12:48 PM, David Parks <davidp...@gmail.com> wrote:

Stefan Karpinski

unread,
May 24, 2016, 1:28:33 PM5/24/16
to Julia Users
The modification I've occasionally considered would be:
  • short-form functions implicitly return their expression value;
  • long-form functions implicitly return `nothing` unless an explicit value is returned.
This could be implemented by automatically inserting a `return nothing` at the end of every long-form function body. I agree that it doesn't help cases where an expression like `a[:] = 1` evaluates to something unexpected. What it does mitigate is accidentally returning some value that you didn't really mean to return. That's not a huge issue since people are free to call the function and ignore the return value, but there is a hazard of people relying on accidental return values which could then change in the future since they were unintentional in the first place.

David Anthoff

unread,
May 24, 2016, 1:34:56 PM5/24/16
to julia...@googlegroups.com

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?

Eric Forgy

unread,
May 24, 2016, 1:48:26 PM5/24/16
to julia-users
On Wednesday, May 25, 2016 at 1:34:56 AM UTC+8, David Anthoff wrote:

I like that idea.


Me too +1. Not a big deal though, 

David Anthoff

unread,
May 24, 2016, 2:36:07 PM5/24/16
to julia...@googlegroups.com

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.

Tom Breloff

unread,
May 24, 2016, 2:41:45 PM5/24/16
to julia-users
-1 I would be sad if my code was suddenly peppered with "return" unnecessarily (IMO) all over the place.  I'm sure David was looking at my code when he was inspired to post this but I would be:   http://giphy.com/gifs/sad-depressed-disappointed-33iqmp5ATXT5m

I'm ok with social pressure to change... just don't force it on me please.

Tamas Papp

unread,
May 24, 2016, 2:49:26 PM5/24/16
to julia...@googlegroups.com
I wonder if a mandatory return would play well with macros. The neat
thing about the Lisp-style syntax is that it is nestable, an expression
does not need to care about where it is and whether a return statement
makes sense in that context.

Jeffrey Sarnoff

unread,
May 24, 2016, 3:57:46 PM5/24/16
to julia-users
Rather than impose `return nothing` on all unshortly functions that do not provide an explicit return, 
perhaps limit postpending `return nothing` to functions that 
    neither provide an explicit return anywhere within the function body 
    nor have as the final line of the function (before end) either 
      (a) a single variable/value or
      (b) a tuple of variables/values or 
      (c) a conditional/branching that selects either (a) or (b) or throws an exception. 

David Anthoff

unread,
May 24, 2016, 4:03:56 PM5/24/16
to julia...@googlegroups.com

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, 

Steven G. Johnson

unread,
May 24, 2016, 5:08:50 PM5/24/16
to julia-users
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.

Jeffrey Sarnoff

unread,
May 24, 2016, 5:31:52 PM5/24/16
to julia-users
David, if it reads 'complicated' that is my hiccup.  The intent was to uncomplicate by letting current and future functions do what one would expect.
The general notion, not entirely captured above, is

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


Stefan Karpinski

unread,
May 24, 2016, 6:30:19 PM5/24/16
to Julia Users
On Tue, May 24, 2016 at 5:08 PM, Steven G. Johnson <steve...@gmail.com> wrote:
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.

What I proposed doesn't change anything about what any expression evaluates to. The only thing it changes is that

function f(args...)
    # stuff
end

would implicitly mean

function f(args...)
    # stuff
    return
end

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.
In order to adjust for this change one would at most need to add a single return at the end of long-form functions which are *intended* to return a value. Short-form functions would not have to change and long-form functions with explicit returns would not have to change.

The problem with making this "a linting thing" is that we don't statically know which expressions return nothing. When you see code like this:

function f(args...)
    # stuff
    g()
end

should it be a lint warning or not? It depends on what g() returns: if g() returns `nothing` then this code is fine; if g() returns a value, then we are accidentally returning it. Whether the code passes linting depends on the unknowable behavior of g(). Even if we did dynamic instrumentation, there's a chance that g() could return `nothing` as a meaningful value (see match). With the change I proposed, we can statically tell the difference between an accidental return and an intentional one.

Jeffrey Sarnoff

unread,
May 24, 2016, 7:04:49 PM5/24/16
to julia-users
Just modify Compat.jl so it offers compatibility with future versions of Julia ...

using Compat

@compat function g()::Int
    # stuff
end
function fg(args...) g() end # returns an Int, so it must return something

@compat function h()::Void
  # stuff
end
function fh(args...) h() end # returns Void, so it must return nothing

Steven G. Johnson

unread,
May 24, 2016, 7:12:30 PM5/24/16
to julia-users


On Tuesday, May 24, 2016 at 6:30:19 PM UTC-4, Stefan Karpinski wrote:
With the change I proposed, we can statically tell the difference between an accidental return and an intentional one.

Nice, now I see.  The biggest problem is that it seems like it would be a hugely breaking change.

David Anthoff

unread,
May 24, 2016, 10:12:56 PM5/24/16
to julia...@googlegroups.com

+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>

Tom Breloff

unread,
May 24, 2016, 11:00:49 PM5/24/16
to julia-users
if g() returns `nothing` then this code is fine; if g() returns a value, then we are accidentally returning it.


This is the frustrating part for me.   I very frequently have methods which "do something and then pass control to another method".  So by putting g() at the end of f, I'm purposefully (not accidentally) saying that I want to return whatever g() returns.  Adding "return" before that doesn't change the function, or the intention.  If someone doesn't care or want what is returned, then they don't use it.  I still don't see any benefit of a change, but I do see a real annoyance.

Is there an actual performance hit if there's a value returned but not used?  I assume that the compiler sees that the return value is unused and discards it as if nothing was returned.  Am I wrong with that assumption?

Eric Forgy

unread,
May 24, 2016, 11:49:33 PM5/24/16
to julia-users
On Wednesday, May 25, 2016 at 6:30:19 AM UTC+8, Stefan Karpinski wrote:
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.

This makes sense to me. The current behavior is not horrible, but I have been confused a few times by my functions returning stuff unexpectedly. I admit, that is mostly me being sloppy and I usually fix it by adding a `return`. I also like the clarity that `return val` provides. It would be breaking in a big way (even for my private stuff), but might be worth it. So far I do not do a lot of work with macros, but I am curious about Tamas' concern earlier.

David Parks

unread,
May 25, 2016, 12:16:07 AM5/25/16
to julia-users
I like Stefan's long-form / short-form solution myself. 
The trivial issue at hand was whether adding a simple print statement at the end of a long-form function was going to break one of the dozens of uses of it.
That should be trivial, but it wasn't.
The bigger the project, the bigger this problem. It's an issue of scalability to me.

Chris Rackauckas

unread,
May 25, 2016, 12:24:41 AM5/25/16
to julia-users
I like Stefan's idea. In fact, this is how I've already been using Julia, precisely for scalability. I think that not having an explicit return value in a long function is just unreadable, so for long-form functions I always add return statements at the bottom. At the same time, there's no reason for return statements in f(x,y)=2x*y. Enforcing this convention will likely have positive benefits for users in the future.

Didier Verna

unread,
May 25, 2016, 3:36:56 AM5/25/16
to Stefan Karpinski, Julia Users
Stefan Karpinski wrote:

> The modification I've occasionally considered would be:
>
> * short-form functions implicitly return their expression value;
> * long-form functions implicitly return `nothing` unless an explicit value is
> returned.

What's returned by a function (in a functional context where
everything is an expression) is a matter of language semantics. If you
go down that road, you're introducing semantic discrepancies out of
syntactic context. Consider that you would no longer be able to talk
about the concept of "function" itself, separate from the way a
function object was constructed (in other words, you increase the
porosity of the syntax/semantic membrane). I think this is a bad idea.

It's traditional in impure functional languages to return the value of
the last expression from compound statements; the former ones only
making sense by side-effecting. Lisp has some constructs to allow you
to return the value of previous sub-expressions instead, and we
idiomatically use (values) to explicitly indicate intent to return
nothing.

I can see why some people may be bitten by accidentally returned
values and would like to get 'nothing' by default, but in a
multi-paradigm language like this one, especially when functional is
prominent, it's not the language that needs to be fixed. It's the
people ;-). They're simply not programming in a functional style
enough and they should learn to do so. It's a long-term gain anyway.

--
Resistance is futile. You will be jazzimilated.

Lisp, Jazz, Aïkido: http://www.didierverna.info

Didier Verna

unread,
May 25, 2016, 3:41:08 AM5/25/16
to David Anthoff, julia...@googlegroups.com
David Anthoff <ant...@berkeley.edu> wrote:

> 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,

See it the other way around: in a functional style, there's almost
always a meaningful value to return. You can simply discard it if
you're not interested, but if one day you need it, it will already be
here.


> which can be confusing, especially in interactive sessions a la
> IJulia.

Then, you're not actually bothered by the fact that a function returns
a value, but by the fact that an interactive session will print it
(the P in REPL). This is different.

Didier Verna

unread,
May 25, 2016, 3:43:27 AM5/25/16
to Jeffrey Sarnoff, julia-users
Jeffrey Sarnoff <jeffrey...@gmail.com> wrote:

> David, if it reads 'complicated' that is my hiccup. The intent was to
> uncomplicate by letting current and future functions do what one would
> expect.

Which "one"? DWIM is evil... ;-)

Milan Bouchet-Valat

unread,
May 25, 2016, 5:16:34 AM5/25/16
to julia...@googlegroups.com
Le mardi 24 mai 2016 à 23:00 -0400, Tom Breloff a écrit :
> > if g() returns `nothing` then this code is fine; if g() returns a
> > value, then we are accidentally returning it.
>
> This is the frustrating part for me.   I very frequently have methods
> which "do something and then pass control to another method".  So by
> putting g() at the end of f, I'm purposefully (not accidentally)
> saying that I want to return whatever g() returns.  Adding "return"
> before that doesn't change the function, or the intention.  If
> someone doesn't care or want what is returned, then they don't use
> it.  I still don't see any benefit of a change, but I do see a real
> annoyance.
The problem isn't so much functions returning values that are not
useful, but functions which inadvertently return  a value just because
it's what the last expression happens to evaluate to. Then callers may
start relying on it, and the day you refactor the function a bit it
returns something different and their code breaks.

To avoid this, you need to add explicit "return nothing" or "nothing"
at the end of functions, which is annoying (and can easily be forgotten
when you never experienced the problem).


Regards

> Is there an actual performance hit if there's a value returned but
> not used?  I assume that the compiler sees that the return value is
> unused and discards it as if nothing was returned.  Am I wrong with
> that assumption?
>
> On Tue, May 24, 2016 at 6:29 PM, Stefan Karpinski <stefan@karpinski.o
> rg> wrote:
> > On Tue, May 24, 2016 at 5:08 PM, Steven G. Johnson <stevenj.mit@gma

Michael Borregaard

unread,
May 25, 2016, 9:23:22 AM5/25/16
to julia-users
To me, the suggested change seems to conflict intuitively with julia syntax. When using Julia at the REPL all expressions return a value, which is confusing at first when coming from othe languages but quickly becomes a feature. That a function also returns the value of the last statement seems consistent with this.
Also, a common use of multiple dispatch is to have methods that modify arguments then call another method of the same name defining the basic functionality. Eg.

function foo(x::SomeType)
...
end

function foo(x::SomeOtherType)
  y = dostufftogetsometype(x)
  foo(y)
end

where this syntax seems intuitive.

Tobias Knopp

unread,
May 25, 2016, 3:09:07 PM5/25/16
to julia-users
I like Stefans idea. Would be great to open an issue for that on github.

Tobi

Jeff Bezanson

unread,
May 25, 2016, 5:50:50 PM5/25/16
to julia...@googlegroups.com
If we want to change this, I also like the simplicity of Stefan's
proposal. However, on the whole I agree with Didier and prefer keeping
things as they are. Automatically adding `return nothing` can be seen
as making `nothing` the "default return value", which implies that
returning nothing is a good thing. I also don't feel it answers the
"explicit is better than implicit" objection that started this thread,
since the value being returned would not be evident in the code.

Tobias Knopp

unread,
May 25, 2016, 6:17:29 PM5/25/16
to julia-users
No return statement is kind of an explicit indication that the function does not return anything. This is at least how we know it from a lot of other languages. Thus at least for me as a previous C++ programmer it seemed pretty natural.

Stefan Karpinski

unread,
May 25, 2016, 6:41:43 PM5/25/16
to Julia Users
An argument for `nothing` being a good default return value is that it's very unlikely to accidentally work. Here's a scenario that illustrates the problem. Suppose you call a function that's supposed to return an integer – maybe the write function, which has many methods and returns the number of bytes written to the I/O stream. But someone implementing a write method (maybe a custom one) forgot to end the method definition with an expression giving the number of bytes written – this is easy to do since the primary purpose of `write` is to output data, not compute how much data is output. However, the function is written so that the last expression happens to evaluate to an integer – but not the number of bytes output. This is also pretty easy to do – IIRC, we had a bug in Base where exactly this happened. The caller gets no hint that there's a problem, they just get a subtle and hard-to-find bug. If, on the other hand, the function just returned `nothing` because there's no explicit return, then they would immediately get an error when they tried to use the return value where an integer is expected. In short, `nothing` is a good default return value precisely *because* it is useless.

Jeffrey Sarnoff

unread,
May 25, 2016, 7:26:33 PM5/25/16
to julia-users
That is a good point, well explained.  

If by default nonshort Julia functions evaluate as nothing, then the default evaluand is nothing -- and so does nothing wrong.
"So Julia's got that goin' for her, which is nice." -- Carl Spackler (Bill Murray in Caddyshack), paraphrased

Miguel Bazdresch

unread,
May 25, 2016, 7:35:27 PM5/25/16
to julia...@googlegroups.com
I think this is similar to the distinction between 'function' and 'procedure' in languages like Pascal. Maybe we could leave functions as they are (which I'd prefer), and add procedures that are like functions but with an implicit 'return nothing' at the end.

-- mb

Qian Long

unread,
May 25, 2016, 8:16:46 PM5/25/16
to julia-users
Why not just let "function foo(...)::Void" return nothing as default and others just keep as they are.

Jeff Bezanson

unread,
May 26, 2016, 1:12:01 AM5/26/16
to julia...@googlegroups.com

I don't think we should make ::Void a special case.

Didier Verna

unread,
May 26, 2016, 2:08:00 AM5/26/16
to 'Tobias Knopp' via julia-users
"'Tobias Knopp' via julia-users" <julia...@googlegroups.com> wrote:

> No return statement is kind of an explicit indication that the
> function does not return anything.

No it's not. It may be when you come from the procedural camp; it is
definitely not when you come from the functional camp. That's the
problem with multi-paradigm languages, especially those with a
heterogeneous user base. Nothing will ever be universally "intuitive"
or "natural".

Ford Ox

unread,
May 26, 2016, 3:05:59 AM5/26/16
to julia-users
It looks like the problem pple has is the fact that they are not sure what their function returns and forget to return nothing.
If print(methodname) prints automatically it's return type, you can easily avoid this confusion.

foo() = 5
>>foo() -> Int

Now you can just easily check what actually your function does.

Tobias Knopp

unread,
May 26, 2016, 6:02:33 AM5/26/16
to julia-users
We are currently talking about the long function form which are inherently non-functional since they involve a function body which is evaluated step by step. This is against the nature of a purely functional language. Thus, I cannot see how its intuitive from a functional side that the last statement within a function body evaluates to a return. A functional language has no statements that are successively executed.

Scott Jones

unread,
May 26, 2016, 8:02:47 AM5/26/16
to julia-users
So, another type could be added, say `Nothing` (currently deprecated) that converts everything to nothing without error.  That would not be a special case then, right?
There are a lot of other decisions in Julia that were made for pragmatic reasons - I think indicating that `nothing` should always be returned via the new
return type assertion syntax would be easy for people to understand and can be used with both the short form and function form.

Scott Jones

unread,
May 26, 2016, 8:10:05 AM5/26/16
to julia-users
Hmm, I use the long function form whenever the function is over 2 (at most 92 char) lines, so I disagree strongly that just because it uses the function form, it is inherently "non-functional".
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

Rafael Fourquet

unread,
May 26, 2016, 8:28:39 AM5/26/16
to julia...@googlegroups.com
I would be sorry to see this so elegant functional aspect of Julia
return to the void. It fits well with the
expression-rather-than-statement feel of Julia.
Regarding the annoyance of having to explicitly "return nothing" for
"procedures" (functions which are called only for side-effects): I
would find annoying to having to return explicitly something in
"functional functions", and I like the explicit "return nothing" to
indicate a procedure.
I don't agree that long form functions are inherently non-functional.
First, as Jeff mentioned, the lisp languages (considered functional)
have such features (e.g. "begin" in scheme), to return implicitly the
last expression in a block a mixed imperative/functional code.
This is true also in Haskell in do blocks (which implement side-effect
computations):

greet :: Int -> IO String
greet intensity = do
name <- getLine
return $ "Hello " ++ name ++ (take intensity $ repeat '!')

haskell> greet 3
Julia
"Hello Julia!!!"

It should be noted that the return here may be misleading: it's a
standard function which computes a value, which is then *implicitly*
returned to the caller of greet because it's the last expression of
the do block.

Second, a whole bunch a functions are "pure" (non-mutating) and can be
seen as implicit let forms:

function f(x)
y = 2*x
z = x^2
x + y - z
end

which corresponds e.g. in Haskell to

f x = let
y = 2*x
z = x*x
in x+y-z

I don't like to argue too much, but the status-quo camp is
under-represented in this thread!

I genuinely don't understand how annotating the function as ::Void or
::Nothing is preferable to "return nothing". And why not a new keyword
"procedure" then?

Rafael Fourquet

unread,
May 26, 2016, 8:34:15 AM5/26/16
to julia...@googlegroups.com
And indeed, as Scott points, a function can switch from using the
short form to the long form only because the number of characters
grows a bit, which is uncorelated to the functionalness. Having the
short form and long form disagree on the "default" returned value
would increase the risk to introduce a bug each time a conversion to
long form is made.

Didier Verna

unread,
May 26, 2016, 12:35:30 PM5/26/16
to 'Tobias Knopp' via julia-users
"'Tobias Knopp' via julia-users" <julia...@googlegroups.com> wrote:

> We are currently talking about the long function form which are
> inherently non-functional since they involve a function body which is
> evaluated step by step.

Nope. In that particular case, size is what matters ;-). You may
switch to the long form because you have a lot of code to type,
regardless of the (purely) functional style, or lack thereof.

Now consider this (a very frequent idiom, at least in my book[1]),
even independently from any consideration of purity:

function long (args...)
let this = that, here = there, etc = and_so_on
# lots of code here
# and also here
# oh, I almost forgot, here as well
# and BTW, all of this may be pure...
end
end

Do you find it unintuitive that a function with only one statement like
this one returns this statement's value? Do you also find it
unintuitive that let returns the value of its last expression, just
because it is long? Because if so, then we'd better make let return
nothing by default...

Or maybe we want even more special cases, like, the long function form
would return nothing by default, except if there is a single block of
code in it, in which case it would return this block's value. But then
again, a toplevel let has no point in returning anything, so maybe let
should return nothing by default, but only at the toplevel? :-D

I'm only half-joking here. Point is, again, DWIM is evil because
everyone is looking at this with a different I (I'm actually quite proud
of that one :-D). Consistency throughout a language is much better and
safer, even if that requires some level of paradigm shift for some
users.


> This is against the nature of a purely functional language. Thus, I
> cannot see how its intuitive from a functional side that the last
> statement within a function body evaluates to a return. A functional
> language has no statements that are successively executed.

You cannot see it because you're mixing "functional" and "purely
functional" all over the place. Congratulations, you've just
discovered one of my secret levels! :-) I believe I have a blog about
this somewhere, but I cannot put my hands on it.

Even unintentionally using "functional" to mean "purely functional"
has always led (and will continue to lead) only to more confusion, and
this is a serious problem. I've witnessed far too many sterile
discussions between different communities because of this.

Functional should only mean 1st class functions, as per Christopher
Stratchey's definition. Purely functional, then, adds the absence of
side effets. End of story. This confusion comes from the fact
(probably) that while you can very well be functional without being
pure, there's little sense in being pure yet not functional. But
nevertheless, this is harmful.

In this discussion, I never talked about purity I think. And I
continue to claim that from a (non pure) functional perspective,
returning the last expression of a block/function as the
block/function's value makes perfect sense, for two reasons:
1. everything has a value (expressions as opposed to instructions,
functions as opposed to procedures),
2. return is an instruction, not an expression. In functional style,
values are /stated/, not /returned/.


Footnotes:
[1] to the point that Lisp has a special construct (&aux) to spare you
let form.

Bart Janssens

unread,
May 26, 2016, 2:43:00 PM5/26/16
to julia-users
In C++ I had quite a few nasty bugs where it turned out that I forgot the return statement, and the function then just returns garbage (if declared as non-void, so I think this can't happen in Julia since you don't declare the return type). At least what is returned in Julia is now clearly defined. I don't think the possible benefits (for some) of returning nothing by default warrant a breaking change like this. On the other hand, I am in favor of putting an explicit return statement in long-form functions as a style guide.

Kristoffer Carlsson

unread,
May 26, 2016, 2:52:53 PM5/26/16
to julia-users
Not completely related but I have had the following happen a few times:

function compute_val(dim)
   
if dim == 1
       
return "boink"
    elseif dim
== 2
       
return "bink"
    elseif dim
== 3
       
return "bank"
   
end
end


The last "elseif" should have been an "else" and now the function is type unstable with Union{ASCIIString,Void} but I will not notice any problems because I only call the function with dim = 1,2,3.

Scott Jones

unread,
May 27, 2016, 9:39:58 AM5/27/16
to julia-users
That could be handled by add `::String`, as a return type assertion, right? (also helping readability / maintainability of the code, IMO)

Scott Jones

unread,
May 27, 2016, 9:55:51 AM5/27/16
to julia-users
Unfortunately, even though the return type assertion syntax is accepted, it is broken:

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


Jeff Bezanson

unread,
May 27, 2016, 10:58:39 AM5/27/16
to julia...@googlegroups.com
The feature hasn't been merged yet.

Scott Jones

unread,
May 27, 2016, 11:14:20 AM5/27/16
to julia-users
OK, since the syntax is now being accepted, I thought it must have been merged already.  (will it be merged soon?)

Thanks!

Reply all
Reply to author
Forward
0 new messages