Discussion:
[Help-bash] which paradigms does bash support
Greg Wooledge
2015-01-26 13:43:31 UTC
Permalink
As a programming language which paradigms does bash support. Declarative, procedural, imperative?
This belongs on help-***@gnu.org so I'm Cc'ing that address.

Shell scripts are procedural.

The control structures are while loops, for loops, procedure calls
(which are called "functions" but aren't really), if statements, and
case statements. There are no gotos, and nothing analogous.

Examples:

# This is a "function". It can only return a value that indicates whether
# it succeeded (0), or failed (1-255). There is no way to pass variables
# "by reference". The arguments are just strings. Functions may be
# recursive, and local variables are supported. Variable scoping is
# dynamic.

# The biggest issue with bash's functions is how to get information out
# of them. Since there is no pass-by-reference, and the return value
# is just a success indicator, you're stuck with writing the results to
# a global variable (or higher-scope variable), writing the results to
# a file on disk, or writing the results to stdout and making the caller
# "capture" it with a command substitution. The last choice is very
# common, but it forces bash to fork() and run the function in a subshell,
# so performance is abysmal, and the subshell prevents other side effects
# from occurring (which may be desirable or not).

process() {
local var1 var2
some code that uses argument "$1"
return 0
}

# A common while loop.

while read line; do
process "$line"
done < "$inputfile"

# An array declaration, and a for loop.

hosts=(ares athena hermes zeus)
for host in "${hosts[@]}"; do
ssh "$host" some command
done

# An if statement.

if grep -q "$keyword" "$inputfile"; then
echo "Found $keyword in $inputfile"
fi

# A case statement.

case "$inputfile" in
*.gif | *.jpg | *.png) xv "$inputfile" ;;
*.mp3 | *.ogg | *.wav) mplayer "$inputfile" ;;
esac
Pádraig Brady
2015-01-26 16:05:16 UTC
Permalink
Post by Greg Wooledge
As a programming language which paradigms does bash support. Declarative, procedural, imperative?
Shell scripts are procedural.
It should be noted that shell programming is closely related to functional programming.
I.E. functional programming maintains no external state and provides
data flow synchronisation in the language. This maps closely to the
UNIX filter idea; data flows in and out, with no side affects to the system.

By trying to use filters and pipes instead of procedural shell statements,
you get the advantage of using compiled code, and implicit multicore support etc.

cheers,
Pádraig.
Garreau\, Alexandre
2018-03-13 15:52:33 UTC
Permalink
Post by Pádraig Brady
It should be noted that shell programming is closely related to
functional programming. […]
By trying to use filters and pipes instead of procedural shell
statements, you get the advantage of using compiled code, and implicit
multicore support etc.
Sorry being much late to react, I don’t always check the lists (much
content and no such time ^^') but this thread triggered me in interest.

I, for instance, usually write bash in a pretty lispy style: kebab-case
(instead of the snake_case I more often observed in big system
shellscripts) and parenthesis instead of pipes (`fun-a $(fun-b
$(fun-c))` instead of `fun1 | fun2 | fun3`), maybe due to the effect
lisp had on me (as I learned it pretty much at the same time as advanced
bash), or maybe because while the later style is more linear thus more
simple for simple and linear things, the former fits better to an
arborescent way of expressing things (which I find more natural).

I’m currently trying to learn how to take advantage of streams (not
normal pipes or std(in|out|err) but arbitrary user-defined ones (>&3 and
3<&1 for instance), named/bash-defined ones (necessarily in the other
order it seems, there: {var}<&1 then >&${var}), process substitution
(<(cmd) and >(cmd), sadly lacking a <>(cmd), or I maybe misunderstood
the previous ones), and named pipes) to achieve that form of
arborescence while saving file descriptors (and avoiding opening and
closing a file again and again) and potentially making some
parallelization, but using a lot of streams (as seeable by my preceding
mail on this list) seems to introduce less readability and really little
way of doing arborescent work (I initially hoped for something near
“tee” but more complex, without intermediary files, and builtin).

But then I wonder, command subtitutions execute sequentially (one arg
evaluated at a time) instead of parallely as pipes, but it seems they do
even when suffixing them with “&” anyway… is there any way of
reproducing this arborescent lispy style of programming while keeping
this form of parallelization bash usually simplify by putting forks all
the way?
Tadeus Prastowo
2018-03-13 16:18:13 UTC
Permalink
On Tue, Mar 13, 2018 at 4:52 PM, Garreau, Alexandre
<galex-***@galex-713.eu> wrote:

[...]
Post by Garreau\, Alexandre
I’m currently trying to learn how to take advantage of streams (not
normal pipes or std(in|out|err) but arbitrary user-defined ones (>&3 and
3<&1 for instance), named/bash-defined ones (necessarily in the other
order it seems, there: {var}<&1 then >&${var}), process substitution
(<(cmd) and >(cmd), sadly lacking a <>(cmd), or I maybe misunderstood
the previous ones), and named pipes) to achieve that form of
arborescence while saving file descriptors (and avoiding opening and
closing a file again and again) and potentially making some
parallelization, but using a lot of streams (as seeable by my preceding
mail on this list) seems to introduce less readability and really little
way of doing arborescent work (I initially hoped for something near
“tee” but more complex, without intermediary files, and builtin).
But then I wonder, command subtitutions execute sequentially (one arg
evaluated at a time) instead of parallely as pipes, but it seems they do
even when suffixing them with “&” anyway… is there any way of
reproducing this arborescent lispy style of programming while keeping
this form of parallelization bash usually simplify by putting forks all
the way?
Perhaps this post would give you a partial answer:
https://unix.stackexchange.com/a/86372

--
Best regards,
Tadeus
Pierre Gaston
2018-03-14 07:22:45 UTC
Permalink
Post by Greg Wooledge
As a programming language which paradigms does bash support.
Declarative, procedural, imperative?
Post by Greg Wooledge
Shell scripts are procedural.
It should be noted that shell programming is closely related to functional programming.
I.E. functional programming maintains no external state and provides
data flow synchronisation in the language. This maps closely to the
UNIX filter idea; data flows in and out, with no side affects to the system.
By trying to use filters and pipes instead of procedural shell statements,
you get the advantage of using compiled code, and implicit multicore support etc.
cheers,
Pádraig.
Though I understand what you say and maybe you can see pipes as something
functional(ish),
I believe this is a misleading statement as imo shell scripting is not even
close to be functional in any kind of way.
Pádraig Brady
2018-03-14 19:56:51 UTC
Permalink
Post by Pierre Gaston
Post by Greg Wooledge
As a programming language which paradigms does bash support.
Declarative, procedural, imperative?
Post by Greg Wooledge
Shell scripts are procedural.
It should be noted that shell programming is closely related to functional programming.
I.E. functional programming maintains no external state and provides
data flow synchronisation in the language. This maps closely to the
UNIX filter idea; data flows in and out, with no side affects to the system.
By trying to use filters and pipes instead of procedural shell statements,
you get the advantage of using compiled code, and implicit multicore support etc.
cheers,
Pádraig.
Though I understand what you say and maybe you can see pipes as something
functional(ish),
I believe this is a misleading statement as imo shell scripting is not even
close to be functional in any kind of way.
Well my point was, filters and pipes are similar to functional programming.
IMHO shell scripts are generally better when using these concepts when possible,
rather than using procedural shell statements.

See also http://okmij.org/ftp/Computation/monadic-shell.html

cheers,
Pádraig
Andy Chu
2018-03-14 21:11:32 UTC
Permalink
I think the best way to ground this type of discussion is to show code. I
wrote a couple articles last year that show shell's relation to the broader
subject of programming paradigms, with example code:

Shell Has a Forth-like Quality
http://www.oilshell.org/blog/2017/01/13.html

Pipelines Support Vectorized, Point-Free, and Imperative Style
http://www.oilshell.org/blog/2017/01/15.html

Andy
Post by Pádraig Brady
Post by Pierre Gaston
Post by Greg Wooledge
As a programming language which paradigms does bash support.
Declarative, procedural, imperative?
Post by Greg Wooledge
Shell scripts are procedural.
It should be noted that shell programming is closely related to
functional
Post by Pierre Gaston
programming.
I.E. functional programming maintains no external state and provides
data flow synchronisation in the language. This maps closely to the
UNIX filter idea; data flows in and out, with no side affects to the system.
By trying to use filters and pipes instead of procedural shell
statements,
Post by Pierre Gaston
you get the advantage of using compiled code, and implicit multicore support etc.
cheers,
Pádraig.
Though I understand what you say and maybe you can see pipes as something
functional(ish),
I believe this is a misleading statement as imo shell scripting is not
even
Post by Pierre Gaston
close to be functional in any kind of way.
Well my point was, filters and pipes are similar to functional programming.
IMHO shell scripts are generally better when using these concepts when possible,
rather than using procedural shell statements.
See also http://okmij.org/ftp/Computation/monadic-shell.html
cheers,
Pádraig
Greg Wooledge
2018-03-15 12:12:27 UTC
Permalink
Post by Andy Chu
Shell Has a Forth-like Quality
http://www.oilshell.org/blog/2017/01/13.html
Similar to http://mywiki.wooledge.org/WrapperScript :)
Post by Andy Chu
Pipelines Support Vectorized, Point-Free, and Imperative Style
http://www.oilshell.org/blog/2017/01/15.html
There are certainly some kinds of problems that are well suited
to the "long pipeline of filters" approach. And some that are not.

It's important to be familiar with multiple approaches (styles, tool
sets), so that you can select the best one for a given problem.

Dieter Van Eessen
2018-03-15 10:06:01 UTC
Permalink
Hello,

From notes from my perspective:
- using the entire filesystem = 'maintaining state' : files ARE state.
- all variables (commands and files) are accessible in global scope through
absolute path: I think of (command line) programs as functions available in
global scope
- all variables(scripts and files) are accessible in local scope through
relative path.
- pipes do provide 'functional glue'
- It really depends on how YOU use your shell, it provides NO constraints
(gift and a curse)

I'm exited to hear your comments on this point of view :)

kind regards,
Dieter
Post by Pádraig Brady
Post by Pierre Gaston
Post by Greg Wooledge
As a programming language which paradigms does bash support.
Declarative, procedural, imperative?
Post by Greg Wooledge
Shell scripts are procedural.
It should be noted that shell programming is closely related to
functional
Post by Pierre Gaston
programming.
I.E. functional programming maintains no external state and provides
data flow synchronisation in the language. This maps closely to the
UNIX filter idea; data flows in and out, with no side affects to the system.
By trying to use filters and pipes instead of procedural shell
statements,
Post by Pierre Gaston
you get the advantage of using compiled code, and implicit multicore support etc.
cheers,
Pádraig.
Though I understand what you say and maybe you can see pipes as something
functional(ish),
I believe this is a misleading statement as imo shell scripting is not
even
Post by Pierre Gaston
close to be functional in any kind of way.
Well my point was, filters and pipes are similar to functional programming.
IMHO shell scripts are generally better when using these concepts when possible,
rather than using procedural shell statements.
See also http://okmij.org/ftp/Computation/monadic-shell.html
cheers,
Pádraig
Loading...