Alias Return to ProcedureReturn in procedures

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
yuki
Enthusiast
Enthusiast
Posts: 101
Joined: Sat Mar 31, 2018 9:09 pm

Alias Return to ProcedureReturn in procedures

Post by yuki »

This may be very contentious, so please feel free to disagree! (or voice your agreement :D)

Proposal

When used in the context of a procedure, have keyword Return act as ProcedureReturn rather than being simply an error.

This would make the two pieces of code below equivalent to each other:

Code: Select all

Procedure Add(x, y)
  Return x + y
EndProcedure

Code: Select all

Procedure Add(x, y)
  ProcedureReturn x + y
EndProcedure
The original ProcedureReturn keyword would continue to function as it does currently.

Should this change be introduced, I'd hope Return eventually becomes the popular style over ProcedureReturn, so more code favours conciseness as time goes on. Again, the existing style would continue to function.


Motivation

There are few reasons I believe this would be a good addition:
  1. Familiarity.
    • The majority of programming languages have a simple, short "return" keyword. I don't mean to say "all the other cool kids are doing it, so PB should too!" but I feel there's definitely merit in making the language more approachable when coming from or used together with other languages.
    • See an example of Return and ProcedureReturn being conflated in a recent issue report here on the forums. I don't believe this is an isolated incident (and can say for sure I've made this mistake on occasion, especially when going back and forth late-night between PB and JS/C). This prompted a compiler change to now warn when Return is used inside procedures.
  2. Ergonomics.
    • Please hear me out on this. It seems silly, but gotta go fast.
    • Having "ProcedureReturn" typed out requires at least 9 key presses in the typical PB IDE:
      1. 4 letters "proc" to have autocomplete narrowed to:
        • Procedure
        • ProcedureC
        • ProcedureCDLL
        • ProcedureDLL
        • ProcedureReturn
      2. 4 down-arrow key presses to reach "ProcedureReturn" in the autocomplete list
      3. 1 tab key press to accept the autocomplete suggestion
    • Having "Return" typed out takes at least 4 key presses and at most 6 in the typical PB IDE:
      1. 3 letters "ret" to have autocomplete show only "Return"
      2. 1 tab key press to accept the autocomplete suggestion
    • Cutting typing (and reading) of this operation in half feels slicker, even through it's a relatively minimal part of each procedure. For small procedures, it has them feel much less verbose.
    • Side note: the input time inefficiency can alternatively be improved by just hiding "Procedure(C)(DLL)" options when showing autocomplete within a procedure, since they can't be nested.
  3. Consistency.
    • Break may be used for control flow in loops without naming the loop type (i.e., no need for ForBreak / BreakFor, WhileBreak / BreakWhile, etc.).
    • Continue follows the same rule as Break above.
    • Procedures are syntax sugar for subroutines, and both may Return to a caller. Similarly, a For loop is syntax sugar for While value <= limit : do_inner_stuff : value + step : Wend, and both may Continue / Break.

Downsides
  1. Semantics and usage of Return will vary slightly depending on the context, notably with subroutines not being able to carry a value through it. (Although, subroutines are already lower-level to the point they've no return value syntax, hence we generally use procedures to ease our lives)
  2. Inconsistency. Multiple ways of doing the same basic operation. Risk of style wars.
    • Are you team Return or ProcedureReturn? Or maybe... you use both in your codebase?
    • This will always exist to some extent in programming, as few languages totally dictate convention. Some examples:
      • Casing: Pascal vs. camel vs. snake vs. etc.
      • Variable declarations, these all have the same general effect (and identical ASM generated):
        • Define.s name = "Zippy Retton"
        • Define name.s = "Zippy Retton"
        • Define name$ = "Zippy Retton"
        • name.s = "Zippy Retton"
      • Implicit/explicit for..next:
        • ForEach users() : Next
        • ForEach users() : Next users()
      • Explicit gadget ID-ing vs. #PB_Any.
(Yes... I listed both consistency and inconsistency as upsides and downsides respectively 8))


Risks

There should be no risks aside from downsides listed above.

Return is already unsupported in procedures at present, so existing code should not break. ProcedureReturn would be retained into the distant future (forever?) for backwards-compatibility (but eventually be hidden from autocomplete so as to favour simplification).

If, in the distant future, ProcedureReturn were to ever be removed, it would be an extremely simple find-replace refactor. Removal of ProcedureReturn at any future point would however break all current procedure-oriented code involving return values (which is to say: loads). I understand if this is reason enough to reject the proposal, as having both ProcedureReturn and Return equivalent eternally may be an undesirable commitment.

The issue of redundant keywords is a very valid criticism. That said, this proposal is made with the hope that benefits are seen to outweigh the cost, where eventually the majority of PB procedure returns follow the simple form (and so legacy details become unimportant in all but niche cases).


Thanks

Thank you for reading/considering this!

I appreciate any feedback, be it negative or positive, so long as it's vaguely civil.

I understand that this is quite the ask, so no feelings of mine will be hurt if it's rejected.
BarryG
Addict
Addict
Posts: 4135
Joined: Thu Apr 18, 2019 8:17 am

Re: Alias Return to ProcedureReturn in procedures

Post by BarryG »

This was first requested in 2013 and not done -> viewtopic.php?t=52724
mestnyi
Addict
Addict
Posts: 1098
Joined: Mon Nov 25, 2013 6:41 am

Re: Alias Return to ProcedureReturn in procedures

Post by mestnyi »

+1
juergenkulow
Enthusiast
Enthusiast
Posts: 581
Joined: Wed Sep 25, 2019 10:18 am

Re: Alias Return to ProcedureReturn in procedures

Post by juergenkulow »

Code: Select all

// Procedure Add(x, y)
static integer f_add(integer v_x,integer v_y) {
integer r=0;
// Return  
goto *SYS_PopGosub();
// EndProcedure
r=0;
end:
return r;
}
documentation Gosub : Return
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Alias Return to ProcedureReturn in procedures

Post by Demivec »

For brevity when using autocomplete for ProcedureReturn you can type the six characters pro{tab}r{tab}.

As to the other points made I say 'When in Rome, do as the Romans do. '

PureBasic is more verbose. There is no correlation between the functions of Return and ProcedureReturn. Return has historical use and meaning in BASIC. ProcedureReturn was created and defined for its distinct use in PureBasic.

You can see a similar blend or some would say inconsistency in the defining of arrays, lists and maps by using the keywords Dim, NewList and NewMap.

In this way PureBasic shows ties to its historical roots while also adding more functionality and features. Anyone who has done many home improvements will ask themselves at some point if it is better to continue to make small adjustments over and over or to instead tear everything down and start again with a new building.

I wouldn't mind some adjustments for consistency while maintaining the possibility of using older syntax or keywords for historical reasons. This particular instance and issue is not one of them.
User avatar
yuki
Enthusiast
Enthusiast
Posts: 101
Joined: Sat Mar 31, 2018 9:09 pm

Re: Alias Return to ProcedureReturn in procedures

Post by yuki »

BarryG wrote: Tue Sep 12, 2023 10:13 pm This was first requested in 2013 and not done -> viewtopic.php?t=52724
Can't believe I missed that – I even searched for existing posts first :oops:
User avatar
yuki
Enthusiast
Enthusiast
Posts: 101
Joined: Sat Mar 31, 2018 9:09 pm

Re: Alias Return to ProcedureReturn in procedures

Post by yuki »

Demivec wrote: Wed Sep 13, 2023 10:13 am For brevity when using autocomplete for ProcedureReturn you can type the six characters pro{tab}r{tab}.
I stand corrected – that's good! (although, even being equal in key-press count to my favourite fuzzy "procr{tab}", the extra tab is a bit less comfy)

Demivec wrote: Wed Sep 13, 2023 10:13 am As to the other points made I say 'When in Rome, do as the Romans do. '
If you'll allow me to take a tangent: see the immense history of Rome.

Change happens. You'd be hard-pressed to find someone acting as if they're in the ancient Roman Kingdom/Republic/Empire (each of which period varied greatly).

To reject the nature of traditions changing and being refined for convenience is a logical fallacy. Or, as they'd say in Rome: argumentum ad antiquitatem (appeal to antiquity, e.g., "because it has been, so should it always be").

Having used – and continuing to use – PB for over a decade, I am accustomed to ProcedureReturn. This change is not for me, but to ease the lives of new users who are arguably an important part of the lifeblood of PB.

Though it's a minor stylistic change, it is one that would take a while to become primary tradition, so I figure putting it out there sooner is better than later.

Demivec wrote: Wed Sep 13, 2023 10:13 am PureBasic is more verbose. There is no correlation between the functions of Return and ProcedureReturn. Return has historical use and meaning in BASIC. ProcedureReturn was created and defined for its distinct use in PureBasic.

You can see a similar blend or some would say inconsistency in the defining of arrays, lists and maps by using the keywords Dim, NewList and NewMap.

In this way PureBasic shows ties to its historical roots while also adding more functionality and features.
I'd argue the two are correlated and very similar in their use.

Subroutine return:
  1. Take return address from stack. (or vintage computing: fixed location)
  2. Goto return address.
Procedure return:
  1. (Optional) move result into some register (e.g., EAX).
  2. (Optional) stack cleanup.
  3. Take return address from stack.
  4. Goto return address.
Continuing the analogy from before: BASIC is the ancient Rome to PureBasic's modern day. BASIC's Etruria would be FORTRAN. And while FORTRAN II had a RETURN statement, people were manually writing RETURN statements for a while before then.

I don't want to dwell on phylogenetics of modern BASIC-likes, but even with significant divergence across the spectrum, most do support simple return statements in procedures. Though "all the cool langs are doing it!" is a poor rationale, this commonality is notable when considering historical refinement of tradition.

Since we're not the PB compiler authors, neither you nor I can say whether the decision to separate "Return" and "ProcedureReturn" keywords was one of necessity at the time, a deliberate style favouring explicitness, or a combination of other factors entirely. If it's a clear stylistic stance, I can very much respect that, but if it's instead bound to chronology it might be worth considering this change now. Regardless, I have no qualms with my request being rejected.

On the topic of precedent, context-sensitivity of operations isn't a new type of compiler magic, for example:

Code: Select all

; Outside the scope of functions, this writes to a set memory location.
level = 9001

; Within the scope of functions, this writes to an offset of the stack.
Procedure something()
  level = 9001
EndProcedure

Furthermore, the scope of assignment syntax doesn't affect only how the assignment operation itself is done (and the resulting variable accessed). It also affects whether or not the variable may be accessed at all. For example:

Code: Select all

Global level = 9001

Procedure GetLevel()
  ProcedureReturn level
EndProcedure

Code: Select all

level = 9001    ; Removed "Global"

Procedure GetLevel()
  ProcedureReturn level
EndProcedure
In the two snippets above, "Global level = 9001" and "level = 9001" will compile to the same machine code despite being very different semantically. However, in the second snippet, GetLevel() will not access the root level variable as it's not tagged global (and so instead returns always 0).

This demonstrates not only a departure from BASIC (where everything is Global), but also the fact that language syntax can be context-aware in a manner that affects not only runtime actions done but also effective types/names produced and known to the compiler.

Therefore, similar context-awareness of Return (varying when inside/outside a procedure) is not without precedent, even when ignoring many other languages which have adopted this convention (and their varying reasons for doing so).

Demivec wrote: Wed Sep 13, 2023 10:13 am Anyone who has done many home improvements will ask themselves at some point if it is better to continue to make small adjustments over and over or to instead tear everything down and start again with a new building.
In the same vein, this proposal is then like simply putting a smart light in. A relatively simple thing by itself (unless you've some dimmer setup, which we'll say PB doesn't, given the context-awareness demonstration above).

You can still walk up to the switch and flip it manually (the long way: ProcedureReturn). Or, you can skip the walking, and just tap a button on your PC/phone (Return).

No gutting necessary, no need to redo wiring. Just a simple lightbulb change. (no, this isn't a punchline)
Post Reply