Hello, how about detecting situations in the code like the following: fun() { some code possibly returning false } (( condition )) && fun || print "Some 'else'-instruction" The warning would be triggered when: - a an || would occur after an instruction preceded by &&, - the instruction wouldn't be an always-true instruction, i.e. not ((1)), local var="value", etc. – this would also include prints etc., as the stdout can be closed and such instruction CAN fail – the usefulness of the option is visible here, it would make the users conscious of such fact. Is this doable? To detect a preceding && and a following ||, and check if the instruction is a function or a print? The name of such option could be: warn_symmetric_cond, it would describe the fact of symmetric way of condition processing. To solve the warning, the users could e.g. convert the fun into { fun; ((1)) } or use an if. -- Sebastian Gniazdowski News: https://twitter.com/ZdharmaI IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin Blog: http://zdharma.org
On Wed, Oct 9, 2019 at 6:03 AM Sebastian Gniazdowski
<sgniazdowski@gmail.com> wrote:
>
> Hello,
> how about detecting situations in the code like the following:
>
> fun() { some code possibly returning false }
> (( condition )) && fun || print "Some 'else'-instruction"
I've made a quick-and-dirty search over powerlevel10k source code to
see how often this warning would have false positives. Here are a few
examples of `x && y || z` constructs where `y` can fail and yet the
code is correct.
(( $+GITSTATUS_DAEMON_PID_POWERLEVEL9K )) &&
gitstatus_start POWERLEVEL9K ||
_p9k_gitstatus_disabled=1
mkdir -p ${dst:h} && cp -f $src $dst || return
_p9k_cached_cmd_stdout node -v && [[ $_p9k_ret == v?* ]] || return
`x && y || z` is not `x ? y : z` even though it's often abused as
such. I think the solution is to use `x && y || z` when you mean it,
which is to say *only* when both `x` and `y` may be falsy. The ternary
can be expressed with an `if`.
Compare:
(( condition )) && fun || print "Some 'else'-instruction"
vs
if (( condition )) { fun } else { print "Some 'else'-instruction" }
The latter is longer but is at least as clear. It also comes with
curlies that make it easy to split the statement into multiple lines
if necessary, or to add extra statements inside the branches.
I myself am guilty of using `x && y || z` in place of a ternary
and this leads to bugs that your proposed warning is meant to flag.
However, if I were to enable this warning, I wouldn't be able to
use `x && y || z` when it is the best tool for the job. Hence I'm
leaning towards unlearning my current habbit and starting to use
`if-else` more.
What do you think?
Roman.
On Wed, 2019-10-09 at 10:45 +0200, Roman Perepelitsa wrote:
> I myself am guilty of using `x && y || z` in place of a ternary
> and this leads to bugs that your proposed warning is meant to flag.
> However, if I were to enable this warning, I wouldn't be able to
> use `x && y || z` when it is the best tool for the job. Hence I'm
> leaning towards unlearning my current habbit and starting to use
> `if-else` more.
>
> What do you think?
For clear code, if-then-else is defnitely preferable anyway.
The problems with && / || are very subtle and often don't register even
if you're aware of the possibility.
pws
On Wed, 9 Oct 2019 at 10:45, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > I myself am guilty of using `x && y || z` in place of a ternary > and this leads to bugs that your proposed warning is meant to flag. > However, if I were to enable this warning, I wouldn't be able to > use `x && y || z` when it is the best tool for the job. Hence I'm > leaning towards unlearning my current habbit and starting to use > `if-else` more. > > What do you think? I like the ternary-use of &&/||. I format the code as follows: (( condition )) && \ code || \ code I even use the ((1)) addition to the code || often. However, I might get onto the alternate syntax-way you've proposed, it looks nice. As for the non-ternary, i.e. symmetric-and-still-correct use of &&/|| I would say: the code that is needy of using &&/|| in such a way can skip this hypothetical new warning option. Covering 8 out of 10 functions with it is still a good result (this reminds me the previous discussion we've had). I in general am a very happy user of warn_create_global and I see how much warning-options can give, hence the feature request. I however don't use warn_nested_var, I'm now starting to wonder why, as even that I've sometimes write code using variables from upper scope, the "covering 8 out ouf 10 functions..." point would apply here too. It's however a recent option, not forever-present like the warn_create_global. I wonder if a very much compressed way of enabling warn_nested_var only on shells that have it exists. -- Sebastian Gniazdowski News: https://twitter.com/ZdharmaI IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin Blog: http://zdharma.org
On Wed, Oct 9, 2019 at 1:56 PM Sebastian Gniazdowski
<sgniazdowski@gmail.com> wrote:
> I would say: the code that is needy of using &&/|| in such a way can
> skip this hypothetical new warning option. Covering 8 out of 10
> functions with it is still a good result (this reminds me the previous
> discussion we've had).
I'm not opposed to warnings that may have false positives. That's why
they are warnings rather than errors.
My point here is different. Imagine the documentation for the new
warning:
Warns if `x && y || z` cannot be proven through static analysis to
be equivalent to `if x; then y; else z; fi`.
Doesn't this strike you as odd? If the latter construct has the
desired semantics, why not use it in the first place? It'll obviate
the need for a new warning and convey the intention to humans reading
the code.
Roman.
On Wed, 9 Oct 2019 at 14:08, Roman Perepelitsa <roman.perepelitsa@gmail.com> wrote: > > Warns if `x && y || z` cannot be proven through static analysis to > be equivalent to `if x; then y; else z; fi`. > > Doesn't this strike you as odd? If the latter construct has the > desired semantics, why not use it in the first place? It'll obviate > the need for a new warning and convey the intention to humans reading > the code. The x && y || z is less verbose. It doesn't require `then' and `else' and `fi'. I'm writing from my point of view – that are the reasons why I use &&/||. -- Sebastian Gniazdowski News: https://twitter.com/ZdharmaI IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin Blog: http://zdharma.org
On Wed, 2019-10-09 at 15:17 +0200, Sebastian Gniazdowski wrote:
> On Wed, 9 Oct 2019 at 14:08, Roman Perepelitsa
> <roman.perepelitsa@gmail.com> wrote:
> >
> >
> > Warns if `x && y || z` cannot be proven through static analysis to
> > be equivalent to `if x; then y; else z; fi`.
> >
> > Doesn't this strike you as odd? If the latter construct has the
> > desired semantics, why not use it in the first place? It'll obviate
> > the need for a new warning and convey the intention to humans reading
> > the code.
>
> The x && y || z is less verbose. It doesn't require `then' and `else'
> and `fi'. I'm writing from my point of view – that are the reasons why
> I use &&/||.
Hmm... that's fair enough, but if you're happy to trade off against
readability I think you have to take possible difficulties with the
syntax on the chin...
pws
On Wed, Oct 9, 2019 at 3:17 PM Sebastian Gniazdowski
<sgniazdowski@gmail.com> wrote:
> The x && y || z is less verbose. It doesn't require `then' and `else'
> and `fi'. I'm writing from my point of view – that are the reasons why
> I use &&/||.
Supposing that "if-then-else is too verbose" is a problem that
warrants extending zsh, a natural solution would be to provide an
alternative syntax for the same construct. Something analogous to
`x ? y : z` from C and other languages derived from it.
Note that C had an extra reason besides terseness to introduce this
syntax: if-then-else is a statement while the ternary is an
expression. This reason doesn't apply to zsh, which leaves saving
on typing as the only benefit of the contemplated innovation.
Since `x ? y : z` already has a meaning in zsh, the new syntax would
have to be different and likely unfamiliar to users.
All-in-all, doesn't seem worth the trouble. if-then-else has the
desired semantics, isn't more verbose than in other languages,
and is easy to read even for people unfamiliar with zsh.
Roman.
On Wed, 9 Oct 2019 at 15:25, Peter Stephenson <p.stephenson@samsung.com> wrote: > > Hmm... that's fair enough, but if you're happy to trade off against > readability I think you have to take possible difficulties with the > syntax on the chin... I thought that: [[ -z $ver ]] && ver="unknown (no .git/refs/heads/master)" || ver=${ver[1,7]} is more or equally readable to: if [[ -z $ver ]]; then ver="unknown (no .git/refs/heads/master)" else ver=${ver[1,7]} fi especially if I would format it like I would today: [[ -z $ver ]] && \ ver="unknown (no .git/refs/heads/master)" || \ ver=${ver[1,7]} but I'm seeing your point. This is like commenting or not the code – I was for a long long time pro-commenting, to just drop it recently, actually finding pleasure in writing a condensed, I could agree – (less /un)readable code. -- Sebastian Gniazdowski News: https://twitter.com/ZdharmaI IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin Blog: http://zdharma.org
2019-10-09 15:41:41 +0200, Sebastian Gniazdowski:
[...]
> I thought that:
>
> [[ -z $ver ]] && ver="unknown (no .git/refs/heads/master)" || ver=${ver[1,7]}
>
> is more or equally readable to:
>
> if [[ -z $ver ]]; then
> ver="unknown (no .git/refs/heads/master)"
> else
> ver=${ver[1,7]}
> fi
[...]
but thyes are different things.
a && b || c, is "run c unles both a and b succeed".
You typically use these things in if statements like
if a && b || c; then
...
fi
You could always do something like:
alias -g '^=else'
if ((x)){echo yes} ^ {echo no}
(can be shortened to if((x)){echo yes} ^ {echo no} with zsh -o
noglobqual -o shglob).
Or even:
alias -g '&|=else'
alias '?=if'
? ((x)){echo yes}&|{echo no}
--
Stephane
On 2019-10-09 6:41 a.m., Sebastian Gniazdowski wrote:
> but I'm seeing your point. This is like commenting or not the code – I
> was for a long long time pro-commenting, to just drop it recently,
> actually finding pleasure in writing a condensed, I could agree –
> (less /un)readable code.
>
Just a comment from the unwashed:
Maybe I'm the only one, but it has always seemed to me that in the
entire cycle of developing software, the time spent entering keystrokes
is a tiny fraction. You save a few seconds typing a line, but come back
to it a while later and you spend hours figuring out your own code. Zsh
has incredibly compact syntax already, and if I don't comment every
line, since I can go months without writing anything, when I come back,
I've forgotten the syntax and must refer to my comments. They say that
with Perl, every keystroke needs a sentence of comment to understand
it. My notion of the ideal language would be quite verbose and
self-explanatory. IMHO the last thing zsh needs is more terse syntax.
Just my two cents.
On Wed, 2019-10-09 at 07:07 -0700, Ray Andrews wrote:
> Maybe I'm the only one, but it has always seemed to me that in the
> entire cycle of developing software, the time spent entering keystrokes
> is a tiny fraction. You save a few seconds typing a line, but come back
> to it a while later and you spend hours figuring out your own code.
This is certainly my experience, and of course it's a lot worse if it's
somebody else's code, which is an important point in any medium to large
scale software projects.
There's the separate question of whether short code is more readable in
some circumstances, which can be the case (or we'd be using some
derivative of COBOL or PROLOG for programming). But if what it's doing
is obscure --- what you're reading isn't what you think you're reading
--- this advantage goes away.
pws
Roman Perepelitsa wrote on Wed, Oct 09, 2019 at 15:40:48 +0200: > Supposing that "if-then-else is too verbose" is a problem that > warrants extending zsh, a natural solution would be to provide an > alternative syntax for the same construct. Something analogous to > `x ? y : z` from C and other languages derived from it. Extending the SHORT_LOOPS form of «if» to allow an «else» comes to mind, but I'm honestly not sure if it'd be a good change to make. > Note that C had an extra reason besides terseness to introduce this > syntax: if-then-else is a statement while the ternary is an > expression. This reason doesn't apply to zsh, which leaves saving > on typing as the only benefit of the contemplated innovation. > Since `x ? y : z` already has a meaning in zsh, the new syntax would > have to be different and likely unfamiliar to users. > > All-in-all, doesn't seem worth the trouble. if-then-else has the > desired semantics, isn't more verbose than in other languages, > and is easy to read even for people unfamiliar with zsh. Cheers, Daniel
On Tue, Oct 8, 2019 at 9:03 PM Sebastian Gniazdowski
<sgniazdowski@gmail.com> wrote:
>
> The warning would be triggered when:
> - a an || would occur after an instruction preceded by &&,
> - the instruction wouldn't be an always-true instruction
To add to what's already been bandied about:
This seems like something better suited for a shell script "lint" type
program, rather than something to emit as a run-time warning from the
shell itself. There's also the question of when this warning would be
emitted; if at execute time, is it really doing anything useful? If
at parse time, the parser has to become aware of even more semantics.
Creation of global variables and references to unset variables can't
really be detected by syntax examination, but all the cases the shell
could successfully warn about in this scheme are, I think, resolvable
by looking at the individual pipelines. If you want a runtime
warning, maybe do something with ${(z)ZSH_DEBUG_CMD} in a TRAPDEBUG
function?
On Wed, 9 Oct 2019 at 20:15, Bart Schaefer <schaefer@brasslantern.com> wrote: > > This seems like something better suited for a shell script "lint" type > program True, it's well suited for such program, but maybe it isn't that bad also for the shell? > rather than something to emit as a run-time warning from the > shell itself. There's also the question of when this warning would be > emitted; if at execute time, is it really doing anything useful? I think yes: it would work similar to warn_create_global – when working on a script it would emit such warnings and inform the programmer of the problem. The programmer would then react and change the code, preventing it to be released to the public, like in the case of creating a global. > If you want a runtime > warning, maybe do something with ${(z)ZSH_DEBUG_CMD} in a TRAPDEBUG > function? Thanks, that's an interesting idea. -- Sebastian Gniazdowski News: https://twitter.com/ZdharmaI IRC: https://kiwiirc.com/client/chat.freenode.net:+6697/#zplugin Blog: http://zdharma.org