Как увеличить переменную в Лиспе

Вот проблема в коде:

    (foreach n l_pt
        (write-line
            (strcat "sommet" str_sep
                (itoa (setq (nbs (+1 nbs )))) str_sep
                (rtos (car n) 2 2) str_sep
                (rtos (cadr n) 2 2) str_sep
                (strcat "2") str_sep
                (strcat "borne")
            )
            f_open
        )
    )
    ;;(write-line "" f_open)

У меня есть такие файлы на выходе:

Sommets;;

Тип;Num;X;Y;Precison; Природа

Sommet;1;1532292,16;3214140,11; 2; Borne

Sommet;2;1532287,08;3214140,60;2; Borne

Sommet;1;1532291,45;3214136,43; 2; Borne

Sommet;2;1532286,50; 3214135,87;2; Borne

Sommet;1;1532287,08;3214140,60;2; Borne

Как вы уже догадались, проблемной частью является "Num", который не работает, как задумано, увеличивается.

Я понял, что это такая строка: " (itoa (setq (nbs (+1 nbs)))) str_se" не работает, как предполагалось, но я не знаю почему. Я пытался переключить его на (setq (nbs (+ 1 nbs))), но он тоже не работает.

Есть ли у вас идеи, откуда это идет?

Полный код

2 ответа

Я думаю, что проблема в том, что у вас одна скобка. Или что вам нужно инициализировать nbs вне повторения. Это зависит от того, как вы хотите, чтобы это работало.

Похоже, ваш код (значительно упрощенный) выглядит так:

;; Stuff before the problem
(repeat (sslength js)
    ;; (setq....)
    (setq nbs 0)
    ;;; Lots of stuff
    (foreach n l_pt
        ;; The printing code including...
        (setq nbs (+ 1 nbs))
    )
)

Как видите, вы устанавливаете nbs в 0 каждый раз, когда вы проходите через repeat цикл, а затем добавление 1 к этому позже.

Похоже, вы хотели разделить эти петли - repeat пока не закончится расчет информации, а затем foreach распечатать весь список l_pt,

На мой взгляд, вы добавляете только 1 строку информации l_pt каждый раз через большой repeat цикл и только печать, что один элемент из foreach заявление.

Перемещение скобок даст вам это:

(repeat (sslength js)
    ;;...
    (setq nbs 0)
    ;;...
)
(foreach n l_pt
    ;;...
    (setq nbs (+ 1 nbs))
)

Вы также можете разместить (setq nbs 0) вне повторного цикла. Это, вероятно, было бы лучше в любом случае, чтобы было ясно, что вы делаете, и нет необходимости инициализировать его 5+ раз...

Кроме того, это показывает, почему стоит четко разделить присвоения переменных. Они могут потеряться в конце долгого (setq) заявление:

;; Do this,
(setq sentence "This is one or more variable assignments."
      number 200)

;; or this,
(setq sentence "This is one or more variable assignments.")
(setq number 200)

;; not this.
(setq sentence "This is one or more variable assignments." number 200)

В любом случае, любой из этих вариантов должен получить ваш счетчик nbs снова работает

Надеюсь, это поможет!

PS Просто чтобы помочь с обсуждением (+1 nbs) в комментариях выше, в AutoLISP все правильно и эквивалентно:

(+ 1 nbs)
(+ nbs 1)         ;; Order is not important for addition
(+ nbs 1 0 0 0)   ;; Any number of values can be added
(1+ nbs)          ;; The typical way to increment a value
                  ;; (1+ is a function that returns the value + 1)

Это должно быть что-то особенное для AutoLISP. Я говорю это потому, что этот код (адаптированный к Common Lisp, как вы увидите)

(defun foo (l_pt)
  (let ((str_sep ";")
        (nbs 0))

    (mapcar #'(lambda (n) (write-line (strcat (list "sommet" str_sep
                                                    (itoa (setq nbs (+ 1 nbs))) str_sep
                                                    (rtos (car n) 2 2) str_sep
                                                    (rtos (cadr n) 2 2) str_sep
                                                    (strcat "2") str_sep
                                                    (strcat "borne")))
                                      ))
            l_pt)))

(defun rtos (a b c) (strcat a))

(defun strcat (string-designators)
  (with-output-to-string (strcat)
    (cond ((listp string-designators)
           (mapcar #'(lambda (s) (princ s strcat)) string-designators))
          (t (princ string-designators strcat)))))

(defun itoa (i) (write-to-string i))

для этого выражения:

(foo '((x y) (a b) (aa bb)))

производит этот вывод:

sommet;1;X;Y;2;borne
sommet;2;A;B;2;borne
sommet;3;AA;BB;2;borne

По общему признанию, мне пришлось изменить многие вещи, чтобы приспособить элементы AutoLISP, которых нет в Common Lisp, возможно, наиболее значимым из которых является то, что я не написал эквивалент foreach (потому что нет никакого способа узнать, что я бы повторил его идиосинкразии), но тем не менее это как минимум появляется setq делает то, что вы ожидаете.

Другие вопросы по тегам