So typically, when I need to do something a little complex, I will write
a shell script.
My boss, on the other hand, will write a shell function that he sources
into his shell.
So typically, when I need to do something a little complex, I will write
a shell script.
My boss, on the other hand, will write a shell function that he sources
into his shell.
I'm curious about the pros/cons of each method.
The biggest "pro" that I see for a shell script over a shell function
is how easily/quickly I can update it. If I have (say) 10 screen
sessions running, a shell function needs to be re-sourced into every
one, while a shell script is instantly available.
Other thoughts? (or facts?)
So typically, when I need to do something a little complex, I[rCa]
will write a shell script.
My boss, on the other hand, will write a shell function that he
sources into his shell.
I'm curious about the pros/cons of each method.
Other thoughts? (or facts?)
POSIX functions, 'f()', may make use of side effects, while
Kornshell functions, 'function f', may have local variables,
own signal handling, own 'getopts' parameter processing.
So typically, when I need to do something a little complex, I will
write a shell script.
My boss, on the other hand, will write a shell function that he
sources into his shell.
I'm curious about the pros/cons of each method.
Side note: The syntax for defining a POSIX function is actually
f() command
The commonly used braces { ... } are _not_ part of the syntax. You
can define a minimal shell function that consists of a single
command. For multiple commands, you need to use a form of grouping,
which is where the braces come in. However, you can also use
( ... ) to inherently run the function body in a subshell.
f() ( ... )
I have actually used this.
Apparently rCRbashrCL does not like that syntax, while rCRdashrCL isquite happy with it.
On 2026-05-12, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
POSIX functions, 'f()', may make use of side effects, while
Kornshell functions, 'function f', may have local variables,
own signal handling, own 'getopts' parameter processing.
Side note: The syntax for defining a POSIX function is actually
f() command
The commonly used braces { ... } are _not_ part of the syntax. You
can define a minimal shell function that consists of a single
command. For multiple commands, you need to use a form of grouping,
which is where the braces come in. However, you can also use
( ... ) to inherently run the function body in a subshell.
f() ( ... )
I have actually used this.
hymie! <hymie@nasalinux.net>:
So typically, when I need to do something a little complex, I will
write a shell script.
My boss, on the other hand, will write a shell function that he
sources into his shell.
I'm curious about the pros/cons of each method.
[rCa]
Other thoughts?-a (or facts?)
It might be very hard or even impossible to make a shell function free
of its context.-a For example, a shell function might iterate over its
given positional parameters:
-a sum()
-a (
-a-a-a unset -v sum arg &&
-a-a-a sum=0 &&
-a-a-a for arg
-a-a-a do
-a-a-a-a-a sum="$(( sum + arg ))"
-a-a-a done &&
-a-a-a printf '%s\n' "$sum"
-a )
Now, if one invokes it like
-a-a readonly arg sum && sum 1 2 3
it will fail.
In this particular example, though, that problem can be avoided:
-a-a sum()
-a-a {
-a-a-a-a if ! : ${1+:} false
-a-a-a-a then
-a-a-a-a-a-a set -- 0
-a-a-a-a else
-a-a-a-a-a-a while ${2+:} false
-a-a-a-a-a-a do
-a-a-a-a-a-a-a-a set -- "$@" "$(( ${1} + ${2} ))"
-a-a-a-a-a-a-a-a shift 2
-a-a-a-a-a-a done
-a-a-a-a fi
-a-a-a-a printf '%s\n' "$1"
-a-a }
On the other hand, a shell script of its own, like
-a #!/bin/sh
-a sum()
-a {
-a-a-a sum=0 &&
-a-a-a for arg
-a-a-a do
-a-a-a-a-a sum="$(( sum + arg ))"
-a-a-a done &&
-a-a-a printf '%s\n' "$sum"
-a } &&
-a sum "$@"
won't fail.
On Tue, 12 May 2026 11:13:27 GMT, hymie! wrote:
So typically, when I need to do something a little complex, I will
write a shell script.
My boss, on the other hand, will write a shell function that he
sources into his shell.
I'm curious about the pros/cons of each method.
I have used shell functions where I wanted to do some direct
manipulation of the shellrCOs internal state. For example, a bash shell function can directly return a sequence of values in a bash array.
Also they are handy because they define commands that are available regardless of your PATH setting--like builtins.
Downsides of shell functions:
* shell-specific
* stay memory-resident once loaded (until explicitly unloaded)
[...]
Side note: The syntax for defining a POSIX function is actually
f() command
[snip], you can also use ( ... ) to inherently run the function
body in a subshell.
f() ( ... )
I have actually used this.
As well as the two grouping commands, compound commands include for,
case, if, while and until.
f() command
The commonly used braces { ... } are _not_ part of the syntax. You
can define a minimal shell function that consists of a single
command.
Apparently rCRbashrCL does not like that syntax, while rCRdashrCL isquite happy with it.
The point with Kornshell functions is not only the sub-shell context
but also with availability of a separate getopts, signal, etc. layer.
That's why I almost always use the 'function f' form. (And meanwhile
it's supported by other prominent shells as well. Though non-POSIX,
On 2026-05-12 19:52, Helmut Waitzmann wrote:
It might be very hard or even impossible to make a shell
function free of its context.-a For example, a shell function
might iterate over its given positional parameters:
That's one reason why I'm using Kornshell functions (as opposed
to POSIX functions), that allow you to iterate separately from
the top-level script getopts over its own arguments in its own
context, and not interfering.
Janis Papanagnou <janis_papanagnou+ng@hotmail.com>:
On 2026-05-12 19:52, Helmut Waitzmann wrote:
It might be very hard or even impossible to make a shell function
free of its context.-a For example, a shell function might iterate
over its given positional parameters:
That's one reason why I'm using Kornshell functions (as opposed to
POSIX functions), that allow you to iterate separately from the top-
level script getopts over its own arguments in its own context, and
not interfering.
The problem I presented is not related to getopts but to the fact that a readonly variable neither can be assigned a new value nor can be unset-arCo even if the assignment resp.-a unset statement occurs in a subshell environment.
Are you going to say that that won't fail using Kornshell?-a So, what
would be the working Kornshell equivalent to the notrCEworking command
-a (
-a-a-a sum()
-a-a-a (
-a-a-a-a-a sum=0 &&
-a-a-a-a-a for arg
-a-a-a-a-a do
-a-a-a-a-a-a-a sum="$(( sum + arg ))"
-a-a-a-a-a done &&
-a-a-a-a-a printf '%s\n' "$sum"
-a-a-a ) &&
-a-a-a readonly arg sum && sum 1 2 3
-a )
when given to a POSIXrCEShell?
On 2026-05-13, Janis Papanagnou <janis_papanagnou+ng@hotmail.com> wrote:
The point with Kornshell functions is not only the sub-shell context
but also with availability of a separate getopts, signal, etc. layer.
That's why I almost always use the 'function f' form. (And meanwhile
it's supported by other prominent shells as well. Though non-POSIX,
And you should be very careful about the semantics of Korn-style
vs. Bourne/POSIX-style function definitions in other shells. For
instance, a quick perusal of the Bash man page indicates that Bash
makes no difference between the two.
On 2026-05-13 23:28, Helmut Waitzmann wrote:
The problem I presented is not related to getopts but to the
fact that a readonly variable neither can be assigned a new
value nor can be unset-arCo even if the assignment resp.-aunset
statement occurs in a subshell environment.
Are you going to say that that won't fail using Kornshell?-a So,
what would be the working Kornshell equivalent to the
notrCEworking command
-a (
-a-a-a sum()
-a-a-a (
-a-a-a-a-a sum=0 &&
-a-a-a-a-a for arg
-a-a-a-a-a do
-a-a-a-a-a-a-a sum="$(( sum + arg ))"
-a-a-a-a-a done &&
-a-a-a-a-a printf '%s\n' "$sum"
-a-a-a ) &&
-a-a-a readonly arg sum && sum 1 2 3
-a )
when given to a POSIXrCEShell?
Trying to change a read-only variable must of course fail since
it's declared 'readonly'. But it makes little sense guessing what
your intention here is.
Initially you had said: "For example, a shell function might
iterate over its given positional parameters [...]"
And that is no problem since you use a Kornshell function with
its own scope.
Summing up values passed to a function, in ksh, I'd just do
function sumupNo.-a Removing that declaration is not an option, as it is part of
{
typeset sum=0 # a local variable
typeset arg # a local variable
for arg
do
(( sum += arg ))
done
printf '%d\n' sum
}
readonly sum sum # no problem but unnecessary - just remove that
# declaration
# irrelevant since you'd work with local vars in sumup# and it makes no sense to have the variables in sumup as r/o
sumup 1 2 3
I think the code is clear enough and don't see where you see a
problem.
If that's not what had been your point, please formulate moreIf you had bothered to run the given example you would have seen
clearly what you actually want to achieve.
(And please also try to formulate the code without unnecessary
irritating obfuscations as naming a function and a variable by
the same name, even if it's functionally no problem.)
Janis Papanagnou <janis_papanagnou+ng@hotmail.com>:
On 2026-05-13 23:28, Helmut Waitzmann wrote:
The problem I presented is not related to getopts but to the fact
that a readonly variable neither can be assigned a new value nor can
be unset-arCo even if the assignment resp.-aunset statement occurs in a >>> subshell environment.
Are you going to say that that won't fail using Kornshell?-a So, what
would be the working Kornshell equivalent to the notrCEworking command
-a-a (
-a-a-a-a sum()
-a-a-a-a (
-a-a-a-a-a-a sum=0 &&
-a-a-a-a-a-a for arg
-a-a-a-a-a-a do
-a-a-a-a-a-a-a-a sum="$(( sum + arg ))"
-a-a-a-a-a-a done &&
-a-a-a-a-a-a printf '%s\n' "$sum"
-a-a-a-a ) &&
-a-a-a-a readonly arg sum && sum 1 2 3
-a-a )
when given to a POSIXrCEShell?
Trying to change a read-only variable must of course fail since it's
declared 'readonly'. But it makes little sense guessing what your
intention here is.
My intention is the one of the OP, as hymie! <hymie@nasalinux.net> wrote:
rCLSo typically, when I need to do something a little complex, I will
write a shell script.
My boss, on the other hand, will write a shell function that he sources
into his shell.
I'm curious about the pros/cons of each method.rCY
The example (summing up the positional parameters by means of a rCLforrCY loop) showed a usecase where some implementation using a shell function
(the boss' way) will fail when used in an invoking shell environment
where the shell variable rCLargrCY or rCLsumrCY happens to be a readonly variable.
On the other hand, the implementation using a shell script (hymie!'s
way) will succeed, even when used in an invoking shell environment where
the shell variable rCLargrCY or rCLsumrCY happens to be a readonly variable.
Initially you had said: "For example, a shell function might iterate
over its given positional parameters [...]"
And that is no problem since you use a Kornshell function with its own
scope.
It is no problem with a POSIX shell as well:-a Each function has got its
own scope regarding the positional parameters.
Summing up values passed to a function, in ksh, I'd just do
-a-a-a-a function sumup
-a-a-a-a {
-a-a-a-a-a-a typeset sum=0-a # a local variable
-a-a-a-a-a-a typeset arg-a-a-a # a local variable
-a-a-a-a-a-a for arg
-a-a-a-a-a-a do
-a-a-a-a-a-a-a-a (( sum += arg ))
-a-a-a-a-a-a done
-a-a-a-a-a-a printf '%d\n' sum
-a-a-a-a }
-a-a-a-a readonly sum sum-a-a # no problem but unnecessary - just remove that
-a-a-a-a # declaration
No.-a Removing that declaration is not an option, as it is part of the invoking shell environment which is neither known to nor in charge of
the rCLsumuprCY implementor.
-a-a-a-a # irrelevant since you'd work with local vars in sumup-a-a-a-a-a # and it makes no sense to have the variables in sumup as r/o
-a-a-a-a sumup 1 2 3
I think the code is clear enough and don't see where you see a problem.
If that's not what had been your point, please formulate more clearly
what you actually want to achieve.
If you had bothered to run the given example you would have seen the
shell's error messages stating that the readonly attribute is the
problem rather than any rCLlocalrCY variable (which is by the way not part of the POSIX standard and in this case unnecessary, as the function
creates a subshell environment of its own by means of the function definition using parentheses for the body of the function).
The problem:-a The implementor of the rCLsumuprCY function doesn't have any means to remove the readonly attribute of any variable defined in the invoking shell environment which happens by coincidence to have the same name like a variable used in the rCLsumuprCY function.
I gave that example using a rCLforrCY loop for summing up the positional parameters to show that in some cases there might exist an
implementation (here: using a rCLwhilerCY loop which doesn't make use of any shell variables besides of the positional parameters) which doesn't
suffer from the rCLreadonlyrCY attribute inherited from the invoking shell environment.
(And please also try to formulate the code without unnecessary
irritating obfuscations as naming a function and a variable by the
same name, even if it's functionally no problem.)
A variable reference is clearly distinguishable from a function
reference by the presence of either a rCL=rCY (when assigning) or a
rCL$rCY (when evaluating).-a So, which lines of the given example were unclear to you?
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 65 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 11:48:51 |
| Calls: | 862 |
| Files: | 1,311 |
| D/L today: |
5 files (10,064K bytes) |
| Messages: | 265,278 |