Слишком мало аргументов lisp ошибка

I am trying to figure out the proper usage of funcall. I have this function:

(defun frame-add-slot (frame slot)
  (push (list slot) (rest (assoc frame *frames*))))

and I’m trying to get this other function to call it.

(defun frame-add-subframe (superframe subframe)
  (let ((res (push (list subframe) (rest *frames*))))
    (funcall (frame-add-slot) subframe 'ako))))

However, when I try to pass it two arguments in this fashion, clisp tells me the called function receives too few arguments. What am I doing wrong? *Frames* is my knowledge base. It looks like this:

(setf *frames* '((mammal
                  (eats 
                   (:value meat)
                   (:if-needed (food))))
                 (4-legged-animal
                  (ako
                   (:type mammal)
                   (:default beings))
                  (blood
                   (:type warm-blooded)))
                 (husky
                  (ako
                   (:type dog))
                  (origin
                   (:value alaska)
                   (:default north-america))
                  (roots
                   (:value unknown)))
                 (dog 
                  (ako 
                   (:type 4-legged-animal))
                  (exterior 
                   (:value furry)
                   (:default skin)))
                 (abner
                  (isa 
                   (:type husky)
                   (:default dog))
                  (shape 
                   (:weight 40-lbs)
                   (:height 20-inches)
                   (:color brown))
                  (acts
                   (:demeanor friendly)
                   (:sometimes rough)))
                 (gypsy
                  (isa 
                   (:default dog))
                  (acts
                   (:demeanor unpredictable))
                  (shapes
                   (:weight 45-lbs)
                   (:color black-and-brown)))))

Rainer Joswig's user avatar

Rainer Joswig

137k10 gold badges221 silver badges346 bronze badges

asked Sep 13, 2011 at 7:12

Sean Glover's user avatar

1

Can you explain why you need FUNCALL?

FRAME-ADD-SLOT is a normal named function and you can call it as such — without FUNCALL.

(defun frame-add-subframe (superframe subframe)
  (let ((res (push (list subframe) (rest *frames*))))
    (frame-add-slot subframe 'ako))))

Literal data

Later in your code you set *frames* to constant literal data. In your functions you are modifying this constant data. In standard Common Lisp the effect of these modifications is undefined. You need freshly allocated data structures — these can be modified without problems. See for example the function COPY-TREE to recursively make a fresh copy of a deeply nested list. The result of COPY-TREE can be modified.

answered Sep 13, 2011 at 8:08

Rainer Joswig's user avatar

Rainer JoswigRainer Joswig

137k10 gold badges221 silver badges346 bronze badges

There’s several problems with your frame-add-subframe function:

  1. Why are you using funcall in this instance? You should be able to directly call frame-add-slot: (frame-add-slot subframe 'ako)
  2. If the funcall usage is merited, then you’d use it like this: (funcall #'frame-add-slot subframe 'ako)
  3. I presume that instead of specifying 'ako hardcoded, you meant to use res somehow? That variable is unused.

answered Sep 13, 2011 at 7:46

C. K. Young's user avatar

C. K. YoungC. K. Young

220k46 gold badges383 silver badges436 bronze badges

In (funcall (frame-add-slot) subframe 'ako)))), you are calling frame-add-slot by putting parens around it.

Try (funcall #'frame-add-slot subframe 'ako).

answered Sep 13, 2011 at 7:42

Paul Nathan's user avatar

Paul NathanPaul Nathan

39.6k29 gold badges112 silver badges213 bronze badges

0

We have installed the latest Autodesk 2021 and one of our scripts (a modified @Lee Mac) which strips and formats some input text now fails. This script runs perfectly on 2019 and below. I can’t seem to work out why there is a difference.

I have substituted the original «vl-catch-all-apply» to «apply» so I could catch the error. The error is:

Too few arguments

This occurs as it hits the ‘(lambda function call. The code is below with the call:

(defun GDD:removeinfo (rgx str)
(if
    (null
        (vl-catch-all-error-p
            (setq str
                (apply
                   '(lambda nil
                        (vlax-put-property rgx 'global     actrue)
                        (vlax-put-property rgx 'multiline  actrue)
                        (vlax-put-property rgx 'ignorecase acfalse) 
                        (foreach pair
                           '(
                                ("\032"     . "\\\\\\\\")
                                ("\n"        . "\\\\P")
                                ("$1"       . "\\\\(\\\\[ACcFfHKkLlOopQTW])|\\\\[ACcFfHKkLlOopQTW][^\\\\;]*;|\\\\[ACcFfKkHLlOopQTW]")
                                ("$1$2/$3"  . "([^\\\\])\\\\S([^;]*)[/#\\^]([^;]*);")
                                ("$1$2"     . "\\\\(\\\\S)|[\\\\](})|}")
                                ("$1"       . "[\\\\]({)|{")
                                ("\\$1$2$3" . "(\\\\[ACcFfHKkLlOoPpQSTW])|({)|(})")
                                ("\\\\"     . "\032")
                                (""     . "(?:.*\\n)*Const\\s+.*\\n")
                                        (""     . "\\w\\w\\d?\\s+\\d+\\s\\d+-\\d+-\\d+")
                                        (""     . "^\\s+\\n")
                            )
                            (vlax-put-property rgx 'pattern (cdr pair))
                            (setq str (vlax-invoke rgx 'replace str (car pair)))
                        )
                    )
                )
            )
        )
    )
    str
)
)

The call to this function is below. I’ve checked the «input» and it is identical to the 2019 version that works and the str is populated properly using the vlisp (vscode) debugger. I’ve run the same code and input through both and only the 2021 version fails?

(setq input (GDD:removeinfo (vlax-get-or-create-object "VBScript.RegExp") input))

I’m not that familiar with LISP and I’m stuck. Thanks for your help.

asked May 22, 2020 at 6:37

Rob Mascaro's user avatar

Rob MascaroRob Mascaro

8018 silver badges16 bronze badges

Assuming <FUN> stands for:

'(lambda nil
  (vlax-put-property rgx 'global     actrue)
  (vlax-put-property rgx 'multiline  actrue)
  (vlax-put-property rgx 'ignorecase acfalse) 
  (foreach pair
   '(("\032"     . "\\\\\\\\")
     ("\n"        . "\\\\P")
     ("$1"       . "\\\\(\\\\[ACcFfHKkLlOopQTW])|\\\\[ACcFfHKkLlOopQTW][^\\\\;]*;|\\\\[ACcFfKkHLlOopQTW]")
     ("$1$2/$3"  . "([^\\\\])\\\\S([^;]*)[/#\\^]([^;]*);")
     ("$1$2"     . "\\\\(\\\\S)|[\\\\](})|}")
     ("$1"       . "[\\\\]({)|{")
     ("\\$1$2$3" . "(\\\\[ACcFfHKkLlOoPpQSTW])|({)|(})")
     ("\\\\"     . "\032")
     (""     . "(?:.*\\n)*Const\\s+.*\\n")
     (""     . "\\w\\w\\d?\\s+\\d+\\s\\d+-\\d+-\\d+")
     (""     . "^\\s+\\n"))
   (vlax-put-property rgx 'pattern (cdr pair))
   (setq str (vlax-invoke rgx 'replace str (car pair)))))

The code you posted, rewritten more compactly, looks as follows:

(defun GDD:removeinfo (rgx str)
  (if (null (vl-catch-all-error-p
             (setq str (apply <FUN>))))
      str))

In particular, the call to APPLY has only one argument:

(apply <FUN>)

APPLY in Autolisp is a function of 2 parameters: a function, and a list of arguments.

The intent is that:

(apply f '(0 1))

… is evaluated as-if you called (f 0 1), but with possibility of building the list of arguments at runtime.

You only gave one argument to apply in your code, so you need to also pass a list of arguments.
In your case, that would be the empty list:

(apply <FUN> nil)

answered May 22, 2020 at 13:10

coredump's user avatar

coredumpcoredump

37.8k5 gold badges43 silver badges77 bronze badges

3

Instead of changing vl-catch-all-apply to apply in order to see the error, simply output the error as part of the else branch of the if statement, for example:

(if
    (null
        (vl-catch-all-error-p
            (setq str
                (vl-catch-all-apply
                    ...
                )
            )
        )
    )
    str
    (prompt (strcat "\nError: " (vl-catch-all-error-message str))) ;; Output error and return nil
)

Aside, whilst this code is relatively trivial, I’m not sure whether I agree with you appropriating 95% of the code for my function and stripping off my heading and author prefix.

answered May 22, 2020 at 15:50

Lee Mac's user avatar

Lee MacLee Mac

15.7k6 gold badges33 silver badges80 bronze badges

4

Whoever wrote that code seemed not to be aware of the progn operator.

So that is to say, if we want to evaluate multiple expressions e1, e2, … for the sake of a side effect that they produce, we do not have to do this:

;; wrap expressions in a dummy lambda and apply empty arg list to it
(apply (lambda () e1 e2 ...) nil)

We can just write this:

(progn e1 e2 ...)

That still leaves us with a strange code smell which looks like this:

(setq str (progn .... (setq str value)))

The code is assigning the variable str twice with the same value. The deeply nested (setq str value) puts value into str and then yields that value as a result. It’s the last expression of the progn (originall, of the lambda) and so that value is also returned. Then the outer setq wastefully stores it in str again. We just need one or the other:

;; set str as the side effect of the last form in the
;; progn; also yield that value.
(progn e1 e2 ...(setq str value))

;; assign value yielded from progn to str, then also
;; yield that value.
(setq str (progn e1 e2 ... value))

answered May 28, 2020 at 14:44

Kaz's user avatar

KazKaz

56.2k9 gold badges102 silver badges149 bronze badges

1


@Shneuph wrote:

Kent — I still don’t fully understand the differences between C: functions and ones w/o the «C:» and how they are used differently.  I do know that some built-in autolisp functions have «optional» arguements which you cannot have with a C: function.  To get around this I have something like C:Symbol (P1 P2 P3 Poptional1 Poptional2 / etc etc)

Then in the lisp I just test to see if Poptional1 or Poptional2 are nil and if so adjust appropritely.  Then call the function like

(C:Symbol «p1» «p2» «p3» «po1» nil)

In the lisp it will have:

(if Poptional1

  (do this)
);if

(if Poptional2

  (do this)

);if


Things defined with the C:, e.g. (defun C:Whatever… are commands [I assume that’s what the C stands for], though they are also sometimes referred to as routines, and their command names can be typed at the Command: prompt line without parentheses, as with other commands, or put in menu items, scripts, etc.  But since they’re not native AutoCAD commands, they can’t be used in a Lisp (command) function if they need to be called from inside other Lisp routines, but need to be in parentheses with the C: included.  They’re not supposed to have arguments, though that doesn’t seem to be absolute [see Message 4].  But they can have localized variables.

Things defined without the C:, e.g. (defun Whatever… are usually called routines, or sub-routines, or maybe some other things.  [Sometimes someone will refer to one as a function, but that has the potential to be confused with what are properly called functions: those listed in the AutoLISP Reference, including (defun) itself.]  You can’t type their bare names at the Command: prompt line, though you can type them there included in parentheses, but usually they are used from within other routines, similarly to the way AutoLISP functions are used.  They can have arguments [though they don’t always need to], as well as localized variables.

In your example, if you’re going to use it by calling it from inside another Lisp function/routine, I would just define it as a routine/sub-routine, not as a command, since the C: isn’t doing anything for you:(defun Symbol (P1 P2 P3 Poptional1 Poptional2 / etc etc)

and use it the way functions/routines/sub-routines are used:

(Symbol p1 p2 p3 po1 nil)

[Note no quotation marks around the arguments — I’m assuming those are variables holding some kind of value, and not actually text strings.]

Kent Cooper, AIA

Please, help me with this program to toggle multiple wire numbers.

Error: too few arguments…

Private Sub ToggleWireNum()

Dim x As AcadEntity

Dim blk As AcadBlock

On Error Resume Next

For Each x In ThisDrawing.ModelSpace

    If TypeName(x) = «IAcadLine» Then

        ThisDrawing.SetVariable «USERS1», x.Handle

        WDCommand («(setq return (c:ace_get_wnum (handent (getvar «»USERS1″»))))» & vbCr)

        WDCommand («(setvar «»USERS2″» (car return))» & vbCr)

        If Len(ThisDrawing.GetVariable(«USERS2»)) > 0 Then

            WDCommand («(setq en (cadr return))» & vbCr)

            WDCommand («(c:ace_toggle_inline en)» & vbCr)

        End If

    End If

Next x

End Sub

Public Sub WDCommand(Command As String)

‘ This function calls lisp function

ThisDrawing.SendCommand (Command)

End Sub

Public Sub WDForceStart()

Call WDCommand(«(if(not wd_load)(if(setq x(findfile «»wd_load.lsp»»))(load x)))(wd_load)» & vbCr)

End Sub

Кто бы ни писал этот код, похоже, не знал о progn оператор.

То есть, если мы хотим оценить несколько выражений e1, e2,… из-за побочного эффекта, который они производят, нам не нужно этого делать:

;; wrap expressions in a dummy lambda and apply empty arg list to it
(apply (lambda () e1 e2 ...) nil)

Мы можем просто написать это:

(progn e1 e2 ...)

Это по-прежнему оставляет нам странный запах кода, который выглядит так:

(setq str (progn .... (setq str value)))

Код присваивает переменную strдважды с одинаковым значением. Глубоко вложенный(setq str value) ставит value в strа затем возвращает это значение в качестве результата. Это последнее выражениеprogn (первоначально из lambda), и это значение также возвращается. Тогда внешнийsetq расточительно хранит это в strеще раз. Нам просто нужно одно или другое:

;; set str as the side effect of the last form in the
;; progn; also yield that value.
(progn e1 e2 ...(setq str value))

;; assign value yielded from progn to str, then also
;; yield that value.
(setq str (progn e1 e2 ... value))

Понравилась статья? Поделить с друзьями:

Интересное по теме:

  • Слова песни ошибка вышел покурить
  • Следственные ошибки учебник
  • Скриншот ошибки что это такое
  • След врачебная ошибка
  • Слова песни список ошибок

  • Добавить комментарий

    ;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: