help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Use readonly wherever possible?


From: Maroloccio
Subject: Re: Use readonly wherever possible?
Date: Thu, 7 May 2020 06:34:10 -0300
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:68.0) Gecko/20100101 Thunderbird/68.8.0

On 06/05/2020 12:17, Greg Wooledge wrote:
On Wed, May 06, 2020 at 12:04:08PM -0300, Maroloccio wrote:
or general thoughts on marking explicitly as "const" what is
de-facto "const":

* https://isocpp.org/wiki/faq/const-correctness

You're bringing concepts from other languages into bash, and expecting
them to play out the same way in bash that they do in these other
languages.

Bash isn't like other languages.

unicorn:~$ readonly foo=bar
unicorn:~$ foo() { local foo="$1"; }
unicorn:~$ foo bar
bash: local: foo: readonly variable

The "readonly" flag is HEAVY.  It is not a thing you toss around as if
it only affects a single scope.


As you illustrate, the "readonly" flag has the surprising behaviour of
propagating to a seemingly new assignment within a function's scope.

Your linked bug-bush discussion illuminates the intent of this,
which was to purposefully prevent local overriding by preemptively
setting the flag, thus "restricting" the shell.

I agree that the counter-intuitive nature of this in comparison to other
programming languages is potentially fraught with problems and I would
similarly advise not to use "readonly" in a global scope.

The intent of the links was to:

- Show that some programming styles actually prefer avoiding argument
  reassignments or even ensure that through static code analysis and
  continuous integration checks, and that if one embraced that style
  there was a way to replicate it in Bash using: "local -r"

- There are other programming styles in which marking const args as
  such explicitly is seen as desirable, and that "local -r" approximates
  that denotation in Bash

Not using it in an outer scope still leaves the possibility of using it
in a local scope, in my opinion. And I do.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This script:

#! /usr/bin/env bash

f() {
    local -r foo=2
    declare -p foo
}

# Outer scope, can assign to foo
foo=1
declare -p foo

f  # Setting read-only on foo inside f()'s scope
foo=3   # Can still assign to foo in this scope
declare -p foo

readonly foo=4  # Setting read-only on foo in outer scope
f # Now this call fails, arguably surprisingly in comparison with other languages

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Outputs:

declare -- foo="1"
declare -r foo="2"
declare -- foo="3"
/tmp/tmp.bash: line 4: local: foo: readonly variable
declare -r foo="4"

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Until setting the flag in the outer scope, things seem to work just
fine.

I think by limiting the usage of the read-only flag to local scopes
one can harmlessly get the benefits of the aforementioned programming
styles.

I am not debating the validity of those styles over others, by the way.

When I decided that I would embrace this `local -r` idiom, I did check
the following script first, and it works as I intuitively expected it
to:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This script:

#! /usr/bin/env bash

f() {
    local -r foo=bar
    declare -p foo
    g() {
        local -r foo=baz
        declare -p foo
    }
    g
    declare -p foo
}

f

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Outputs:

declare -r foo="bar"
declare -r foo="baz"
declare -r foo="bar"

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I still maintain that "local -r" within functions is harmless and
potentially beneficial to those who think in that "local consts or
no-args-reassign" way.

Thanks for showing us all the pitfalls of Bash, by the way, Greg.

--
Marco Ippolito
address@hidden





reply via email to

[Prev in Thread] Current Thread [Next in Thread]