no, I'm not referring to giving the do in for loops and while loops a free pass. rather, I'm referring to the rarely-used naked do block. the primary function of the do block by itself is to arbitrarily introduce a new scope. for example, a code snippet I just wrote:
do local yclp=127-17*pizzapower clip(104,yclp,127,127) end
this makes it clear to the reader that I do not intend to use yclp at any other point in the program. In this case, it becomes fairly obvious that I lifted an inline expression to its own line for clarity's sake. however, the do construct here eats up a token, making using it disadvantageous. considering that the do block's only real use has to do with usage of local variables, and the local keyword already has its cost annulled to encourage its use, I think it would make sense if there was a similar exception for the by-itself do block. what do all of you think?
You could say the same about parentheses. They're really both just hints to the parser about what goes where and what's associated with what. Nevertheless, even if they don't really have a runtime functionality once parsed, they're still a part of your cart, since the parsing happens at runtime. So, even though I'm usually one for reducing unnecessary token costs, I'm not sure I can get behind this one.
@Felice the difference is that parens have a lot of uses and as such you can't really avoid using them. plus, changing the cost of parens would have a lot of knock-on effects since they are used in so many constructs anyway, so that's a much more complicated subject.
naked do blocks on the other hand are completely avoidable-- if they have a cost, almost nobody will use them. it's the same reason the local keyword has no cost to it.
@freds72 the purpose would be to encourage more use of the do block in order to facilitate cleaner code. as it stands pico's rules encourage that if you don't need a do block, you should go without, which leads to poorer code hygiene, especially in large functions which effectively contain several "subroutines" that could each be neatly delineated with a do block.
if you go this way, tbh, the whole token concept goes to the bin!
pico point is not clean code, is balance between features/readability/performance/...
you want clean code, you get less features 🤷♂️
(ok local is the exception here...)
(and for this case, a comment will do!)
local is the comparison I'm trying to make here, I suppose. it feels like if binding a variable to a scope is free, creating a new scope should also be free. especially since, outside of super-advanced use cases like yours, there really isn't much reason to use do blocks outside of code hygiene-- in fact I'd argue the primary function of the do block is to guard against accidental variable shadowing, which is something that can always be trivially worked around.
it comes down to taste, I suppose-- but I also think compared to a lot of other potential token exemptions one could argue for, the do block is one of the least complicated to implement with the fewest potential non-obvious side effects.
As much as I'd love token count reductions, I don't find the argument compelling.
The main weakness is that I don't consider it appropriate to draw a comparison between naked do...end vs local. They are related, but different.
do..end creates a scope for cost of 1 token. In this sense it should be compared to other scope creation costs:
if <cond> then <body> end
if: 1 token for the branching construct
then+end: 1 token for scope creation
if <cond> then <body1> else <body2> end
if: 1 token for the branching construct
then+else+end: 2 tokens for scope creation ×2
while <cond> do <body> end
while: 1 token for the looping construct
do+end: 1 token for scope creation
repeat <body> until <cond>
1 token for looping construct
1 token for scope creation
function(<params>) <body> end
function+end: 1 token for scope creation
parentheses: 1 token for demarcation of params
[note that function name is not relevant to this discussion: since functions are first class values, 1 token cost for function name in 'function name() ... end' is analogous to variable name in 'name=function() ... end']
By contrast, local is used within a scope to flag vars that should be confined to that scope, rather than global. The cost for creating the scope has already been paid, so presumably the rationale is that there is no need to pay a token cost again for each 'local' keyword.
[Please log in to post a comment]