LINUX.ORG.RU

Сообщения swizard

 

хвостовая рекурсия (lisp/scheme)

Вопрос достаточно наивный -- почему в sum-list рекурсия не сворачивается 
в цикл?

(define summator
  (lambda (initial-value)
    (lambda (proc)
      (proc
       (lambda (value) (summator (+ initial-value value)))
       initial-value))))

(define sum-list
  (lambda (list-arg)
    (let loop ((current-summator (summator 0))
               (rest-list list-arg))
      (current-summator
       (lambda (next-proc result)
         (if (null? rest-list)
             result
             (loop (next-proc (car rest-list))
                   (cdr rest-list))))))))

Это из-за замыкания lambda (next-proc result)? Если да, то как переписать
код, чтобы сворачивалось? :)
swizard
()

Perl, большие числа

my @packCharacters    = ('0'..'9', 'A'..'Z');
my %unpackCharacters;
my $decimalValue = 0;
map { $unpackCharacters{$_} = $decimalValue++ } @packCharacters;

sub packLongId
{
    my $id         = shift;
    my $base       = scalar @packCharacters;
    my $packedId   = '';
    for ( my $currentValue = $id; $currentValue > 0; $currentValue = int($currentValue / $base) )
    {
	$packedId .= $packCharacters[ $currentValue % $base ];
    }

    return join "", reverse split //, $packedId;
}

sub unpackLongId
{
    my $packedId     = shift;
    my $base         = scalar @packCharacters;
    my $id           = 0;
    my $currentPower = 1;
    map
    {
	$id           += $unpackCharacters{$_} * $currentPower;
	$currentPower *= $base;
    } reverse split //, $packedId;

    return $id;
}

Переводит, вроде, нормально, но на больших числах начинает лажать.
packLong(11764992501273288845) => 2HDUTRXH5G84T
unpackLong("2HDUTRXH5G84T") => 11764992501273290285 ???

Накопал в цпане Math::BaseCalc, но он лажает точно так же
swizard
()

scheme + lazy streams?

Застрял с реализацией потоков на схеме :( 

Основные определения у меня такие:

(define-macro (stream-cons p q)
  (let
    ((pv (gensym)) (qv (gensym)))
    `(let
         ((,pv (lambda () ,p)) (,qv (lambda () ,q)))
         (lambda (f) (f ,pv ,qv)))))

(define stream-car
  (lambda (s) (s (lambda (p q) (p)))))

(define stream-cdr
  (lambda (s) (s (lambda (p q) (q)))))

(define stream-for-each
  (lambda (func stream)
    (if (null? stream)
      'done
      (begin
        (func (stream-car stream))
        (stream-for-each func (stream-cdr stream))))))

(частично спер из sicp, частично подогнал под свои нужды). 
Простенький поток типа (define ones (stream-cons 1 ones)) работает
отлично, stream-for-each можно пустить по нему навечно. 
Однако что-нибудь чуток посложнее, почему-то, начинает жрать память:

(define stream-map
  (lambda (func . streams)
    (if (or
          (null? streams)
          (< 0
            (apply +
              (map (lambda (s) (if (null? s) 1 0)) streams))))
      '()
      (stream-cons
        (apply func (map stream-car streams))
        (apply
          stream-map
          (cons func (map stream-cdr streams)))))))

(define nums (stream-cons 1 (stream-map + ones nums)))

или даже

(define number-stream
  (lambda (number) (stream-cons number (number-stream number))))

Стоит пустить по такому потоку stream-for-each, рано или поздно он
сломается от того, что сожрет всю оперативку. 

Второй день уже не могу разобраться. Есть подозрение, что где-то я
скосячил в определениях. Возможно, кто-нибудь сможет мне помочь?
swizard
()

Scheme + functional programming

Изучаю сейчас сабж, и у меня возникли некоторые затруднения. Предположим, передо мной стоит простая задача: реализовать операции добавления числа и умножения на число некой последовательности чисел. Как это грамотно сделать с точки зрения функционального программирования? 

В sicp предлагается вариант некого подобия ОО, это бы выглядело так:

(define make-sequence
  (lambda (values-list)
    (lambda (message)
      (cond
       ((equal? message 'add)
        (lambda (number)
          (make-sequence
           (map (lambda (value) (+ value number))
                values-list))))
       ((equal? message 'scale)
        (lambda (number)
          (make-sequence
           (map (lambda (value) (* value number))
                values-list))))
       (else
        (display "Wrong message for make-sequence"))))))

И потом использование:

(define s (make-sequence (list 0 1 2 3)))

((s 'add)   4)
((s 'scale) 2)

Но, что-то, меня смущает эта псевдо-диспетчеризация :) А если мне надо будет миллион раз вызвать (s 'add), он ведь будет миллион раз делать cond, хотя я же явно ему указываю, что я хочу.

С другой стороны, мне явно надо определять нужные операции внутри make-sequence, чтобы получить замыкание, иначе придется все параметры передавать еще куда-то дальше, а если их не один, а десять, это тоже накладно :(

Сходу я придумал такой вариант, с возвращением списка замыканий:

(define make-sequence
  (lambda (values-list)
    (list
     (lambda (number)
       (make-sequence
        (map (lambda (value) (+ value number))
             values-list)))
     (lambda (number)
       (make-sequence
        (map (lambda (value) (* value number))
             values-list))))))

(define sequence-add
  (lambda (sequence number)
    ((car sequence) number)))

(define sequence-scale
  (lambda (sequence number)
    ((cadr sequence) number)))

И использование:

(define s (make-sequence (list 0 1 2 3)))

(sequence-add   s 4)
(sequence-scale s 2)

Тут много можно под макросы упаковать, но для наглядности я оставил так. Сразу видны минусы: чтобы выполнить операцию, надо ползти по списку, что тоже должно быть накладно :(

Есть какая-нибудь устоявшаяся практика в реализации таких вещей?
swizard
()

emacs jde-mode & generics

Народ, а кто-нибудь уже делал или видел поддержку java generics в jde-mode? Или все-таки самому писать придецца?

swizard
()

Задолбали уже дистрибутивы :)

Мб боян, но плз объясните мне, как закореннелому пользователю bsd, почему вы постоянно так активно возитесь с дистрибутивами? "Понравились шрифты в Kubuntu - заменил на нее FC" ~(c)

Ядро-то одно, неужели нельзя поставить один единственный дистрибутив (все равно какой) и потом на него уже вешать все, что требуется? Зачем ради emerge ставить генту, когда этот же емерж можно поставить пакаджем к слакваре?

swizard
()

RSS подписка на новые темы