Logo    
Деловая газета CitCity.ru CITKIT.ru - все об Open Source Форумы Все публикации Учебный центр Курилка
CitForum    CITForum на CD    Подписка на новости портала Море(!) аналитической информации! :: CITFORUM.RU
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

21.01.2017

Google
WWW CITForum.ru
С Новым годом!
2003 г

И опять о функциональном программировании на Python

David Mertz, Ph.D., Applied Metaphysician, Gnosis Software, Inc
Перевод: Intersoft Lab

Предыдущие статьи коснулись основных понятий функционального программирования (ФП). Эта статья продолжит обсуждение, иллюстрируя дополнительные возможности, главным образом реализованные в библиотеке Xoltar Toolkit: частичное вычисление функций (Currying, карринг), функции высшего порядка (higher-order functions) и другие концепции.

Что такое python?

Python - свободно доступный, интерпретируемый язык программирования высокого уровня, разработанный Гвидо ван Россумом (Guido van Rossum). Он объединяет ясный синтаксис с мощной (но необязательно) объектно-ориентированной семантикой. Python может быть установлен на любой платформе и обеспечивает прекрасную совместимость при переходе с одной платформы на другую.

Связывание выражений

Недовольный полурешениями, один из читателей - Ричарда Дейвис (Richard Davies) - поднял вопрос, можем ли мы целиком переместить связывания в отдельные выражения. Давайте попытаемся понять, зачем нам может этого захотеться, а также продемонстрируем замечательно элегантный способ этого добиться, предоставленный участником comp.lang.python.

Давайте сначала вспомним о классе Bindings, определенном в модуле functional. Используя свойства этого класса, мы смогли гарантировать, что отдельное имя имеет единственное значение в пределах области данного блока:

    #------- Python FP session with guarded rebinding -------#
          >>> from functional import *
          >>> let = Bindings()
          >>> let.car = lambda lst: lst[0]
          >>> let.car = lambda lst: lst[2]
          Traceback (innermost last):
            File "", line 1, in ?
            File "d:\tools\functional.py", line 976, in __setattr__
              raise BindingError, "Binding '%s' cannot be modified." % name
          functional.BindingError:  Binding 'car' cannot be modified.
          >>> let.car(range(10))
          0

С помощью класса Bindings нам удалось достичь желаемого результата в пределах модуля или функции, но в отношении отдельного выражения мы бессильны. Тем не менее, для семейства ML-языков вполне естественно создавать связывания в пределах отдельного выражения:

    #-------- Haskell expression-level name bindings --------#
          -- car (x:xs) = x  -- *could* create module-level binding
          list_of_list = [[1,2,3],[4,5,6],[7,8,9]]
          -- 'where' clause for expression-level binding
          firsts1 = [car x | x <- list_of_list] where car (x:xs) = x
          -- 'let' clause for expression-level binding
          firsts2 = let car (x:xs) = x in [car x | x <- list_of_list]
          -- more idiomatic higher-order 'map' technique
          firsts3 = map car list_of_list where car (x:xs) = x
          -- Result: firsts1 == firsts2 == firsts3 == [1,4,7]

Грэг Эвинг (Greg Ewing) заметил, что мы можем достичь того же эффекта, воспользовавшись списочными встраиваниями Python  (list comprehensions); мы даже можем сделать это почти столь же ясным способом, как в Haskell:

    #------ Python 2.0+ expression-level name bindings ------#
          >>> list_of_list = [[1,2,3],[4,5,6],[7,8,9]]
          >>> [car_x for x in list_of_list for car_x in (x[0],)]
          [1, 4, 7]

Этот прием - размещение выражения внутри одноэлементного кортежа в списочном встраивании - не позволяет использовать связывание на уровне выражений с функциями высшего порядка. Для использования таких функций мы все еще должны использовать область блока:

     #------- Python block-level bindings with 'map()' -------#
          >>> list_of_list = [[1,2,3],[4,5,6],[7,8,9]]
          >>> let = Bindings()
          >>> let.car = lambda l: l[0]
          >>> map(let.car,list_of_list)
          [1, 4, 7]

Неплохо, хотя если мы хотим использовать map(), область связывания остается несколько шире, чем мы того хотели. Тем не менее, можно уговорить списочное встраивание делать для нас связывание имен, даже если список - не то, что нам нужно в конечном счете:

          #---- "Stepping down" from Python list-comprehension ----#
          # Compare Haskell expression:
          # result = func car_car
          #          where
          #              car (x:xs) = x
          #              car_car = car (car list_of_list)
          #              func x = x + x^2
          >>> [func for x in list_of_list
          ...       for car in (x[0],)
          ...       for func in (car+car**2,)][0]
          2

В этом примере мы произвели арифметическое действие над первым элементом первого элемента списка list_of_list и одновременно поименовали это действие (но только в области объемлющего выражения). В качестве "оптимизации" можно посоветовать создавать список длиной не более одного элемента, поскольку с помощью индекса [0] в конце выражения выбираем только первый элемент:

    #---- Efficient stepping down from list-comprehension ---#
          >>> [func for x in list_of_list[:1]
          ...       for car in (x[0],)
          ...       for func in (car+car**2,)][0]       2

Функции высшего порядка: частичное вычисление функций - карринг[1] (currying)

Три наиболее общих функций высшего порядка встроены в Python: map(), reduce() и filter(). Эти функции используют в качестве (некоторых) своих параметров другие функции - вот почему мы называем их функциями высшего порядка. Другие функции высшего порядка (но не эти три) возвращают объекты-функции (function objects).

Python всегда предоставлял программистам возможность создавать свои собственные функции высшего порядка благодаря полноправному статусу функций как объектов. Ниже в качестве иллюстрации приведен простой пример:

          #----------- Trivial Python function factory ------------#
          >>> def foo_factory():
          ...     def foo():
          ...         print "Foo function from factory"
          ...     return foo
         ...
          >>> f = foo_factory()
          >>> f()
          Foo function from factory

Программа Xoltar Toolkit, о которой я упоминал в предыдущих статьях, содержит замечательный набор функций высшего порядка. Большинство этих функций, предоставляемых модулем functional, имеются во множестве традиционных функциональных языках программирования, и их полезность проверена многолетним использованием. Пожалуй, наиболее известная и важная функция высшего порядка традиционно называется curry(). Она названа в честь логика Хаскелла Карри (Haskell Curry), чьим именем назван уже упоминавшийся язык программирования. В основе карринга лежит допущение о том, что (почти) любую функцию можно рассматривать как частично вычисляемую функцию одного аргумента. Для того, чтобы эта идея работала, необходимо чтобы значение, возвращаемое  функцией, само могло быть функцией, но возвращаемые функции должны быть уже или ближе к завершению . Этот механизм подобен замыканию, о котором я рассказывал в предыдущей статье - каждый вызов каррированой функции добавляет больше данных, необходимых для  окончательного вычисления (данные прикрепляются к процедуре). Проиллюстрируем сначала карринг очень простым примером на Haskell, а затем повторим тот же пример на Python с помощью модуля functional:

    #------------- Currying a Haskell computation -----------#
          computation a b c d = (a + b^2+ c^3 + d^4)
          check = 1 + 2^2 + 3^3 + 5^4
          fillOne   = computation 1  -- specify "a"
          fillTwo   = fillOne 2      -- specify "b"
          fillThree = fillTwo 3      -- specify "c"
          answer    = fillThree 5    -- specify "d"
          -- Result: check == answer == 657

А теперь на Python:

    #------------- Currying a Python computation ------------#
          >>> from functional import curry
          >>> computation = lambda a,b,c,d: (a + b**2 + c**3 + d**4)
          >>> computation(1,2,3,5)
          657
          >>> fillZero  = curry(computation)
          >>> fillOne   = fillZero(1)   # specify "a"
          >>> fillTwo   = fillOne(2)    # specify "b"
          >>> fillThree = fillTwo(3)    # specify "c"
          >>> answer    = fillThree(5)  # specify "d"
          >>> answer
          657

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

    #------------ Python curried tax calculations -----------#
          from functional import *
          taxcalc = lambda income,rate,deduct: (income-(deduct))*rate
          taxCurry = curry(taxcalc)
          taxCurry = taxCurry(50000)
          taxCurry = taxCurry(0.30)
          taxCurry = taxCurry(10000)
          print "Curried taxes due =",taxCurry
          print "Curried expression taxes due =", \
                curry(taxcalc)(50000)(0.30)(10000)

В отличие от замыкания, при использовании curry( ) необходимо заполнять параметры в определенном порядке (слева направо). Но заметьте, в модуль functional также включен класс rcurry(), для которого отсчет начинается с другого конца (справа налево).

Обратите внимание на второй оператор print в этом примере - с одной стороны, это всего лишь тривиальное синтаксическое изменение - можно было бы просто вызвать taxcalc(50000,0.30,10000). Но с другой стороны, благодаря этому становится понятным идея о том, что каждая функция может быть функцией всего одного аргумента - весьма неожиданная идея для тех, кто с эти незнаком.

Другие функции высшего порядка

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

По большей части функции высшего порядка ведут себя как "усовершенствованные" версии стандартных функций map(), filter() и reduce(). В большинстве случаев они действуют согласно следующему правилу: "принять функцию или функции и некоторые списки в качестве параметров, затем применить функцию (функции) к списку параметров". Это правило предоставляет потрясающие возможности для программирования. Другой принцип "принять набор функций и создать функцию, комбинирующую их функциональность". И опять-таки, возможны многочисленные вариации. Давайте взглянем, что предоставляет functional.

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

    #---- Sequential calls to functions (with same args) ----#
          >>> def a(x):
          ...     print x,
          ...     return "a"
          ...
          >>> def b(x):
          ...     print x*2,
          ...     return "b"
          ...
          >>> def c(x):
          ...     print x*3,
          ...     return "c"
          ...
          >>> r = also(a,b,c)
          >>> r
         
          >>> r(5)
          5 10 15
          'a'
          >>> sequential([a,b,c],main=c)('x')
          x xx xxx
          'c'

Функции disjoin() и conjoin()  схожи с sequential() и also() в том смысле, что они также создают новые функции, которые применяют параметр(ы)  к нескольким составляющим функциям. Но disjoin() выясняет, возвращает ли хотя бы одна из составляющих функций "истину" (true), а conjoin()  выясняет, возвращают ли все функции "истину". При этом, когда это возможно, логика "короткого замыкания"[2], поэтому при их вызове часть побочных эффектов может не проявиться. joinfuncs() похожа на also(), но, в отличие от нее, возвращает кортеж результатов составляющих функций, а не выбирает одно значение.

В то время как вышеуказанные функции вызывают много функций с одинаковыми параметрами, функции any(), all() и none_of() позволяют вызывать одну и ту же функцию для каждого значения из списка. В общем случае они подобны встроенным функциям map(), filter() и reduce(). Но, в отличие от последних, эти функции задают булевы (логические) вопросы касательно набора возвращаемых величин. Например,

    #--------- Ask about collections of return values -------#
          >>> from functional import *
          >>> isEven = lambda n: (n%2 == 0)
          >>> any([1,3,5,8], isEven)
          1
          >>> any([1,3,5,7], isEven)
          0
          >>> none_of([1,3,5,7], isEven)
          1
          >>> all([2,4,6,8], isEven)
          1
          >>> all([2,4,6,7], isEven)
          0

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

    #----------- Creating compositional functions -----------#
          >>> def minus7(n): return n-7
          ...
          >>> def times3(n): return n*3
          ...
          >>> minus7(10)
          3
          >>> minustimes = compose(times3,minus7)
          >>> minustimes(10)
          9
          >>> times3(minus7(10))
          9
          >>> timesminus = compose(minus7,times3)
          >>> timesminus(10)
          23
          >>> minus7(times3(10))
          23

Некоторые рекомендации

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

Ресурсы

Предыдущие статьи, посвященные программированию на языке Python можно найти по следующему адресу:

http://gnosis.cx/publish/programming/charming_python_13.html
http://gnosis.cx/publish/programming/charming_python_16.html

Библиотека Xoltar toolkit, написанная Брином Келлером и включающая модуль functional, значительно расширяет возможности ФП на Python. Поскольку модуль functional написан на чистом Python, все, что он делает так или иначе уже возможно в Python. Но Келлер создал очень удачный комплект расширений, предоставлющий большую мощность при компактности определения. Библиотеку можно найти по адресу:

http://sourceforge.net/projects/xoltar-toolkit

Если вы только начали изучать функциональное программирование, вы сможете найти ответы на многие вопросы по адресу:

http://www.cs.nott.ac.uk/~gmh//faq.html#functional-languages

Автор находит, что гораздо легче понять суть функционального программирования, используя язык Haskell, а не Lisp/Scheme (несмотря на то, что последний чаще используется, хотя бы в Emacs). Кроме того, программистам на Python будет много проще жить без такого количества круглых скобок и префиксной (польской) записи:

http://www.haskell.org/

Прекрасная вводная книга:

Haskell: The Craft of Functional Programming (2nd Edition)
Simon Thompson, Addison-Wesley (1999). 

Еще одна книга более прикладного характера, которая одновременно является отличным введением в язык Haskell:

The Haskell School of Expression:  Learning Functional Programming Through Multimedia
Paul Hudak, Cambridge University Press (2000).

Об авторе

(Фотография автора: http://gnosis.cx/cgi-bin/img_dqm.cgi)

Поскольку постижение без интуиции бесплодно, а интуиция без постижения слепа, Дэйвид Мертц хочет литой бюст Джона Мильтона в свой офис. Запланируйте подарить ему на день рождения. Дэйвид доступен по адресу: mertz@gnosis.cx, а жизнь его описана на http://gnosis.cx/publish/. Присылайте свои замечания и предложения касательно этой, прошлых или будущих статей.



[1] Переводчик отдает себе отчет в странности термина "карринг" для русского уха. Но в большей части русскоязычной литературы по Haskell он звучит именно так. (Прим. перев.)

[2] Т.е. вычисления прекращаются, как только известен результат. Для disjoin() первый возврат true приведет к прекращению вычислений; для conjoin() - false. (Прим. перев.)



Оригинальный текст статьи можно посмотреть здесь:
Even More Functional Programming in Python

Размещение рекламы — тел. +7 495 4119920, ICQ 232284597

Подписка на новости IT-портала CITForum.ru
(библиотека, CITKIT.ru, CitCity)

Новые публикации:

24 декабря

CITKIT.ru:

  • Новогодние поздравления
  • Сергей Кузнецов. Цикл Операционные системы: Ностальгия по будущему:

  • Алексей Федорчук. OpenSolaris 2008.11 Release

  • Сергей Голубев:

  • Евгений Чайкин aka StraNNik (Блогометки):

    17 декабря

  • С.Д.Кузнецов. Базы данных. Вводный курс

    10 декабря

    CITKIT.ru:

  • OpenSolaris 2008.11 Release

  • Альтернативные ОС: две грустные истории (С.Кузнецов)
  • Nokia N810 — доведение до ума
  • CitCity:

  • Платформа 2009: заоблачные перспективы Microsoft

    4 декабря

  • Лекция С.Д.Кузнецова Понятие модели данных. Обзор разновидностей моделей данных

    CITKIT.ru:

  • OpenSolaris 2008.11 Release. Первые впечатления

  • Linux vs FreeBSD: продолжим "Священные войны"?

  • Nokia N810 as is

  • Индульгенция для FOSS

  • Друзья СПО'2008

    26 ноября

  • Нечеткое сравнение коллекций: семантический и алгоритмический аспекты

    CitCity:

    CITKIT.ru:

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • 19 ноября

  • Проблемы экономики производства крупных программных продуктов

  • Язык модификации данных формата XML функциональными методами

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Заметки к книге:

  • FreeBSD: монтирование сменных устройств и механизм HAL
  • Текстовый редактор ee

    12 ноября

  • Правило пяти минут двадцать лет спустя, и как флэш-память изменяет правила (Гоц Грейф, перевод: Сергей Кузнецов)

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:
  • OSS в России: взгляд правоведа (В.Житомирский)

  • Новая статья из цикла С.Голубева "Железный марш":

    29 октября

  • О некоторых задачах обратной инженерии

  • Веб-сервисы и Ruby

  • Тестирование web-приложений с помощью Ruby

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

  • PuppyRus Linux - беседа с разработчиком (С.Голубев)

  • Сергей Кузнецов. Заметка не про Linux

    22 октября

  • Обзор методов описания встраиваемой аппаратуры и построения инструментария кросс-разработки

    CITKIT.ru:

  • Сергей Кузнецов. Почему я равнодушен к Linux

  • Глава из книги А.Федорчука
    Сага о FreeBSD:
  • Что надо иметь
    3. Базовые познания

    CitCity:

  • Управление IT-инфраструктурой на основе продуктов Microsoft

    15 октября

  • Методы бикластеризации для анализа интернет-данных

    CitCity:

  • Разъемы на ноутбуках: что они дают и зачем их так много?
  • AMD Puma и Intel Centrino 2: кто лучше?

    CITKIT.ru:

  • Новый цикл статей С.Голубева
    Железный марш:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    8 октября

  • Автоматизация тестирования web-приложений, основанных на скриптовых языках
  • Опыт применения технологии Azov для тестирования библиотеки Qt3

    Обзоры журнала Computer:

  • SOA с гарантией качества
  • Пикоджоуль ватт бережет
  • ICT и всемирное развитие

    CitCity:

  • Пиррова победа корпорации Microsoft

    CITKIT.ru:

  • Главы из книги А.Федорчука
    Сага о FreeBSD:

    Статья из архива:

  • Я живу в FreeBSD (Вадим Колонцов)

    Новые Блогометки:

  • Перекройка шаблона Blogger или N шагов к настоящему
  • Blogger. Comment style
  • Screenie или глянцевый снимок экрана

    2 октября

    CITKIT.ru:

  • Сага о FreeBSD (А. Федорчук)

    Zenwalk: пакет недели

  • Банинг — интеллектуальное развлечение (С.Голубев)

    CitCity:

    25 сентября

  • Клермонтский отчет об исследованиях в области баз данных

    CITKIT.ru:

  • Пользователям просьба не беспокоиться... (В.Попов)

  • Снова про ZFS: диск хорошо, а два лучше
  • Командная оболочка tcsh (А.Федорчук)

    Zenwalk: пакет недели

    17 сентября

  • T2C: технология автоматизированной разработки тестов базовой функциональности программных интерфейсов
  • Технология Azov автоматизации массового создания тестов работоспособности

    CITKIT.ru:

  • FreeBSD: ZFS vs UFS, и обе-две — против всех (А.Федорчук)

    Zenwalk: пакет недели

  • Дачнет — практика без теории (С.Голубев)

    10 сентября

  • За чем следить и чем управлять при работе приложений с Oracle
  • Планировщик заданий в Oracle
    (В.Пржиялковский)

    CITKIT.ru:

  • Microsoft: ответный "боян" (С.Голубев)

  • Причуды симбиоза, или снова "сделай сам" (В.Попов)

  • Файловые системы современного Linux'а: последнее тестирование
  • Zsh. Введение и обзор возможностей
    (А.Федорчук)

    Описания пакетов Zenwalk: Zsh, Thunar, Thunar-bulk-rename, Xfce4-places-plugin, Xfce4-fsguard-plugin

    Блогометки:

  • Google Chrome
  • Лончер для ASUS Eee PC 701

    3 сентября

    CITKIT.ru:

  • Заметки о ядре (А.Федорчук):

    Добавлены описания пакетов Zenwalk: Galculator, Screenshot, Gnumeric, Pidgin

    В дискуссинном клубе:

  • И еще о Википедии и Google Knol

  • Лекция для начинающего линуксоида (С.Голубев)

    26 августа

  • Транзакционная память (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Открыт новый проект Zenwalk: пакет недели

  • Статья Текстовые процессоры и их быстродействие: конец еще одной легенды?

    21 августа

    CITKIT.ru:

  • Почему школам следует использовать только свободные программы (Ричард Столлман)
  • Беседа Сергея Голубева с учителем В.В.Михайловым

  • Википедия или Гуглезнание? Приглашение к обсуждению (Алексей Федорчук)
  • Народная энциклопедия от Google (StraNNik)

  • Обзор Mandriva 2009.0 Beta 1 Thornicrofti
  • Новичок в Линукс: Оптимизируем Mandriva 2008.1

  • Книга Zenwalk. Приобщение к Linux:

    13 августа

    CitCity:

  • Мирный Atom на службе человеку. Обзор платы Intel D945GCLF с интегрированным процессором
  • Обзор процессоров Intel Atom 230 на ядре Diamondville

  • iPhone - год спустя. Скоро и в России?

    CITKIT.ru:

  • Интермедия 3.4. GRUB: установка и настройка (из книги Zenwalk. Приобщение к Linux)

    6 августа

  • СУБД с хранением данных по столбцами и по строкам: насколько они отличаются в действительности? (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • Интермедия 2.2. Что неплохо знать для начала (из книги Zenwalk. Приобщение к Linux)

  • И снова про шрифты в Иксах (А.Федорчук)

  • 20 самых быстрых и простых оконных менеджеров для Linux

  • Дело о трех миллиардах (С.Голубев)

    30 июля

  • OLTP в Зазеркалье (Пересказ: С. Кузнецов)

    CitCity:

  • Будущее BI в облаках?
  • Тиражные приложения и заказная разработка. Преимущества для заказчика
  • Дискуссия со сторонниками заказной разработки

    CITKIT.ru:

  • Новые главы книги Zenwalk. Приобщение к Linux:
  • Глава 8. Пакеты: средства установки, системы управления, системы построения
  • Глава 9. Zenwalk: репозитории, пакеты, методы установки

    23 июля

    CITKIT.ru:

  • Все против всех. 64 vs 32, Intel vs AMD, tmpfs vs ext3
  • Две головы от Intel

  • Zenwalk: обзор штатных приложений (глава из книги "Zenwalk. Приобщение к Linux")

  • Нормально, Григорий...

    16 июля

    Обзоры журнала Computer:

  • Перспективы и проблемы программной инженерии в XXI веке
  • Большие хлопоты с большими объемами данных
  • Перспективы наноэлектроники

    CITKIT.ru:

  • Интермедия о лицензиях (А.Федорчук. "Zenwalk. Приобщение к Linux")

  • Есть ли будущее у KDE?

  • Linux в школе: альтернативный вариант в задачах

  • Шифр (приключения агента Никодима)

    10 июля

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия вступительная. Linux или GNU/Linux? Как вас теперь называть?
  • Глава 5. Среда Xfce
  • Глава 6. Xfce: приложения и плагины

  • ZUR (Zenwalk User Repository) FAQ

    2 июля

  • Персистентность данных в объектно-ориентированных приложениях (С. Кузнецов)

    CITKIT.ru:

  • Новые разделы книги А. Федорчука Zenwalk. Приобщение к Linux:
  • Интермедия 1.2. Дорога к Zenwalk'у. Период бури и натиска
  • Интермедия 3.3. Немного о Linux'е и "железе"
  • Глава 4. Настройка: инструментами и руками
  • Интермедия 4.1. Zenpanel и конфиги: поиски корреляции

  • Интервью с Жан-Филиппом Гийоменом, создателем дистрибутива Zenwalk

  • Linux в школе: первые итоги (С. Голубев)

    25 июня

    CITKIT.ru:

  • Zenwalk. Приобщение к Linux (А. Федорчук)

  • Логика и риторика (С.Голубев)

  • Технология Tru64 AdvFS

  • Ханс Райзер предлагает отвести полицейских к телу Нины

    18 июня

  • Проекты по управлению данными в Google (Пересказ: С. Кузнецов)

    CITKIT.ru:

  • ОС и поддержка "железа": мифы и реальность (А. Федорчук)

  • Linux в школе: другие дистрибутивы

  • Пинок (С. Голубев)

    4 июня

  • Ландшафт области управления данными: аналитический обзор (С. Кузнецов)

    CITKIT.ru:

  • Linux в школе: слово заинтересованным лицам

  • SlackBuild: пакеты своими руками

  • Linux от компании Novell. Установка и обзор openSUSE Linux

    Все публикации >>>




  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — тел. +7 495 4119920, ICQ 232284597 Пресс-релизы — pr@citcity.ru
    Послать комментарий
    Информация для авторов
    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2007 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...