Это, кажется, работает, хотя это кажется нелогичным, что http://us.php.net/date документы спецификатор микросекунды все же действительно не поддерживает его:
function getTimestamp()
{
return date("Y-m-d\TH:i:s") . substr((string)microtime(), 1, 8);
}
Вы можете довольно легко выполнить параллелизм конвейерного типа в Erlang. трубопроводы - как насчет "gzcat" foo.tar.gz | tar xf - "? Вы не можете знали это, но оболочка запускаем распаковку и распаковываем в parallel - стандартный ввод, читаемый в tar, просто блоки, пока данные не будут отправлены на стандартный вывод gzcat.
Многие задачи можно выразить с точки зрения трубопроводов, и если вы можете сделай это, затем получи некоторый уровень распараллеливание просто с Дэвидом Вспомогательный код King (даже в erlang узлы, т.е. машины):
конвейер: запуск ([конвейер: генератор (BigList),
{filter, fun some_filter / 1},
{map, fun_some_map / 1},
{generic, fun some_complex_function / 2},
весело some_more_complicated_function / 1,
забавный конвейер: собирать / 1]).
В основном то, что он здесь делает, составление списка шагов - каждый шаг внедряется в удовольствие, которое принимает в качестве входных данных все предыдущие пошаговые выходы (развлечения могут быть даже определен встроенным конечно). Пойти проверить из записи в блоге Дэвида для код и более подробное объяснение.
Objective-C имеет класс NSPipe . Я использую его довольно часто.
Я думаю, что основная причина заключается в том, что C # и Java обычно используются для создания более монолитных систем. В культурном отношении просто не принято хотеть делать что-то похожее на конвейер - вы просто заставляете свое приложение реализовывать необходимые функции. Идея создания множества простых инструментов с последующим их склеиванием произвольным образом просто не распространена в этих контекстах.
Если вы посмотрите на некоторые языки сценариев, такие как Python и Ruby, есть несколько довольно хороших инструментов для выполнения подобных задач из этих скриптов. Посмотрите, например, на модуль подпроцесса Python, который позволяет делать такие вещи, как:
proc = subprocess.Popen('cat -',
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,)
stdout_value = proc.communicate('through stdin to stdout')[0]
print '\tpass through:', stdout_value
Вы можете найти что-то вроде каналов в C # и Java, например, где вы берете поток подключения и помещаете его в конструктор другого потока подключения.
Итак. , у вас есть в Java:
new BufferedReader(new InputStreamReader(System.in));
Возможно, вы захотите найти цепочки входных или выходных потоков.
Благодаря всем отличным ответам и комментариям, вот краткое изложение того, что я узнал:
Оказывается, существует целая парадигма, связанная с тем, что меня интересует, называется Программирование на основе потоков . Хорошим примером языка, разработанного специально для потокового программирования, являются конвейеры Хартмана . Конвейеры Hartamnn обобщают идею потоков и конвейеров, используемых в Unix и других ОС, что позволяет использовать несколько входных и выходных потоков (а не только один входной поток и два выходных потока). Erlang содержит мощные абстракции, которые позволяют легко выражать параллельные процессы способом, напоминающим конвейеры. Java предоставляет PipedInputStream и PipedOutputStream , которые можно использовать с потоками для достижения тех же абстракций более подробным образом.
Обычно он вам просто не нужен, и программы работают быстрее без него.
В основном конвейер - это шаблон потребитель / производитель. И написать этих потребителей и производителей несложно, потому что они не передают много данных.
Мне очень понравилось создавать конвейерные функции на Python. У меня есть библиотека, которую я написал, я поместил ее содержимое и пробный прогон сюда . Лучше всего мне подошла обработка XML, описанная в этой статье Википедии .
Ха-ха! Благодаря моему гугл-фу я нашел такой ответ , который может вас заинтересовать. По сути, ответ идет против аргумента «не перегружайте операторы, если вам действительно не нужно» путем перегрузки оператора побитового ИЛИ для обеспечения конвейерной обработки, подобной оболочке, в результате чего код Python выглядит следующим образом:
for i in xrange(2,100) | sieve(2) | sieve(3) | sieve(5) | sieve(7):
print i
Что он делает, концептуально , является конвейером списка чисел от 2 до 99 ( xrange (2, 100)
) через функцию сита, которая удаляет кратные заданного числа (сначала 2, затем 3, затем 5, затем 7). Это начало генератора простых чисел, хотя создание простых чисел таким способом - довольно плохая идея. Но мы можем сделать больше:
for i in xrange(2,100) | strify() | startswith(5):
print i
Это генерирует диапазон, затем преобразует их все из чисел в строки, а затем отфильтровывает все, что не начинается с 5.
В сообщении показан базовый родительский класс, который позволяет вам перегрузить два метода, map
и filter
, чтобы описать поведение вашего канала. Так strify ()
использует метод map
для преобразования всего в строку, а sieve ()
использует метод filter
для отсеивания вещи, которые не кратны числу.
Это довольно умно, хотя, возможно, это означает, что он не очень питонический, но он демонстрирует, что вам нужно, и технику для этого, которая, вероятно, может быть легко применена к другим языкам.