Начинающим на LISP

Здесь находятся темы форума, утратившие актуальность

Модератор: Администраторы

Начинающим на LISP

Сообщение gsvano » Чт мар 24, 2005 9:04:09

А нельзя ли пример кода чего-нибудь простого, с разбором и пояснениями?
И ещё изложите свое понимание и назначение языка Lisp.
Для чего он, по-вашему, наиболее подходит?
Оно, конечно, ничего, если ничего не случится. А вот если случится, тогда что?
Аватара пользователя
gsvano
Цотонист-язычнег
 
Сообщения: 2168
Зарегистрирован: Пт янв 14, 2005 2:50:39
Откуда: с Востока

Re: Начинающим на LISP

Сообщение Lisper » Пт мар 25, 2005 10:48:02

gsvano писал(а):А нельзя ли пример кода чего-нибудь простого, с разбором и пояснениями?
И ещё изложите свое понимание и назначение языка Lisp.
Для чего он, по-вашему, наиболее подходит?


Конечно если Вы не читали приведенные в списке литературы книги (хотя бы Practical Common Lisp), то даже самое простое может показаться сложным, но все же попробую.

Как язык Common Lisp сам по себе построен на весьма простой концепции. Выражения, заключенные в скобки, назваются формами. То, что в форме при оценивании идет первым элементом, это функция, все остальное ее аргументы. Символ ' или quote поставленный перед формой, как например '(1 2 3) предотвращает ее оценивание, по сути получается список. В Лиспе широко используются т.н. символы или символьные идентификаторы вроде: +, MYSYMBOL, :KEYWORD и т.п. Программа состоит из списков форм, наполненных символами и примитивными типами - строками, числами,векторами и т.д.

(let ((a 2)(b (+ 3 4))) (+ a b))
Как видно, здесь let,a,b,+ являются символами. Специальная форма let предназначена для объявления локальных переменных, + является обычной функцией.

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

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

Например Python имеет множество элементов, заимствованных из Лиспа, но его безымянные функции (lambda) были практически бесполезны по причине неудачной реализации и в ближайших версиях их собираются удалить. Зачем они нужны ?
Например вам однократно требуется указать некую формулу действующую при обходе коллекции:
(mapcar (lambda (x) (* x x)) (list 2 3 4 5 6))
=> 4 9 16 25 36
Т.е. возвращает список с элементами возведенными в квадрат.
Здесь mapcar - это функция, принимающая первым аргументом функцию, а остальными аргументами списки. Очередные соответствующие элементы списков передаются в функцию, а по результату строится новый список.
Можно было бы сделать это так:
(defun power2 (x) (* x x))
(mapcar (function power2) (list 2 3 4 5 6))

Теперь поговорим о списках. Списки в Лиспе не существуют (матрица прямо какая-то) ;-) На самом деле есть только ячейки списков, состоящие из двух элементов, которые могут быть какими либо объектами, либо другими ячейками. Конструируются ячейки списков с помощью функции CONS. (CONS 1 2) возвращает ячейку с элементами 1 и 2 - так называемая точечная пара, которая записывается как (1 . 2)
Что такое список ? Это множество ячеек у которых первый элемент содержит значение, а второй элемент ссылается на следующую ячейку списка, в последней ячейке второй элемент списка ссылается на NIL (ничто). Мы можем вручную сконструировать список 1 2 3 4:
(CONS 1 (CONS 2 (CONS 3 (CONS 4 NIL)))) => (1 2 3 4)
А можно применить функцию-конструктор LIST: (LIST 1 2 3 4)
Для доступа к элементам ячейки применяются функции с исторически сложившимися названиями CAR и CDR.
(CAR (CONS 1 2)) => 1
(CDR (CONS 1 2)) => 2
При работе со списками эти функции используются весьма широко:
(CAR (CDR (LIST 1 2 3))) => (CAR (CONS 2 (CONS 3 NIL))) => 2
Множество вложенных вызовов CAR и CDR объединяются в специально объявленные функции с именами: СADR = (CAR (CDR lst)), CDDR = (CDR (CDR lst)) и т.д. вроде CADADR ;-)

Вместо них можно использовать и более привычные названия вроде FIRST,SECOND,LAST,REST и т.п.

(продолжение следует)
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение Lisper » Пт мар 25, 2005 13:27:19

Так как ниже это упоминать будет поздно, прошу запомнить одну особенность выражений в языке Лисп - все выражения ВСЕГДА возвращают значение. Это понятно при вызове функции (+ 2 2), но например при выходе из цикла может сбивать с толку. Любая оцениваемая при выполнении форма возвращает значение, даже если оно пустое. Эта концепция была частично перенята в языках Си, C++ и т.п. например оператор присваивания возвращает значение
int a = (b = 2);
Еще большей аналогией является оператор ? в языке Си:
int a = (b > 2) ? 1 : 2;
т.е. выражение после знака равно возвращает значение, которое присваивается переменной а.
Но выражение for (i=0;i<10;i++) {} ничего не возвращает, его нельзя присвоить переменной в отличие от того же в Лисп:
(dotimes (i 10 (* i i)) i) вернет 100, за возврат значения отвечает форма (* i i). Если ее не указать то DOTIMES вернет NIL (т.е. ничто).


Попробуем разобрать lex-string, функции разбивающей строку на список подстрок на основе данного ей списка символов-разделителей:
(lex-string "Привет. Как дела?" '(#\space #\. #\?))
=> ("Привет" "Как" "дела")

Код: Выделить всё
(defun lex-string (string &optional (whitespace-chars '(#\space #\newline)))
  "Separates a string at whitespace and returns a list of strings"
  (flet ((whitespace-char? (char)
           (member char whitespace-chars :test #'char=)))
            (let ((tokens nil))
              (do* ((token-start
                      (position-if-not #'whitespace-char? string)
                         (when token-end
                            (position-if-not #'whitespace-char? string
                                    :start (1+ token-end))))
                    (token-end
         (position-if #'whitespace-char? string :start (or token-start 0))
                          (when token-start
                            (position-if #'whitespace-char? string :start token-start))))
                    ((null token-start) (nreverse tokens))
                    (push (subseq string token-start token-end) tokens)))))


Страшная с виду функция, но на самом деле все опирается на знание функций библиотеки, входящей в стандарт Common Lisp.

Итак начнем с объявления аргументов:
Код: Выделить всё
(defun lex-string (string &optional (whitespace-chars '(#\space #\newline)))


lex-string - это название функции
&optional означает, что далее идут необязательные аргументы, которые при вызове функции можно не указывать, при этом они могут принять значение по умолчанию. Форма (whitespace-chars '(#\space #\newline)) описывает аргумент whitespace-chars, со значением по умолчанию '(#\space #\newline) - это и есть список символов-разделителей (пробел и перевод строки). В примере выше я указывал в качестве разделителей '(#\space #\. #\?) - пробел, точка и знак вопроса, вместо значения по умолчанию.

Далее идет строка документации:
"Separates a string at whitespace and returns a list of strings"
Которую можно в последствии запросить так:
(documentation 'lex-string 'function)

Код: Выделить всё
  (flet ((whitespace-char? (char)
           (member char whitespace-chars :test #'char=)))


FLET - это специальная форма, которая в отличие от LET объявляет локальные функции. Синтаксис следующий
(FLET (обявление-функции(ий)) формы-где-используются-локальная(ые)-функция(ии))

Обявление функции выглядит так же как с DEFUN, но первым в списке сразу идет имя функции:
(имя-функции (аргументы) тело)

Например мы хотим использовать локальные функции для сложения и вычитания двух чисел:
Код: Выделить всё
(FLET ((SUM-NUMBERS (X Y) (+ X Y))
          (SUB-NUMBERS (X Y) (- X Y)))
    (LIST (SUM-NUMBERS 5 3) (SUB-NUMBERS 5 3)))

=> (8 2)


В случае lex-string объявляется функция WHITESPACE-CHAR? которая возвращает NIL в случае если аргумент не является разделителем и не NIL в обратном случае (подробности позже).
Код: Выделить всё
(whitespace-char? (char)
           (member char whitespace-chars :test #'char=))


Сразу поясню, аргумент TEST является аргументом передаваемым как ключевое слово. Смысл такой, обявляется функция у которой есть "аргументы-ключевые слова":

Код: Выделить всё
(defun MYFUN (A B &key MYKEY-1 MYKEY-2)
    (list A B MYKEY-1 MYKEY-2))

A и B - обычные обязательные аргументы
MYKEY-1 и MYKEY-2 - аргументы-ключевые слова


Вызов функции сопровождается указанием значений этих аргументов в виде: (MYFUN 1 2 :MYKEY-1 5 :MYKEY-2 6)
=> (1 2 5 6)
Аргументы, передаваемые через ключевое слово, могут следовать после обязательных аргументов в любом порядке. При этом их можно не указывать, тогда внутри функции они принимают значение NIL, если не задано значение по умолчанию:
(MYFUN 1 2)
=> (1 2 NIL NIL)

Символы вида :SYMBOL (с двоеточием вначале) являются особым видом символов-ключевых слов. На самом деле это обычные символы, но они определены в пакете KEYWORD, а следовательно его можно заменить на обычный символ с указанием пакета KEYWORD:SYMBOL. Про пакеты рассказывать подробно не буду, так как это отдельная тема, которая лучше освещена в книгах. Главное, что вы можете в любом месте программы использовать ключевые слова для своих нужд, например для создания списка цветов: (list :red :blue :green) или для указания свойств объекта '(BOOK :title "ANSI Common Lisp" :author "Paul Graham").

Функция MEMBER ищет первый аргумент (char) в списке (white-space-hars), аргумент TEST является аргументом передаваемым как ключевое слово, передается функция char=, то есть функция для сравнения символов (не символьных идентификаторов, а буковок и цифирок).

И так мы объявили локальную функцию WHITESPACE-CHAR?, которая указывает, является ли разделителем заданный символ (буква).

(let ((tokens nil)) - обявление локальной переменной tokens, NIL - это синоним НИЧТО и в то же время пустой список, его также можно писать записать как '(). Т.е. обявлен пустой список разобранных слов, на которые мы должны разбить строку.

Что такое форма DO* ? Это форма для задания циклов. Синтаксис следующий:
(DO* (объявления-переменных) (блок проверки) тело-цикла)

Каждое объявление переменной выглядит как:
(ИМЯ-ПЕРЕМЕННОЙ НАЧАЛЬНОЕ-ЗНАЧЕНИЕ СЛЕДУЮЩЕЕ-ЗНАЧЕНИЕ)

Т.е. если Вам больше знаком язык Си или Java, то это больше соответствует:
for (ИМЯПЕРЕМЕННОЙ=НАЧАЛЬНОЕЗНАЧЕНИЕ;БЛОКПРОВЕРКИ; ИМЯПЕРЕМЕННОЙ=СЛЕДУЮЩЕЕЗНАЧЕНИЕ)
{ ТЕЛОЦИКЛА }

Что означает звездочка в имени формы ? Вопрос не праздный, так как формы без звездочек работают по другому. Объясняется все просто: без звездочки все присваивания значений объявляемых переменных идут параллельно, а в формах со звездочкой - последовательно. То есть
в (LET ((a 2)(b 4)) ...) нет способа присвоить b значение, основанное на объявляемом выше а. В форме LET* (читается как "let star") можно использовать для последующих объявлений предыдущие:
(LET* ((a 2)(b (+ a 4)) ...)
Кстати интересен случай (LET ((A A)) ...) вы можете присвоить локальной переменной A значение внешней переменной с таким же названием.
В С++ такой фокус не проходит:
int A = 2;
{
int A = A;
// A == ?????
}

Блок проверки DO и DO* состоит из формы проверки и возвращаемого результата, если проверка показывает, что пора выйти из цикла:

Код: Выделить всё
(DO ((I 0 (+ I 1)))
      ((> I 25) (* I I))
      ...)


В данном случае I имеет начальное значение 0, каждый раз увеличивает свое значение на 1 и цикл завершается, когда значение I будет больше 25, при этом результатом оценки формы будет квадрат значения I (26^2).
Что почти эквивалентно: for (i=0;i<26;i++) {...}

Итак что делает код:
Код: Выделить всё
              (do* ((token-start
                      (position-if-not #'whitespace-char? string)
                         (when token-end
                            (position-if-not #'whitespace-char? string
                                    :start (1+ token-end))))


Переменная цикла token-start в качестве начального значения получает позицию первого символа в строке, который не является разделителем.
(position-if-not #'whitespace-char? string) - функция POSITION-IF-NOT принимает в качестве аргумента функцию проверки и строку и возвращает индекс символа в строке, для которого функция проверки впервые выдала t (в Лиспе t - это аналог TRUE, а NIL - это FALSE).
Мы даже можем сами определить такую функцию, чтобы лучше понять как работает форма DO*.
Код: Выделить всё
(defun our-position-if-not (fn string)
   (do* ((idx 0 (1+ idx))) ;; переменные
           ((= idx (length string)) nil) ;; блок проверки, если конец то NIL
         (when (not (funcall fn (elt string idx))) ;; если условие выполнено
               (return idx)))) ;; вернуть индекс

(our-position-if-not #'evenp '(2 4 6 7 8))
=>

FUNCALL - функция, применяющая заданную функцию к аргументам.
т.е. (FUNCALL '+ 2 2) => 4
ELT - функция извлекающая из последовательности элемент, причем последовательностью может быть список, массив, вектор, строка...
(ELT "The string" 0) => #\T
(ELT '(1 2 3 4 5) 2) => 3
(ELT (make-array 10 :initial-element 1) 5) => 1 (массив единиц)
(ELT (vector 1 2 3 4) 0) => 1

Форма RETURN, в отличие от Си, производит выход не из функции, а из ближайшего лексического блока, который устанавливается формами LOOP,DO,PROG и т.д. То есть сначала DO* возвращает значение, потом его возвращает функция.

Вернемся к нашим баранам. На первой итерации в LEX-STRING переменной token-start будет присвоен индекс первого элемента строки, не являющегося разделителем. Если таких символов нет, то token-start будет присвоен NIL. Переменной token-end будет присвоен индекс первого разделителя начиная с token-start или, если не нашелся символ-не разделитель, то с нуля.

Код: Выделить всё
(token-end (position-if #'whitespace-char? string :start (or token-start 0))


Далее происходит проверка на равенство token-start NIL.
Функция NULL возвращает t если значение равно NIL, иначе возвращает NIL.
Код: Выделить всё
((null token-start) (nreverse tokens))

и если больше слов не найдено (нет символов не разделителей) то переворачиваем накопленный список слов и возвращаем (зачем переворачиваем обясню позже).

Далее если проверка показала "ложь", то помещаем очередное слово
(выделяя его из строки функцией SUBSEQ) в начало списка. Список строится сначала (помните как строится список при помощи CONS ?), поэтому-то его и требуется перевернуть при возврате из цикла.
Код: Выделить всё
(push (subseq string token-start token-end) tokens)


На следующей итерации token-start приобретает следующее значение:
Код: Выделить всё
(when token-end
      (position-if-not #'whitespace-char? string
                            :start (1+ token-end)))


Если на предыдущей итерации найден следующий разделитель, то ищем после него т.е. (1+ token-end) индекс следующего символа-не разделителя. Если token-end равен NIL, то форма WHEN вернет NIL. WHEN - это сокращенный вариант IF, WHEN оценивает первый аргумент (форму) и если t (правда), то выполняет остальные формы.

Также на следующей итерации token-end приобретает значение:
Код: Выделить всё
(when token-start (position-if #'whitespace-char? string :start token-start)))


Т.е. если на ЭТОЙ итерации (помните для чего зведочка у DO* ?) был найден следующий символ-не разделитель, то найти после него индекс следующего символа-разделителя. Причем, если разделитель не найден, то token-end становится равным NIL. Но функция SUBSEQ воспринимает это как просьбу выделить кусок строки, начиная с индекса token-start до конца строки. Как видно из описания блока проверки цикла, если token-start на этой итерации стал равным NIL, то тело цикла не выполняется список накопленных значений переворачивается и возвращается из формы DO*.

Это не самый элегантный способ описания циклов, тем более есть множество мощных конструкции типа LOOP, ITERATE и других. Но DO является базовой конструкцией, можно сказать намертво встроенной в язык и хорошо поддерживается даже самыми не соблюдающими стандарт реализациями Common Lisp.

Вопросы, пожалуйста.;-)[/b]
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение Lisper » Пт мар 25, 2005 17:00:53

И ещё изложите свое понимание и назначение языка Lisp.
Для чего он, по-вашему, наиболее подходит?


Весьма непростой вопрос. Как мультипарадигмный язык общего назначения, поддерживающий функциональный, императивный, логический, объектно-ориентированный и т.д. - любые стили программирования, содержащий мощные конструкции для метапрограммирования, обширную библиотеку входщую в стандарт, Лисп (в частности Common Lisp) является серьезным инструментом для разработки приложений промышленного масштаба.

При оценке плюсов и минусов следует делать разграничение объектов оценки:
1) Common Lisp как язык может иметь свои положительные и отрицательные стороны. Кому-то может не нравится, что нет специального оператора [] для извлечения элемента массива, хотя его можно ввести слегка в измененном виде с помощью макроса чтения. Например пакет INFIX позволяет для удобства писать сложные математические выражения в инфиксной нотации, где элемент массива и операторы присвоения выглядят так же как Си, после чего выражение трансформируется в обычное Лисп представление и компилируется.

Пришедшим из С++ Лисп кажется странным, мой коллега заядлый плюсист, все время пытается найти в Лиспе "умные" указатели и итераторы ;-) Так же он не знает, как жить без шаблонов и адресной арифметики. Но на самом деле без всего этого жить легко и весело, за некоторыми исключениями, которые можно при желании изобразить на Си и прицепить к Лиспу.

2) Реализации довольно большого стандарта и того, что не входит в стандарт, могут иметь свои особенности и разные возможности.

Можно ругать язык, но на самом деле все зависит от реализации: GUI (не считая Common Lisp Interface Manager), FFI, сокеты, COM/ActiveX, CORBA, SQL, многопоточность - все это не входит в стандарт и реализуется каждым вендором по своему. Есть библиотеки объединяющие множество реализаций, так что это не большая проблема.

3) Железо на котором работают современные реализации для них довольно чужеродно, поэтому сам Лисп отчасти выглядит странноватым языком, по сравнению с низкоуровневыми слаботипизированными языками вроде Си. В Лисп машинах была аппаратная проверка типов, аппаратная поддержка управления памятью и прочие полезные вещи, но современные архитектуры общего назначения пошли по более дешевому и глючному (в смысле софта) пути. Тем не менее даже X86 Лисп может догонять и обгонять даже Си за счет своей динамичности, например откомпилированная в машинный код функция будет работать быстрее, чем интерпретируемая, написанная на Си. Таким образом при разборе регулярных выражений CMU Common Lisp обставил на некоторых тестах Perl, который был специально создан именно для таких нужд.

Стоит поставить вопрос так:
Для чего Лисп ниболее не подходит?

Учитавая, что Лисп (окроме как через FFI или ассемблерные вставки) не содержит конструкций для прямого управления памятью (указатели и т.п.), то можно заключить, что на железе общего назначения типа X86 на Лиспе пока что трудно писать какие-либо системные вещи вроде драйверов устройств и т.п. Но это не значит, что это невозможно, кое какие разработки ведутся и на X86, а на Лисп машинах ОС и драйверы были написаны на самом Лиспе. Можно генерировать Си по Лисп представлению и не пользоваться Лисп рантаймом.

Также не очень легко сделать какие-то жесткие риал-тайм вещи, но сборщик мусора, я уверяю, отключается очень просто, а не делать мусор совсем, тоже вполне возможно. Остается только размер бинарника. Тут ситуация похожа на Java. Обычные реализации Common Lisp рожают EXE файл от 1.5М и больше. На LispWorks типичная программа в архиве занимает не менее 2.5М. Так что здесь есть некоторые неприятности, но с другой стороны такими цифрами уже никого не напугаешь.

Проще спросить, а где нет Лиспа ? Он как хамелеон приспосабливается и принимает любые формы. Слышали про XAML ? Уже много лет была возможность делать GUI формочки на XML или напрямую на Лиспе, а потом увязывать их с программной логикой, но Microsoft снова все это изобрела и рекламирует как огромное достижение человеческой мысли.

Внутри копилятора GCC программа превращается в дерево выражений, весьма сходное с Лиспом, и затем компилируется в нужное представление.
Лисп существует во многих формах, в которых Вы даже нисколько его не заподозрите ;-)

Даже Java испытала сильное влияние Лисп, тому кто знает Common Lisp сразу видно отличие работы в Java от С++. Синтаксис может быть где-то похож, но кто кому больший родственник? Ведь создатель Java хорошо знал Лисп. ;-)

Если бы идея Лиспа была плоха, то она бы не протянула столько лет среди часто появляющихся "новинок": ООП, логическое программирование, обобщенное программирование и т.п. Но к сожалению многие не понимают, как использовать этот язык в среде программистов с самой низкой квалификацией. Ясно, что если усадить за Лисп 1000 мартышек, что в результате получится полный абзац. Но если посадить 3-4 профи, которые сформируют некий строгий языковой уровень для этих самых мартышек, то они будут работать гораздо продуктивнее, чем в общем случае, так как язык будет специально хорошо подходить к решаемой задаче.[/quote]
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение gsvano » Пн мар 28, 2005 3:37:00

Спасибо за столь подробное расжеваное объяснение - очень интересно.
Буду пробовать. (Когда время будет)
Оно, конечно, ничего, если ничего не случится. А вот если случится, тогда что?
Аватара пользователя
gsvano
Цотонист-язычнег
 
Сообщения: 2168
Зарегистрирован: Пт янв 14, 2005 2:50:39
Откуда: с Востока

Сообщение Гость » Вт апр 12, 2005 23:52:10

Подскажите где можно достать информацию на русском языке...
Гость
 

Сообщение Lisper » Ср апр 13, 2005 9:08:16

MOHAX писал(а):Подскажите где можно достать информацию на русском языке...


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

Вот пример такой книги на русском:
http://dstu2204.narod.ru/4sem/fp/yapl.cab

Еще в списке литературы в этом разделе форума посмотрите двухтомник "Мир Лиспа".

Предупреждают только, что книги эти малость устарели, с тех пор некоторые вещи изменились до неузнаваемости (например объектная система была стандартизирована и превратилась в Common Lisp Object System - CLOS).

Я начал переводит Successful Common Lisp, но времени нет. К тому же верятно полезнее было бы перевести книгу Practical Common Lisp.

С наилучшими пожеланиями
Lisper
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение Гость » Ср апр 13, 2005 13:27:22

А какие у этого языка возможности по анализу текстов?
Можел лучше PERL?
Гость
 

Сообщение Lisper » Ср апр 13, 2005 17:24:40

MOHAX писал(а):А какие у этого языка возможности по анализу текстов?
Можел лучше PERL?


Думается возможности неплохие, есть пакет для регулярных выражений PERL, который на CMU Common Lisp на определенных тестах показывает даже лучшее быстродействие, чем PERL . Я не пишу на PERL, но проекты на Common Lisp IMHO должны быть более сопровождаемыми за счет многих факторов. Не стоит и забывать, что Лисп - это метаязык с довольно четкой основой в отличии от PERL, не думаю, что Вам понравится писать на PERL встраиваемый в PERL компилятор языка PROLOG.
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Какая разница какой язык?

Сообщение NewPoisk » Ср апр 20, 2005 13:16:12

В конечном итоге текст программы на любом языке преобразуется в машинные коды. Следовательно любой язык равносилен по своим возможностям ассемблеру. Вопрос: зачем нужно учить, использовать Java, Lisp, Prolog и т.д. если все тоже самое можно написать например на простом досовском Бэйсике. В устоявшихся областях программирования (базы данных к примеру лучше вести на СУБД) выбор языка определяется быстротой и удобством создания на нем программ, т.е. чисто практической мерой. Но в ИИ мы еще ничего не знаем! Мы даже не знаем каковы самые общие принципы его работы. Следовательно не имеет смысла утверждать что для ИИ один язык лучше, а другой хуже. Пока все одинаково полезны (а точнее бесполезны). Так не лучше ли перейти всем на простые понятные системы программирования без затей, чем лезть вон из кожи изучая туманные концепции и колоссальные библиотеки каких-то очень крутых комплексов программирования? Зачем это вообще нужно?!!!
Аватара пользователя
NewPoisk
Разбирающийся в ИИ
 
Сообщения: 493
Зарегистрирован: Пт ноя 26, 2004 9:14:17

Re: Какая разница какой язык?

Сообщение Lisper » Ср апр 20, 2005 21:20:31

NewPoisk писал(а):В конечном итоге текст программы на любом языке преобразуется в машинные коды. Следовательно любой язык равносилен по своим возможностям ассемблеру. Вопрос: зачем нужно учить, использовать Java, Lisp, Prolog и т.д. если все тоже самое можно написать например на простом досовском Бэйсике.

В устоявшихся областях программирования (базы данных к примеру лучше вести на СУБД) выбор языка определяется быстротой и удобством создания на нем программ

Сами себе и отвечаете. Языки программирования не равны по выразительной мощности, это еще сильнее проявляется в неустоявшихся областях, когда проверяются какие-то идеи.

NewPoisk писал(а):Но в ИИ мы еще ничего не знаем! Мы даже не знаем каковы самые общие принципы его работы.


Лучше иметь максимально мощный язык, на случай если эти принципы окажутся не очень простыми. Уже знаем, что ИИ должен быть самоприменим, следовательно требуется "программируемый язык программирования" ;-)

NewPoisk писал(а):Так не лучше ли перейти всем на простые понятные системы программирования без затей, чем лезть вон из кожи изучая туманные концепции и колоссальные библиотеки каких-то очень крутых комплексов программирования? Зачем это вообще нужно?!!!


Это самый спорный вопрос. Что такое "понятные системы программирования" ? Для меня Common Lisp - это проверенная временем и понятная система программирования, которая позволяет проверять новые идеи как можно быстрее. Туманные концепции я тоже не люблю, поверьте в Лиспе их нет (если и есть, то большинством они не поддерживаются/не известны), это совершенно прозрачная система, без всякой мистики и волшебства типа поиска решения с помощью встроенной системы вывода как в ПРОЛОГ.
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение gsvano » Вт апр 26, 2005 10:39:43

По крайней мере изучив Lisp, будет более понятно, что лучше в данный момент использовать.
Возможно, что Lisp наиболее полно подходит для создания "Интегральной системы ИИ"
Оно, конечно, ничего, если ничего не случится. А вот если случится, тогда что?
Аватара пользователя
gsvano
Цотонист-язычнег
 
Сообщения: 2168
Зарегистрирован: Пт янв 14, 2005 2:50:39
Откуда: с Востока

Сообщение Lisper » Вт апр 26, 2005 20:28:05

А для изучения Практический Common Lisp в данный момент является наилучшим учебником. Кстати надо ли его переводить на русский или большинство нормально в оригинале читает ? Я вот на пробу перевел одну из самых интересных глав, наверное на этом не остановлюсь, но в одиночку прогресс будет идти медленно, особенно когда это никому не надо.
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение gsvano » Ср апр 27, 2005 1:59:08

Эх.. знал бы я английский как вы.
В оригинале читаю с трудом. Перевод, несомненно нужен, но тут я вам ничем не смогу помочь.
Оно, конечно, ничего, если ничего не случится. А вот если случится, тогда что?
Аватара пользователя
gsvano
Цотонист-язычнег
 
Сообщения: 2168
Зарегистрирован: Пт янв 14, 2005 2:50:39
Откуда: с Востока

Сообщение Lisper » Ср апр 27, 2005 11:46:40

Если не трудно почитайте перевод Главы 19, который прицеплен к теме "Переведена глава...." и скажите свое мнение о качестве перевода. В общем-то я переводил бегло и повторно не особо просматривал, но все равно интересно.
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение gsvano » Чт апр 28, 2005 2:57:20

Не только не трудно, а очень интересно!
Конечно, перевод не без ошибок, но логически все понятно.
После небольшой редакции вполне можно рекомендовать все кто плохо знает английский, и хочет изучить LISP.
Единственное что не понравилось, так это толкование слова Conditions -Ситуация.
Imho - в данном контексте оно переводится как Событие.
Если вы не против, я бы рекомендовал заменить это слово.
Ещё я начал редактировать перевод, что бы он стал более читабельным (заодно и текст выучу, и пойму)
Оно, конечно, ничего, если ничего не случится. А вот если случится, тогда что?
Аватара пользователя
gsvano
Цотонист-язычнег
 
Сообщения: 2168
Зарегистрирован: Пт янв 14, 2005 2:50:39
Откуда: с Востока

Сообщение Lisper » Чт апр 28, 2005 9:44:59

Не могу согласиться, иначе бы это слово называлось Event. А из текста явно следует, что речь идет об Ошибочной Ситуации. IMHO замена этого слова на слово Событие исказит смысл.
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение gsvano » Чт апр 28, 2005 9:57:22

Да, я это уже сам понял.
Вот мой немного отредактированный перевод 19 статьи.
Я попытался увеличить его читабельность путем удаления семантических ошибок из текста и преобразования части предложений к русифицированной форме построения.
Конечно, этого мало, но IMHO - текст стал более понятен.
(особенно мне ;) )
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Оно, конечно, ничего, если ничего не случится. А вот если случится, тогда что?
Аватара пользователя
gsvano
Цотонист-язычнег
 
Сообщения: 2168
Зарегистрирован: Пт янв 14, 2005 2:50:39
Откуда: с Востока

Сообщение Lisper » Чт апр 28, 2005 12:15:22

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

Спасибо за Ваш вклад в общее дело !
Lisper
Серьёзный посетитель
 
Сообщения: 147
Зарегистрирован: Пт фев 25, 2005 1:54:54

Сообщение gsvano » Пт апр 29, 2005 0:59:54

Я согласен за разделение труда - вы переводите, а я редактирую (делаю читабельным). Польза всем.
Я - например, процессе редактирования текста выучу Common Lisp, да и не только выучу, а пойму (без этого редактировать вообще невозможно).
Оно, конечно, ничего, если ничего не случится. А вот если случится, тогда что?
Аватара пользователя
gsvano
Цотонист-язычнег
 
Сообщения: 2168
Зарегистрирован: Пт янв 14, 2005 2:50:39
Откуда: с Востока

След.

Вернуться в Архив тем

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


cron


Rambler's Top100 Каталог ресурсов ListTop.Ru Каталог сайтов Союз образовательных сайтов Parenting.ru - Родители семья дети ребенок

     Сайт "Искусственный интеллект" - программирование ИИ от разработчика: общение, статьи, ссылки.