In dash, functions and variables appear to live in separate namespaces:

    fn="hello world"
fn; echo "The value is $fn!" #prints: The value is hello world!
fn; echo "The value is $fn!" #prints: The value is hello world!
#the fn variable doesn't conflict with the fn function

Is this a dash-specific feature or a POSIX guarantee?

  • 2
    Your code doesn't actually prove that the fn function is in a separate namespace; if executing it once had wiped out its definition, we'd see exactly the same behavior. You should show that the function is still defined, e.g. with type fn afterwards. – alexis Oct 30 '16 at 14:25

A guarantee:

2.9.5 Function Definition Command

A function is a user-defined name that is used as a simple command to call a compound command with new positional parameters. A function is defined with a "function definition command". [...]

The function is named fname; the application shall ensure that it is a name (see XBD Name) and that it is not the name of a special built-in utility. An implementation may allow other characters in a function name as an extension. The implementation shall maintain separate name spaces for functions and variables.

  • Also note that unset has -v and -f to choose between unsetting the variable or function by the given name. bash (as opposed to most other shells) will unset the foo function with unset foo if there's no foo variable (!), a behaviour allowed by POSIX. That's why in POSIX scripts it's good practice to always use either -v or -f (and of course in bash scripts as well, but note that unset may not always unset a variable in bash, bash variable scoping has quite a few issues). – Stéphane Chazelas Jan 18 '18 at 13:26
  • Note that in pre-shellshock bash, you'd have problems when exporting both the variable and function by a given name, as bash would end up using the same environment variable name for both (putting it twice in the environment, some commands could remove one of them) – Stéphane Chazelas Jan 18 '18 at 13:29

Variables and functions reside in different namespaces in dash and this is also specified by POSIX:

The implementation shall maintain separate name spaces for functions and variables.

In addition to that, variables have global scope, by default. Some shells (e.g. bash, ksh and zsh) provide the local keyword to declare variables in a function with local scope only.

So, yes, the behavior you are seeing is guaranteed by POSIX.

POSIX hasn't standardized local, yet:

The description of functions in an early proposal was based on the notion that functions should behave like miniature shell scripts; that is, except for sharing variables, most elements of an execution environment should behave as if they were a new execution environment, [..]

[..] Local variables within a function were considered and included in another early proposal (controlled by the special built-in local), but were removed because they do not fit the simple model developed for functions and because there was some opposition to adding yet another new special built-in that was not part of historical practice. Implementations should reserve the identifier local (as well as typeset, as used in the KornShell) in case this local variable mechanism is adopted in a future version of this standard.

(emphasis mine)

  • ash (from the late 80s) upon which is based dash also has local, one of the most consistent interfaces out there (compared to the severely broken one in bash for instance), bash only just recently (4.4) borrowed the local - (for local scope for options) from ash (implementing ash-style scoping for that one $- variable only). ksh and yash don't have local (only the pdksh variants have local), but have typeset instead (in ksh93 typeset provides local (static) scope only in functions declared using the ksh syntax). – Stéphane Chazelas Jan 18 '18 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.