diferencia entre "función foo() {}" y "foo() {}"

diferencia entre "función foo() {}" y "foo() {}"

Puedo definir bashfunciones usando u omitiendo la functionpalabra clave. ¿Hay alguna diferencia?

#!/bin/bash

function foo() {
  echo "foo"
}

bar() {
  echo "bar"
}

foo

bar

Ambas llamadas a funciones footienen baréxito y no veo ninguna diferencia. Entonces me pregunto si es solo para mejorar la legibilidad o hay algo que me falta...

Por cierto, en otros shells como dash( /bin/shtiene un enlace simbólico dashen Debian/ubuntu), falla al usar la functionpalabra clave.

Respuesta1

La razón por la que existen dos sintaxis diferentes es histórica. La functionpalabra clave vino deksh. La sintaxis inspirada en C ()provino delconcha de bourne.POSIXestandariza sólo la foo ()sintaxis de Bourne. Bash y zsh admiten ambos, así como el híbrido function foo () { … }. Excepto en ATT ksh, la función resultante es exactamente la misma.

Tenga cuidado con un problema con la ()sintaxis: el nombre de la función está sujeto a expansión de alias.

alias f=g
f () { echo foo; }
type f               # f is an alias for g
type g               # g is a shell function
f                    # alias f → function g → print foo
\f                   # no alias lookup → f: not found
g                    # function g

En ATT ksh (pero no en pdksh y sus descendientes como mksh), existen algunas diferencias entre las funciones definidas por functiony las funciones definidas con la sintaxis Bourne/POSIX. En las funciones definidas por function, la typesetpalabra clave declara una variable local: una vez que la función sale, el valor de la variable se restablece al que tenía antes de ingresar a la función. Con la sintaxis clásica, las variables tienen un alcance global, ya sea que las uses typeseto no.

$ ksh -c 'a=global; f () { typeset a=local; }; f; echo $a'
local
$ ksh -c 'a=global; function f { typeset a=local; }; f; echo $a'
global

Otra diferencia en ksh es que las funciones definidas con la functionpalabra clave tienen su propio contexto de captura. Las trampas definidas fuera de la función se ignoran mientras se ejecuta la función, y los errores fatales dentro de la función salen solo de la función y no de todo el script. Además, $0es el nombre de la función en una función definida por functionpero el nombre del script en una función definida con ().

Pdksh no emula ATT ksh. En pdksh, typesetcrea variables de ámbito local independientemente de la función y no hay trampas locales (aunque su uso functionsupone algunas diferencias menores; consulte la página de manual para obtener más detalles).

Bash y zsh introdujeron la functionpalabra clave para compatibilidad con ksh. Sin embargo, en estos shells function foo { … }y foo () { … }son estrictamente idénticos, al igual que las extensiones bash y zsh function foo () { … }(excepto por la posible expansión del alias al analizar la definición, como se explicó anteriormente). La typesetpalabra clave siempre declara variables locales (excepto con, -gpor supuesto), y las trampas no son locales (puede obtener trampas locales en zsh configurando la local_trapsopción).

Respuesta2

No hay diferencia AFAIK, aparte del hecho de que la segunda versión es más portátil.

Respuesta3

foo() any-command

es la sintaxis de Bourne compatible con cualquier shell similar a Bourne pero bash,yashy versiones recientes de posh(que solo admiten comandos compuestos). (Sin embargo, las implementaciones de Bourne Shell y AT&T kshno son compatibles foo() any-command > redirectionsa menos que any-commandsea un comando compuesto).

foo() any-compound-command

(ejemplos de comandos compuestos: { cmd; }, for i do echo "$i"; done, (cmd)... siendo el más utilizado { ...; })

es la sintaxis POSIX compatible con cualquier shell tipo Bourne y la que generalmente desea utilizar.

function foo { ...; }

es la sintaxis del shell Korn, que es anterior a la sintaxis de Bourne. Utilice este solo si escribe específicamente para la implementación de AT&T del shell Korn y necesita el tratamiento específico que recibe allí. Esa sintaxis no es POSIX, pero es compatible con bash, yashy zshpor compatibilidad con el shell Korn, aunque esos shells (y las pdkshvariantes basadas en -del shell Korn) no la tratan de manera diferente a la sintaxis estándar.

function foo () { ...; }

es la sintaxis deNoconcha yNo debería ser usado. Resulta que solo es compatible por accidente con bash, y las variantes basadas del shell Korn. Por cierto, también es la sintaxis de la función.yashzshpdkshawk

Si seguimos bajando por la lista esotérica,

function foo() other-compound-command

(como function foo() (subshell)o function foo() for i do; ... done) es aún peor. Es compatible con bash, yashy zsh, pero no con ksh, ni siquiera con las pdkshvariantes basadas en -.

Mientras:

function foo() simple command

sólo es compatible con zsh.

foo bar() any-command

O incluso:

$function_list() any-command

Definir varias funciones a la vez sólo es compatible conzsh

function { body; } args
() any-compound-command args

cuales sonfunción anónimalas invocaciones, solo son compatibles con zshtambién.

Respuesta4

Varios otros ya han respondido correctamente, pero aquí está mi sinopsis concisa:

La segunda versión es portátil y probablemente funcione con muchos shells estándar (particularmente POSIX).

La primera versión funcionará solo con bash, pero puede omitir los paréntesis que siguen al nombre de la función.

De lo contrario, representan entidades idénticas después de que bash las interprete.

información relacionada