Monday, December 6, 2010

В продолжение обзора ЯП

К чему приходит тот, кого во всех языках достаёт ограниченность синтаксиса? Правильно, к Common Lisp-у =) Единственное, чего я опасаюсь, так это того, что буду строчить на нём всякую невменяемую хрень, потому что то, что язык позволяет выразить на нём всё что вздумается, не всегда полезно. Потому что вздуматься может всякое. Вот сегодняшний пример: надо было цепную дробь вычислить (на projecteuler.net зарегистрировался ради того, чтобы было на чём новый язык поизучать). Взбрела в голову шальная мысль: а что, если не сразу вычислять, а сперва выражение составить? Ну и набыдлокодил в итоге:

(defun generate-continued-fraction (lst)
  (loop with sexp = (list '+ (first lst) (list '/ 1 (second lst)))
        for num in (rest (rest lst)) do
        (loop for to-change = sexp then (third to-change)
              until (atom (third to-change))
              finally (setf (third to-change)
                            (list '+ (third to-change) (list '/ 1 num))))
        finally (return sexp)))

Ну а чё, работает же даже:

(generate-continued-fraction '(2 1 2 1 1 4 1))
(+ 2 (/ 1 (+ 1 (/ 1 (+ 2 (/ 1 (+ 1 (/ 1 (+ 1 (/ 1 (+ 4 (/ 1 1))))))))))))

Но вот о производительности такой функции лучше не думать, особенно с учётом того, что потом ещё и eval вызывается. На любом обычном языке мне б и в голову, наверное, не взбрело подобный бред писать, написал бы что-нибудь навроде
(defun continued-fraction (lst)
  (loop with rlst = (reverse lst)
        with frac = (pop rlst)
        for num in rlst do
          (setf frac (+ num (/ 1 frac)))
        finally (return frac)))

Так что надо порядок в голове наводить... %-)

No comments:

Post a Comment