18

Я (действительно) новичок в функциональном программировании (на самом деле имел дело только с ним с помощью Python), но, похоже, является хорошим подходом для некоторых задач с интенсивным списком в среде оболочки.

Я хотел бы сделать что-то вроде этого:

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

Есть ли оболочка Unix с такими функциями? Или, может быть, какая-то функция, позволяющая легкий доступ к оболочке (команды, env/vars, readline и т.д.) Изнутри python (идея состоит в том, чтобы использовать интерактивный интерпретатор python вместо замены bash).

РЕДАКТИРОВАТЬ:

Может быть, сравнительный пример уточнит. Допустим, у меня есть список, состоящий из dir/file:

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

И я хочу сделать действительно простую задачу: скопировать все файлы в dist/ и установить его в системе (это часть процесса сборки):

Используя bash:

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

Используя подход "pythonic shell" (осторожно: это воображаемый код):

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

Вы видите разницу? Вот о чем я говорю. Как не может выйти из оболочки с такими встроенными вещами? Работать со списками в оболочке очень сложно, даже если это такая распространенная задача: список файлов, список PID, список всего.

И действительно, очень важный момент: используя синтаксис / инструменты / функции, которые все уже знают: sh и python.

IPython выглядит хорошо, но он раздут: если имя переменной начинается с «$», он делает это, если «$$» это делает. Его синтаксис не является "естественным", поэтому существует много правил и "обходных путей" ([ ln.upper() for ln in !ls ] -> синтаксическая ошибка)

7 ответов7

9

Существует оболочка Scheme, которая, вероятно, очень близка к тому, что вы ищете. Я не использовал это сам.

ОБНОВИТЬ :

Я только что установил и попробовал это сам. Похоже, что scsh - больше интерактивный интерпретатор Scheme и язык сценариев, чем действительно полезная интерактивная оболочка. Вы не можете просто напечатать

echo hello

синтаксис выглядит так

(run (echo hello))

и потребовалось несколько минут, чтобы найти это. Первый пример здесь :

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

что переводится как:

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

но это не говорит вам, как запустить простую команду оболочки.

Эта запись часто задаваемых вопросов говорит:

4.6 Могу ли я использовать scsh в качестве интерактивной оболочки?

Ну, технически вы можете: просто запустите команду "scsh", и вы войдете в сеанс Scheme 48 со всеми доступными функциями scsh. Однако это определенно не подходит для интерактивной работы: нет редактирования командной строки, нет истории командной строки, нет завершения имени файла / функции, нет краткого синтаксиса и т.д.

Чтобы облегчить эти проблемы, Мартин Гасбихлер и Эрик Кнауэл написали Commander S, который работает поверх scsh и обеспечивает удобную интерактивную среду. Одна из его новых функций заключается в том, что он может понимать вывод многих команд Unix и позволяет пользователю просматривать и манипулировать им полезными способами. Более подробную информацию о Commander S можно найти в документе, описывающем его: http://www.deinprogramm.de/scheme-2005/05-knauel/05-knauel.pdf Инструкции о том, как получить и установить Commander S, можно найти в Веб-сайт scsh: http://www.scsh.net/resources/commander-s.html

Так что, возможно, это реальный ответ.

6

Стандартные оболочки Bourne-стиля (sh , bash , ksh и т.д.) Уже позволяют вам:

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

(Обратите внимание на необходимость точки с запятой, прежде чем do и done .) Кроме того, в bash и других оболочках, если $repo появляется только один раз в команде, вы можете написать:

git clone $host/{repo1,repo2,repo3}
5

В категории прямого ответа на вопрос есть оболочка ES, которая предназначена для функциональной замены Bash, Zsh и т.д.

Во-вторых, в категории, помогающей вам написать более функциональную стандартную оболочку, рассмотрите изучение техники pipemill:

who | while read username 
do
  cat <<EOF | grep $username
nic
mark
norman
keith
EOF
done | while read username
do
  echo "you have an answer on superuser.com" | mail -s "well done" $username
done

Первый цикл while является функциональным keep (передают только ненулевые значения, которые выходят из цикла), а второй - each (отображение только для побочных эффектов).

Это огромный импульс для fp в снарядах.

Можно выразить многие вещи в стиле fp в оболочке, это не так просто, как могло бы быть. Похоже, что делать лучшие оболочки не очень интересно, хотя мы все так часто их используем.

1

Схема Shell, scsh, действительно хороша.

Как отмечает Кит Томпсон, он не используется в качестве интерактивной оболочки (хотя Commander S выглядит как интересный эксперимент). Вместо этого это отличный язык программирования для контекстов, где полезно использовать все привязки POSIX, включая случаи, когда вы хотите вызывать другие приложения Unix. Сценарий оболочки, состоящий из нескольких десятков строк, всегда будет выглядеть как хак, независимо от того, насколько аккуратно вы напишите sh ; напротив, ничто не мешает вам писать важные программы с использованием scsh.

scsh не очень компактен (краткость - это сила и слабость языков семейства sh), но он мощный.

Поскольку он полезен и практичен для малых и больших задач, scsh - хороший способ справиться со Схемой (хотя, если это и стало вашей целью, в эти дни вы могли бы также пойти прямо в Racket).

Преимущества функциональных языков не только для задач, требующих большого количества списков (хотя из-за их истории они предпочитают списки в качестве структуры данных) - это действительно надежный способ написания программ, когда вы выпиваете правильный kool- помощь.

Нет никакого осмысленного смысла в том, что оболочки в стиле sh являются функциональными, а Python функционален только в предельном смысле, что у него есть лямбда-функция.

1

Во-первых, вы должны использовать "${files[@]}" везде, где у вас есть ${files[*]} . В противном случае пробелы запутают вас.

Оболочка уже довольно функциональна; если вы думаете, что с точки зрения вывода текста это списки строк, то grep - это filter , xargs - это map и т. д. Каналы очень функциональны.

Оболочка, по общему признанию, не самая дружественная среда программирования, но она гораздо больше подходит для интерактивного использования, чем Python. И у этого есть очень хорошая особенность, что API и интерфейс идентичны - изучите оба сразу.

Я не понимаю, почему вы находите cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist' предпочтительнее, чем cp "${FILES[@]}" dist , Последний гораздо меньше печатает.

1

Оболочки обязательно очень выразительны, а это значит, что вы добиваетесь большего с меньшим количеством линий, токенов и т.д.

Мы обычно делаем языки выразительными, проектируя их для специальных целей, таких как оболочки или DSL, такие как R, maple и т.д. И вы обнаружите относительно небольшую выразительность в большинстве языков общего назначения, таких как C, C++, Java и т.д.

Python, Perl, Ruby и т.д. Являются языками общего назначения, которые более выразительны в способах, аналогичных оболочкам, а также типизации утки. Таким образом, DSL привариваются к ним, аля Sage для математики. Не очень хорошо для реальных команд оболочки, хотя.

Схема не так уж и выразительна, даже когда вы строите DLS из-за всех круглых скобок.

Однако существуют такие функциональные языки, как Haskell, с огромной выразительностью и большими возможностями для создания DSL. Интересными усилиями по созданию панциря на Хаскелле являются черепаха и ракушка.

На практике из-за мощной, но строгой системы типов Haskell есть кривая обучения с инструментами усилий, но они показывают значительные перспективы.

0

Не знаю, что он "функциональный", но есть и rc, о котором упоминается в scsh paper . Это предшественник эс.

На Linux Mint (и, возможно, Debian, Ubuntu ...) вы можете попробовать это с

sudo apt-get install rc
man rc
rc

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .