14

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

fn(){
    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?

Petr Skocik
  • 28,176
  • 14
  • 81
  • 141
  • 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

2 Answers2

14

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.

ilkkachu
  • 133,243
  • 15
  • 236
  • 397
  • 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
8

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)

maxschlepzig
  • 56,316
  • 50
  • 205
  • 279
  • 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