Why ^ for method return values?


#1

does anyone know why functions return the last statement in the enclosed block, but method return values must be denoted with ^? i’d like to know what the motivation was for this since it strikes me as one of the more perplexing design decisions in sclang.


#2

It’s a wierd one, and a big point of confusion… The only thing that comes to mind is method chaining on objects, which to me is one of the nicer festures of the language (and has some performance benefits, I think). You pragmatically don’t get that if you have to explicitly return “this” everywhere to enable chaining.

You can’t easily require explicit returns inside of free functions, because it would mean you couldn’t do a return from a method if you were inside e.g. a .do{} frame. This is a HUGE downside for the language, and would ruin the best lambda syntax in the biz.

The way I internalize this is something like: ^ is a method return operator, which explicitly pushes it’s target onto the stack outside the method. Free functions don’t return at all, they are simply a way to execute a chunk of code in your current scope. Whatever the last thing they push to the stack is, that’s what you’re left with, just like any other block of code you e.g. stuck on the right side of an assignment operator.


#3

nice. even if it doesn’t totally justify the inconsistency, that’s a good way of putting it.

yeah. a lot of imperative languages (C, Python, …) support early exits. a lot of more functional languages (Lisp) employ lambdas for control flow. having both in the same language paints you into an awkward spot — how do you specify what scope you’re exiting to?

there is block… i find it more elegant than ^ since it doesn’t require any additional parser rules nor is it localized to methods, but in practice i still never use it and generally prefer to structure my code in a more functional than imperative style.

idiomatic returning of this is a valid point, but i do wonder whether this idiom is important enough to warrant the strange divergence between the return syntax for methods vs functions.


#4

i’d also like to point out some fun (and useless) quirks of ^. it can be used in interactively executed code, but with strange caveats. it has to be inside a function, or the parser rejects it:

    ^3; // parser error
    { ^3 }.value; // ok

and sclang/scide don’t print anything if they hit ^. both of these seem like oversights.

also interesting to me is that ^ is strong enough that it can even break out of an .interpret call!

CaretTest {
    *foo {
        "^nil".interpret;
        "this doesn't post".postln;
    }
}