Оказывается, это не настолько твердо, как Вы могли бы думать. Синтаксис ужасен как черт, но пакетный синтаксис на самом деле способен к некоторым удивительным вещам, включая рекурсию, локальные переменные и некоторый удивительно сложный парсинг строк. Не понимайте меня превратно, это - ужасный язык, но к моему удивлению, этому не полностью наносят вред. Я не думаю, что узнал что-либо о quicksort, но я узнал много о пакетных файлах!
В любом случае вот quicksort в пакетном файле - и я надеюсь, что у Вас есть столько забавы, пытающейся понять причудливый синтаксис при чтении его, сколько я сделал при записи этого.:-)
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
call :qSort %*
for %%i in (%return%) do set results=!results! %%i
echo Sorted result: %results%
ENDLOCAL
goto :eof
:qSort
SETLOCAL
set list=%*
set size=0
set less=
set greater=
for %%i in (%*) do set /a size=size+1
if %size% LEQ 1 ENDLOCAL & set return=%list% & goto :eof
for /f "tokens=2* delims== " %%i in ('set list') do set p=%%i & set body=%%j
for %%x in (%body%) do (if %%x LEQ %p% (set less=%%x !less!) else (set greater=%%x !greater!))
call :qSort %less%
set sorted=%return%
call :qSort %greater%
set sorted=%sorted% %p% %return%
ENDLOCAL & set return=%sorted%
goto :eof
Назовите его путем предоставления ему ряда чисел к виду на командной строке, разделенной пробелами. Пример:
C:\dev\sorting>qsort.bat 1 3 5 1 12 3 47 3
Sorted result: 1 1 3 3 3 5 12 47
Код является чем-то вроде боли для понимания. Это - в основном стандартный quicksort. Ключевые биты - то, что мы храним числа в строке - массив бедного человека. Второе для цикла довольно неясно, он в основном разделяет массив на голову (первый элемент) и хвост (все другие элементы). Haskell делает это с нотацией x:xs, но пакетные файлы делают это с для цикла, названного с переключателем/f. Почему? Почему нет?
SETLOCAL и вызовы ENDLOCAL позволяют нам сделать локальные переменные - вид. SETLOCAL дает нам полную копию исходных переменных, но все изменения полностью вытерты, когда мы называем ENDLOCAL, что означает, что Вы не можете даже общаться с функцией вызова, использующей globals. Это объясняет ужасный "ENDLOCAL и возврат набора =, % отсортировал %" синтаксис, который на самом деле работает несмотря на то, на что указала бы логика. Когда строка выполняется, отсортированная переменная не была вытерта, потому что строка еще не была выполнена - затем впоследствии, возвращаемая переменная не вытерта, потому что строка была уже выполнена. Логичный!
Кроме того, забавно, Вы в основном не можете использовать переменные в для цикла, потому что они не могут измениться - который удаляет большую часть точки наличия для цикла. Обходное решение должно установить ENABLEDELAYEDEXPANSION, который работает, но делает синтаксис еще более ужасным, чем нормальный. Заметьте, что у нас теперь есть соединение переменных, на которые ссылается только их имя, путем добавления префикса их единственный %, путем добавления префикса их два %, путем обертывания их в %, или путем обертывания их в!. И эти различные способы сослаться на переменные являются почти полностью НЕ взаимозаменяемыми!
Кроме этого, должно быть относительно легко понять!