-> can override functions without a warning
Use
function funcname () { ...body... } declare -rf funcnameand function
funcname can be referenced and used, but not redefined.
Note that function and variable namespaces are separate: you can also have a variable
funcname. You may therefore wish to add
declare -r funcname=funcname-> no actual return value
Use the 'first argument specifies result variable name' pattern:
function funcname () { [[ $# -ge 2 ]] || return 1 declare -n retval="$1" shift 1 ...body... retval=value-or-expression } declare -rf funcname declare -r funcname=funcnameand you can modify the named variable in the caller scope. Granted, this isn't "return value" per se, but passing a variable by reference, allowing modifying the variable in the caller scope.
In Bash, and many other shells, the return value is always
status; zero for success, nonzero values indicating errors.
Exit status itself is always accessible as
$?.
-> the number of arguments is not checked
Just like in C main(), you need to do it yourself.
$# is the number of positional parameters (
$1,
$2, ..., also
${1},
${2}, ...),
NOT including the function name itself (
$0 or
${0}. In the example before, the line
[[ $# -ge 2 ]] || return 1means that unless there are at least 2 positional parameters given, the function returns immediately with exit status 1.
-> arguments data-type is not checked
Not automatically, no. Technically, all shell variables and environment variables are strings, so there are no data types.
You can always define a function that assigns the value of an integer expression to a variable, or returns nonzero if it is not possible. For example, if you want to evaluate any integer expressions,
function inteval () { [[ -n "$1" && $# -ge 2 ]] || return 2 declare -n retval="$1" shift 1 ( retval=$(($*)) ) 2>/dev/null || return 1 retval=$(($*)) return $? }For example,
inteval X 2*3+4 returns with success, with
X=10.
To verify a specific variable or value is an representable integer,
function isint () { [[ $# -eq 1 && $1 =~ ^[-+]?[0-9]+ ]] || return 1 ( tmp=$(($1)) && [[ "$tmp" == "${1#+}" ]] ) 2>/dev/null || return 2 return 0 }For example,
isint -254 returns with success, but
isint 0x254 with failure.
Similarly, a large enough integer in magnitude will overflow and therefore return with failure.
the integer data type is simulated by external tools
No, integer arithmetic is implemented within Bash itself, and is quite fast. All assignments of form
VAR=$((expression)) (or
VAR=$[expression]) will either assign an integer value of the expression to
VAR, or fail with an interpreter error.
I do prefer the
$[expression] form over
$((expression)), because there is a risk of confusing the latter with
$( (statement) ), which is replaced with the output of
statement.
It is true that Bash does not warn about integer arithmetic overflow. If you try e.g.
X=$[ 1208925819614629174706176 ]then
X will be assigned a zero, because the right hand evaluates to 2
80 which wraps to zero. Then again, C behaves the same.
-> compare two numbers is ugly, and too error prone
Ugly is in the eye of the beholder.
As to error prone, not so, when one uses the
-lt,
-le,
-eq,
-ne,
-ge, and
-gt arithmetic comparison operators in
[ expression and
[[ expression ]] expressions.
<,
<=,
==,
!=,
>=, and
> are
lexicographic comparisons in
[[ expression ]], not arithmetic comparisons.
=~ is a POSIX extended regular expression (string) match operator.