Enabling `no strict` for `raku` one-liners (and perhaps REPL)
The details are a bit fuzzy now, and IRC searches have not clarified much, but I remember heavily advocating for moving the behavior of -e invocations from no strict to use strict. Enough others agreed and this was changed sometime prior to 6.c.
I honestly think this is still a good default. I'm glad we aren't in the position where no strictis the default expectation and it's impossible to remove or change because of inertia
But over time I've come to understand that no strict is actually a great deal less absurd in Raku than it is in Perl. I've even been inspired to use it a time or two.
Reading this comment from @raiph yesterday, I thought it might be time to discuss providing a new switch for the raku command -- either used in conjunction or as a replacement of -e -- that would evaluate the expression string with no strict as a preamble.
Here is the commit which changed the behavior back in 2015. It doesn't explicitly state "because ab5tract won't shut up about it" in the commit message, but...
On the other issue I suggested -E
Hi @ab5tract, @FCO,
I followed the link Liz provided in the other issue. That immediately made it clear to me that enabling strict by default was a decision driven by adequate discussion and consensus. So that pretty much concluded things for me.
That said, I was curious to understand what had led to that consensus, and also whether there had been a push for something like -E, and if so, what the conclusion was. So I fired off searches for both p6u (mentioned in the commit) and #perl6:
I almost immediately bumped into Tux's very powerful argument: confusables. Here was his example:
-e'my Int $this = 1; $thıs++; say $this;'
The $thıs++ uses a Turkish dotless ı.
He's so right.
I've seen confusables as a slow motion train wreck waiting to happen to Raku for about a decade. So slow in fact I'd forgotten about them.
Malicious online Raku one-liners that devs cut/paste/run absolutely could become a thing.
Anyhow, I now see why strict needs to be on for all scenarios.
And why the most natural vulnerable point is cut/paste/run of code such as one liners.
And why we don't want to huffmanize skipping it with something like -E.
Indeed, if we ever think we've adequately addressed confusables by default, then I'd likely still be for keeping strict on by default for -e, and I might well vote against -E too, until/unless we are sure whatever defenses we've put in place against confusables are sufficient. Getting to that level of comfort would presumably take years even after introducing adequate defense by default (assuming we ever get that done; we don't even have a userland module defense, presumably because it's a major undertaking).
So, in summary, I had reversed my stance when I discovered there had already been proper discussion and a rough consensus decision, even before I looked at the discussion. And having been reminded of confusables I'm hard core with that consensus. There may have been other good arguments for or against, but for me the confusables argument is devastatingly strong.
More later but:
And then I reflected on what may have been @jubilatious1's thinking. Perhaps he had confusables in mind?
This would read a lot more comfortably to me if you were using the @ reference to ask a direct question of the person being referenced instead of wondering about their thoughts in third person with a presumed pronoun.
I don't mean to imply you meant any ill intent but rather I believe you to be concerned about how language is used and I get a sense that you desire for your text to read as considerate. So this stood out pretty starkly.
Hi @ab5tract
I've reflected on when I've wanted no strict; and it's always been when I'm not cutting/pasting someone else's code, but writing all the code, and wanting my code to have minimum boilerplate, and wanting others to feel free to copy my code.
The next thought that popped into my head was that @jubilatious1 may have had confusables specifically in mind when they talked about deliberately choosing to not even mention strict on unix.se. While I didn't previously understand why they raised the non mentioning aspect, and regardless of their reasoning but especially if it was due primarily to the issue of confusables, I now interpret their principle of not mentioning strict as unequivocally important, because while talking about confusables here is hopefully appropriate, talking about it on unix.se most definitely isn't, and while I don't think the generic strict concept in PLs is obviously connected to confusables, in Raku the one currently inevitably leads directly to the other.
(Note that I don't mean my @mentions to bother anyone, to summon them, if they're not interested in engaging with something I've written. Afaik my mention should not "summon" them because they're not listed in the autocomplete for @mentions. If they choose to visit this thread then they'll get to see how I may finally be cottoning on to why they mentioned not mentioning strict, and my hope is that they'd appreciate that.)
I mention the foregoing partly because a brainstorm followed. Maybe the following is absurd, but hopefully not.
Perhaps an initial cut at giving Rakoons a general defense against confusables would be an "ASCII" mode that clamped variable names down to ASCII instead of full Unicode. Initially just clamping user defined variable names to Aa thru Zz (and underscore).
~~Perhaps a userland module named A. One that disabled strict for -e. Then one could write -MA -e and cut/paste/write/run a no strict one liner without boilerplate.~~
[I've edited this (now blown over) "brainstorm" to align its "thinking" with @ab5tract's comment below emphasizing that this issue isn't about any change to -e. That said the idea was very flawed anyway, and I've since shifted my focus to a much simpler and, for me, better solution. After posting this edit I will hide this comment.]
Perhaps a userland Rakudo plugin module named A. One that introduced a -E that's like a standard -e but which is different in that no strict; is in force (so variables can be introduced without my) and identifiers are locked down to eliminate confusables (so cut/paste of others' code doesn't risk the dangers of confusables). Then one could write -MA -E and cut/paste/write/run a one liner without my "boilerplate".
There will be plenty of negatives. As I write this one that immediately popped into my head was that such a "feature" might badly backfire, primarily bringing undue attention to Raku's confusables dilemma. Hmm.
Anyhow, food for thought.
PS. I deeply love that you cared. And even more, that you spoke up. I mean that about both you opening this issue (which felt like you were deeply caring about me and my thoughts, even while I found it a bit ironic because I only saw it after I had accepted there was a clear consensus against disabling strict for -e for 6.c, which had already thoroughly demolished my thought process behind me writing "FWIW, unless there was a clear consensus against it, I would support a PR disabling strict for -e for 6.e.) and then engaging further with me. Regardless of whether my faux pas ends up being a consequential one, or has happily been caught before it was, I will always remember that you gently brought my attention to something I have tried to studiously avoid for a decade or more, long before I knew many of the Rakoons who are active today.
Under the hood App::Crag (Calculator using RAku Grammar) uses no strict and eval so that e.g. you can calculate the size of your woodpile like this and save on 4 mys...
crag '$h=69;$w=31+21;$d=21+43;$v=$h*$w*$d; say (♎️"$v cu in").in: <cords>'
I think in this 'extreme' use case, the $ sigil is good enough to denote a var visually
And yet, I am not asking for no strict to be the default eg on raku -e or even raku -E since this can be handled under the hood with the current tools.
In case it isn't clear, there is nothing in this problem-solving query about changing the behavior of -e.
FYI, I managed to write over 500 answers in Raku on Unix & Linux StackExchange, without ever once invoking no strict.
In fact, until an esteemed Rakuun here on Github mentioned it, I had no idea the no strict pragma even existed. I had to look it up just last week, on docs.raku.org (which is a good thing).
I feel it would be a mistake to have the Raku language default to different levels of strictness based upon context. For example, no one would suggest that strict be enabled by default on Unix/Linux, while Windows would default to no strict. Simply put, you would want Windows Raku users to be able to run unmodified Unix/Linux Raku code, and vice versa.
I feel code that runs in a script should be freely transferrable to a one-liner, and vice-versa. Command-line switches should be kept to a minimum (-e, -pe, -ne). There's an NNTP post from @\TimToady saying at least one command-line switch went away because '...it wasn't pulling its weight'. The general argument is to have the code do the heavy-lifting, not the switches (reducing complexity):
https://www.nntp.perl.org/group/perl.perl6.users/2020/07/msg9004.html
Already I can pretty reasonably re-write -pe, -ne one-liners using for lines(), so pretty simple to convert that code to a stand-alone script.
@ab5tract are you saying no strict is presently disallowed in one-liners? Not really sure, and I'd be hard-pressed to do a complete test. If I recall there were some curlie/parens issues I encountered within BEGIN blocks, and no strict was offered as a solution. But maybe I need to learn curlie/parens rules better, instead?
Anyway---making a wild estimate here---that for every command-line switch that has to be fiddled with on a regular basis, we lose 50% of new users.
If my original post lacks clarity, I apologize.
Some attempts at clarification:
no strictcan obviously be added to a-einvocation. But the whole point of turning offstrictis to save some typing. One needs to declare three separate variables in order to make typing outno strictworthwhile. This is the entire basis of the proposal.- To repeat myself: I absolutely, 100% do not believe
-ebehavior should change. - There are no workarounds for disabling
strictfor CLI invocations besides includingno strictitself, belying @librasteve's declaration that there are other readily available alternatives. -Eis too close to-eto be appropriate in my opinion (also a bit confusing in contrast toperl, where-Eturns on all those features which were missing when-ewas introduced.) Something at the opposite end of the spectrum, like-Yor-Z, seems better to me. Debatably, requiring the switch to be combined with-e(ie,-Ze), is even better because it adds a layer of consideration to the mix.- @raiph's excellent resurrection of the non-ASCII potential for havoc in
no strictis the strongest argument against providng an invocation flag. - This would be a flag for users who know what they are doing. Hopefully such users will also know that sharing invocations as a learning exercise would necessarily involve adapting those invocations back to the default (
use strict) behavior of-e. If not, other knowledgeable and more concientious users can be expected to correct such miscarriages of syntax.
@ab5tract wrote:
If my original post lacks clarity, I apologize.
Thank you for your well-worded and thoughtful reply.
One-liners are often a "point-of-entry" for new users to a programming language. The problem with an "alphabet-soup" of command line switches is that new users copy/paste them with little thought/understanding, often lifting a one-liner from StackOverflow verbatim. When they try to modify/augment/extend the code, they get stuck/discouraged if the basic safeguards of the language have been disabled.
If strict is one of the most important changes between Perl and Raku, then we shouldn't make it easy for a new user to accidentally disable it. A copy/paste of a flag that does something as dramatic as turning off strict essentially impairs a new user's ability to learn the language. An introduction to my and our is delayed, for example.
\ ab5tract wrote:
This would be a flag for users who know what they are doing.
The problem isn't old users who know what they're doing--but new users who think they know what they're doing (and are incorrect).
The fear is that new users will drop the language because it's too frustrating/confusing, or because of a bad experience (e.g. lost/corrupted/overwritten files, etc).
We can help new users avoid those bad experiences.
@ab5tract wrote
There are no workarounds for disabling strict for CLI invocations besides including no strict itself, belying @librasteve's declaration that there are other readily available alternatives.
Good point - apologies for giving that impression. I agree that this is not directly relevant to the raku command.
My idea was something dual:
(i) not requiring my in one liners is a concrete benefit, after all perl/raku/$ syntax was originally intended for bare vars, this is the specific trade off I made in crag [blush]
(ii) on lines of if you want to make a command that has [strict|no strict] behaviour, then (if you care that much about it) then you can make you own command such as crag
Reduces noise to signal: I agree with this proposal
@librasteve wrote:
(i) not requiring my in one liners is a concrete benefit...
I don't see it that way:
- One-liners using
-neor-pelinewise command-line flags have shortcuts that don't require variable declarations, such ass/old/newandtr/old/new. Otherwise you can often get by with a$_and shortcuts (e.g..putshort for$_.put). Above that, you havestatevariables that can be invoked, with or withoutBEGIN/ENDblocks. If you're doing anything more complex, you're probably not using-neor-pebut usinglinesorslurpinstead, which gets you into the realm of free-standing scripts, not CLI one-liners. - If you don't invoke
my, then what's your variable's scope? Does Raku default to local or global (our)? Which is safer (probablymy)? So we're going to havemy-optional variables? Again, a lot of effort for a newbie to dissect/correct a non-functional one-liner due to a (possible) command-line flag error. - Why the focus on eliminating
myorourfrom one-liners? They very clearly have scoping utility and furthermore prevent mis-spelled variable names. Then you have thestatevariable declaration, which only initializes once inside a block. Somy,our, andstatemakes for a nice trio, while adding ano-scoping-declaration$var would seem to be the odd player out.
Right now I always can grep through my code for the line where I initialize a variable. Why should that change? And if a no-scoping-declaration $var is implemented, what prevents a newbie from instantiating a $x at the top of the code and again $x (mistakenly) at the bottom of the code, causing errors?
Finally, I do hope some Rakuuns will take a look at the over 500 one-liners I've posted on StackOverflow/StackExchange. My hope is that users in the "Unix & Linux" StackExchange forum will pick-up on this body of work and adopt Raku for CLI tasks. Feedback (and upvotes) appreciated:
https://unix.stackexchange.com/search?q=user%3A227738+%22raku%22
https://unix.stackexchange.com/users/227738/jubilatious1
@librasteve wrote:
(i) not requiring my in one liners is a concrete benefit...
I don't see it that way:
- One-liners using
-neor-pelinewise command-line flags have shortcuts that don't require variable declarations, such ass/old/newandtr/old/new. Otherwise you can often get by with a$_and shortcuts (e.g..putshort for$_.put). Above that, you havestatevariables that can be invoked, with or withoutBEGIN/ENDblocks. If you're doing anything more complex, you're probably not using-neor-pebut usinglinesorslurpinstead, which gets you into the realm of free-standing scripts, not CLI one-liners.
One-liners are about getting things done. Period. -pe and -ne are great in their own corners of CLI processing and in fact provide a massive benefit in those use cases because they provide an implicit context.
This problem solving ticket raises the question of whether other users see a net benefit in adding another flag (let's call it -Y, as a sort of shorthand for "Yes I'm opting into something I understand") that also provides an implicit context, this time for (essentially) pre-pending no strict; at the beginning of the provided invocation.
- If you don't invoke
my, then what's your variable's scope? Does Raku default to local or global (our)? Which is safer (probablymy)? So we're going to havemy-optional variables? Again, a lot of effort for a newbie to dissect/correct a non-functional one-liner due to a (possible) command-line flag error.
Importantly, our doesn't mean "global" (maybe we have different definitions here?). It means that it is accessible from outside of it's scope. It is still strictly namespaced.
However, the rule of no strict is super simple: without a scoped declarator, there is only one.
no strict;
$x = 1;
module X {
$x = 2;
module Y {
our $x = 3;
}
}
dd :$x;
dd :X($X::x)
dd :Y($X::Y::x)
# :x(2)
# :X(Any)
# :Y(3)
Again, I don't expect newbie to be exposed to -Y one-liners. But I also have enough confidence in "newbies" to be able to understand the relevance of strict and discern the very simple distinction between it being on and off. FWIW, I think there are a thousand and one things that bounce people off of learning Raku and I do take these things into consideration and usually push for simplicity and user-friendliness.
Yet I also find arguments for restricting QoL improvements for power users for the sake of new user onboarding to be a matter of degree. In this case, the degree of added velocity that a user capable of understanding strict -- 10 days new or 10 years experienced -- would gain from -Y (in my opinion) far outweighs catering to users that are too new to programming to understand the concept.
- Why the focus on eliminating
myorourfrom one-liners? They very clearly have scoping utility and furthermore prevent mis-spelled variable names. Then you have thestatevariable declaration, which only initializes once inside a block. Somy,our, andstatemakes for a nice trio, while adding ano-scoping-declaration$var would seem to be the odd player out.
I guess it's because this is a problem-solving ticket related to giving users the option of having the benefits of no strict; without typing it in?
It's not like there is some concerted, organized, cabalistic push to eliminate strict-ness.
Right now I always can grep through my code for the line where I initialize a variable. Why should that change? And if a
no-scoping-declaration$var is implemented, what prevents a newbie from instantiating a$xat the top of the code and again$x(mistakenly) at the bottom of the code, causing errors?
Again, no one is talking about forcing you to change your code or the way you write it? What kind of one-liner is a newbie creating that it is so large that they've lost track of their variables?
Since we would all surely suggest to any new user that they should start off with -e instead of -Y, if they ask for help or seek documentation, then a resolution to their double-usage issue appears immediately.
Finally, I do hope some Rakuuns will take a look at the over 500 one-liners I've posted on StackOverflow/StackExchange. My hope is that users in the "Unix & Linux" StackExchange forum will pick-up on this body of work and adopt Raku for CLI tasks. Feedback (and upvotes) appreciated:
https://unix.stackexchange.com/search?q=user%3A227738+%22raku%22
https://unix.stackexchange.com/users/227738/jubilatious1
These are awesome efforts @jubilatious1 ! Genuinely, I want to express a massive THANK YOU for spreading these far and wide!! I will log into SE and upvote.
But just to play devil's advocate: who is to say how many potential users might be gained based on examples that are even more concise due to -Y?
@jubilatious1 - thanks for sharing your one liner trove - I had no idea this v. cool resource is out there. definitely will bring these into my toolkit!
to illustrate my claim that this proposal would be a concrete benefit, the point at which I decided to make no strict the default in App::Crag was when I found myself writing this:
crag 'my $h=69; my $w=31+21; my $d=21+43; my $v=$h*$w*$d; say ^"$v cu in" .in: <cords>' #my logpile
and I felt that for a quick knock up calculation the declarations were overkill
now I can do this:
crag '$h=69; $w=31+21; $d=21+43; $v=$h*$w*$d; say ^"$v cu in" .in: <cords>' #my logpile
which is a reduction from 81 to 69 chars (15%) which I feel is quite a lot of unnecessary housekeeping for this specific use case
coming from perl, my main point is that my eye is trained to detect the $ and so a declaration is not essential as a way to distinguish a var
I would not advocate for this proposal in anything that has more than 1 line or that needs multiple scoped blocks
@librasteve if this is about crag, why no put `no strict; ' in front of the expression on the command line before EVALling it?
@lizmat - sorry I have not explained myself very well, maybe I can clarify:
- crag already puts
no strictin front of the eval - I decided on this design choice for crag since I felt that declarations were overkill for one liner calculations
- this proposal will not change crag - rather I am using the history here and crag examples to illustrate why and where I think this proposal would provide a concrete benefit ...
;-)
@librasteve wrote:
crag 'my $h=69; my $w=31+21; my $d=21+43; my $v=$h*$w*$d; say ^"$v cu in" .in:
' #my logpile
In the Raku REPL:
[0] > my ($h,$w,$d) = (69,31+21,21+43); my $v=$h*$w*$d; say "$v cu in";
229632 cu in
Cheers.
@jubilatious1
well yes, you don't need crag for basic arithmetic, but since it brings Physics::Measure to the party, you can easily do units conversion eg from cu in to cords
I am precoccupied with web stuff right now, but one day I aim to put lizmats new repl tools at the heart of crag 2.0 ;-)
@librasteve
well yes, you don't need
cragfor basic arithmetic, but since it brings Physics::Measure to the party, you can easily do units conversion eg fromcu intocordsI am precoccupied with web stuff right now, but one day I aim to put lizmats new repl tools at the heart of
crag 2.0;-)
I was just trying to show how three my declarations can be collapsed to one:
my ($h,$w,$d) = (69,31+21,21+43);