Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm (really) newbie to functional programming (in fact only had contact with it using python) but seems to be a good approach for some list-intensive tasks in a shell environment.

I'd love to do something like this:

$ [ git clone $host/$repo for repo in repo1 repo2 repo3 ]

Is there any Unix shell with these kind of feature? Or maybe some feature to allow easy shell access (commands, env/vars, readline, etc...) from within python (the idea is to use python's interactive interpreter as a replacement to bash).

EDIT:

Maybe a comparative example would clarify. Let's say I have a list composed of dir/file:

$ FILES=( build/project.rpm build/project.src.rpm )

And I want to do a really simple task: copy all files to dist/ AND install it in the system (it's part of a build process):

Using bash:

$ cp ${files[*]} dist/
$ cd dist && rpm -Uvh $(for f in ${files[*]}; do basename $f; done))

Using a "pythonic shell" approach (caution: this is imaginary code):

$ cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'

Can you see the difference ? THAT is what i'm talking about. How can not exits a shell with these kind of stuff build-in yet? It's a real pain to handle lists in shell, even its being a so common task: list of files, list of PIDs, list of everything.

And a really, really, important point: using syntax/tools/features everybody already knows: sh and python.

IPython seams to be on a good direction, but it's bloated: if var name starts with '$', it does this, if '$$' it does that. It's syntax is not "natural", so many rules and "workarounds" ([ ln.upper() for ln in !ls ] --> syntax error)

share|improve this question

migrated from stackoverflow.com Apr 18 '12 at 19:34

This question came from our site for professional and enthusiast programmers.

    
Somewhat related: github.com/amoffat/pbs –  Josh Lee Apr 18 '12 at 18:47
    

4 Answers 4

The standard Bourne-style shells (sh, bash, ksh, etc.) already let you do:

for repo in repo1 repo2 repo3 ; do git clone $host/$repo ; done

(Note the need for semicolons before do and done.) Additionally, in bash and other shells, if $repo only appears once in the command, you can write:

git clone $host/{repo1,repo2,repo3}
share|improve this answer
    
sure, and I do use it a lot. but what about other stuff, like lambda functions? –  Caruccio Apr 18 '12 at 18:57
4  
git clone $host/{repo1,repo2,repo3} doesn't do the same thing as the for loop; it invokes git clone once with three arguments. The fact that does essentially the same thing is an artifact of how git clone works; it doesn't necessarily apply to other commands. (Compare echo foo bar baz to echo foo; echo bar; echo baz, for example.) –  Keith Thompson Apr 18 '12 at 20:41

There's a Scheme Shell that's probably very close to what you're looking for. I haven't used it myself.

UPDATE :

I just installed and tried it myself. It appears that scsh is more of an interactive Scheme interpreter and scripting language than a really useful interactive shell. You can't just type

echo hello

the syntax appears to be

(run (echo hello))

and it took several minutes of Googling just to find that. The first example here is:

gunzip < paper.tex.gz | detex | spell | lpr -Ppulp &

which translates to:

(& (| (gunzip) (detex) (spell) (lpr -Ppulp)) (< paper.tex.gz))

but that doesn't tell you how to run a simple shell command.

This FAQ entry says:

4.6 Can I use scsh as an interactive shell?

Well, technically you can: just run the "scsh" command and you will enter a Scheme 48 session with all scsh functions available. However, this is definitely not suitable for interactive work: there is no command-line editing, no command-line history, no file/function name completion, no terse syntax, etc.

To alleviate these problems, Martin Gasbichler and Eric Knauel have written Commander S, which runs on top of scsh and provides a comfortable interactive environment. One of its novel features is that it can understand the output of many Unix commands, and allows the user to browse and manipulate it in useful ways. More information about Commander S can be found in the paper describing it: http://www-pu.informatik.uni-tuebingen.de/users/knauel/commander-s.pdf Instructions about how to obtain and install Commander S are available from the scsh Web site: http://www.scsh.net/resources/commander-s.html

So maybe that's the real answer.

share|improve this answer

Scheme Shell, scsh, is really good.

As Keith Thompson notes, it's not useful as an interactive shell (though Commander S looks like an interesting experiment). Instead, it's an excellent programming language for contexts where having all the POSIX bindings is useful -- that includes cases where you want to call other unix applications. A shell script of more than a few dozen lines will always feel like a hack, no matter how neatly you write sh; in contrast there's nothing stopping you writing significant programs using scsh.

scsh isn't very compact (brevity is both the strength and the weakness of sh-family languages), but it's powerful.

Because it's useful and practical for small and large tasks, scsh is incidentally a good way of getting to grips with a Scheme (although, if that happened to be your goal, you might as well go straight to Racket, these days).

The advantages of functional languages aren't just for list-intensive tasks (though because of their history, they tend to favour lists as a data structure) -- it's a really robust way to get programs written, once you drink the right kool-aid.

There is no meaningful sense in which the sh-style shells are functional, and Python is only functional in the marginal sense that it has a lambda function.

share|improve this answer

First, you should be using "${files[@]}" everywhere you have ${files[*]}. Otherwise spaces will mess you up.

The shell is pretty functional already; if you think in terms of text output being lists of lines, then grep is filter, xargs is map, etc. Pipes are very functional.

The shell is admittedly not the friendliest programming environment, but it's much more suited to interactive use than Python. And it has the very nice feature that the API and the UI are identical - learn both at once.

I don't understand why you find cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist' preferable to cp "${FILES[@]}" dist. The latter is much less typing.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.