Luna Posté(e) le 22 avril 2020 Posté(e) le 22 avril 2020 Bonjour, Petite question (sûrement idiote), mais je me demandais si l'on avait la possibilité de créer une fonction avec un nombre d'argument non défini/non fixe. Par exemple la fonction '+ additionne l'ensemble des nombres spécifiés en argument, donc elle ne possède pas un nombre fixe d'argument comme la fonction 'car : (+ 1 2 3 4 5 ... n) J'ai trouvé ce post mais j'ai l'impression qu'il s'agit d'une version différente (à vrai dire je suis perdue entre les LISP, Visual LISP, ActiveX, Common LISP, ...) --"J'ai testé ceci : (defun test (a b &rest c) (if c a b ) ) commande:(test 0 1) ; erreur: nombre d'arguments insuffisants commande:(test 0 1 T) ; erreur: nombre d'arguments insuffisants commande:(test 0 1 T T) 0 commande:(test 0 1 T nil) 1 commande:(test 0 1 nil T) 0 Donc en clair, il ne reconnaît pas l'écriture &rest et le comprend comme un argument quelconque et non un keyword...J'ai essayé également avec le keyword &optional mais même résultat...Voici un extrait de la source de cette info (GNU Emacs Lisp Reference Manual) :In a function description, the name of the function being described appears first. It isfollowed on the same line by a list of argument names. These names are also used in thebody of the description, to stand for the values of the arguments.The appearance of the keyword &optional in the argument list indicates that the subsequent arguments may be omitted (omitted arguments default to nil). Do not write&optional when you call the function.The keyword &rest (which must be followed by a single argument name) indicates thatany number of arguments can follow. The single argument name following &rest receives,as its value, a list of all the remaining arguments passed to the function. Do not write&rest when you call the function.Here is a description of an imaginary function foo:foo integer1 &optional integer2 &rest integers [Function]The function foo subtracts integer1 from integer2, then adds all the rest of thearguments to the result. If integer2 is not supplied, then the number 19 is used bydefault.(foo 1 5 3 9)⇒ 16(foo 5)⇒ 14Avez-vous déjà étudié cette question, est-ce seulement possible sur de la programmation basique avec AutoLISP 2018 ? L'idée derrière cette question c'est pour éviter d'avoir à écrire deux fonctions quasi identiques ou bien d'avoir à me trimbaler une variable nil dans l'utilisation de cette fonction.. ;; Définition deux deux fonctions quasi-identiques : (defun func1 (arg1 arg2 / ...) [expr...] jsel ) ;;Renvoie un jeu de sélection (defun func2 (arg1 arg2 / ...) [expr...] (princ rslt) ) ;;Renvoie le contenu du jeu de sélection ;;========================================================;; ;;Définition d'un argument prompteur (defun func (arg1 arg2 display / ...) [expr...] (if display (princ rslt) jsel ) ) ;; Donc à l'utilisation, il faudra obligatoirement écrire (func arg1 arg2 nil). ;;========================================================;; ;;Utilisation d'un argument optionnel (defun func (arg1 arg2 &rest display / ...) [expr...] (if display (princ rslt) jsel ) ) ;; Donc (func arg1 arg2) et (func arg1 arg2 nil) renverront le même résultat Bisous,Luna
(gile) Posté(e) le 22 avril 2020 Posté(e) le 22 avril 2020 Salut, Pas d'arguments optionnels en AutoLISP / Visual LISP.Le seul moyen de contourner serait de passer comme argument une liste contenant les arguments. Mais je trouve ça lourdingue de tester la présence (et/ou le type) des arguments contenus dans la liste. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Luna Posté(e) le 22 avril 2020 Auteur Posté(e) le 22 avril 2020 Salut, En effet j'avais déjà penser à cette solution mais en effet ça demande d'avoir un cond assez complexe pour prendre en compte toutes les possibilités par rapport aux argumentsAprès dans mon cas, ça ne serait pas si complexe que ça puisque qu'il s'agit plutôt d'un argument optionnel et non un nombre d'argument indéfini.. Je trouve tout de même dommage que cela ne soit pas possible...Et dans ce cas, à quoi fait référence le document GNU Emacs Lisp Reference Manual ..? --" Merci de ta réponse en tout cas ! :3 Bisous,Luna
(gile) Posté(e) le 22 avril 2020 Posté(e) le 22 avril 2020 Et dans ce cas, à quoi fait référence le document GNU Emacs Lisp Reference Manual ..? --"À un autre dialecte LISP appelé Emacs LISP. Depuis 1958 et l'invention du LISP nombre de dialectes ont vu le jour et certains sont toujours utilisés comme Common LISP, Emacs LISP, Scheme, Clojure et bien sûr AutoLISP. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Luna Posté(e) le 22 avril 2020 Auteur Posté(e) le 22 avril 2020 Oki doki, merci beaucoup pour ces précisions :3 Bisous,Luna
bonuscad Posté(e) le 22 avril 2020 Posté(e) le 22 avril 2020 Ça me rappelle cette réponse que j'avais faite. Je n'ai jamais compris comment ceci était possible de construire une fonction de la sorte. Çà relance le sujet Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius
(gile) Posté(e) le 22 avril 2020 Posté(e) le 22 avril 2020 Avec ObjectARX ou .NET, on peut définir des fonctions LISP qui, comme les fonctions "natives" peuvent avoir des arguments optionnels. Il y a quelques temps j'avais commis quelques fonctions LISP (CF LISP Extension sur cette page) dont une pour forcer les propriétés des calques par fenêtre.La fonction accepte de 3 à 6 arguments, le troisième (couleur) peut être un entier (code ACI), une liste de 3 entiers (Rouge Vert Bleu) ou une liste de 2 chaînes pour les couleurs nommées (nom carnet) Extarit de l'aide:(gc-vplayeroverride fenetre calque couleur [typeLigne [epaisseurLigne [styleTrace]]]) Argumentsfenetre (ename) Le nom d'entité de la fenêtre. calque (string) Le nom du calque. couleur (int ou (red green blue) ou (colorName bookName)) L'index ou une liste de trois bytes (rouge vert bleu) ou une liste de deux chaînes (nom_de_la_couleur nom_du_carnet) pour la couleur à attribuer au calque (ou nil). typeLigne (int) optionelLe nom du type de ligne à attribuer au calque (ou nil). epaisseurLigne (int) optionelUn entier valide pour l'épaisseur de ligne à attribuer au calque (-3 = défaut, 0 = 0.00mm, 5 = 0.05mm, 15 = 0.15mm, 100 = 1.00mm, etc.). styletrace (string) optionelLe nom du style de tracé à attribuer au calque (uniquement STB). Valeur retournéeT si l'opération s'est bien passée, nil sinon. Exemple (gc-vplayeroverride (car (entsel)) "Calque1" 40 nil 35) La quasi totalité du code consiste à vérifier le nombre et le type des arguments (CF tous les : throw new *Exception;). // (gc-VpLayerOverride viewportEname layerName colorIndex [lineType [lineWeight [plotStyle]]]) // (gc-VpLayerOverride viewportEname layerName RGBlist [lineType [lineWeight [plotStyle]]]) // (gc-VpLayerOverride viewportEname layerName colorBookName [lineType [lineWeight [plotStyle]]]) [LispFunction("gc-VpLayerOverride")] public TypedValue VpLayerOverride(ResultBuffer resbuf) { int i = 0; try { if (Application.Version.Major < 17 && Application.Version.Minor < 1) { throw new LispException("only available for AutoCAD 2008 and later"); } Document doc = AcAp.DocumentManager.MdiActiveDocument; Database db = doc.Database; ObjectId vpId; string layer; if (resbuf == null) { throw new TooFewArgsException(); } TypedValue[] args = resbuf.AsArray(); if (args.Length < 3) { throw new TooFewArgsException(); } if (args.Length > 9) { throw new TooManyArgsException(); } if (args[i].TypeCode == (short)LispDataType.ObjectId) vpId = (ObjectId)args[i++].Value; else { throw new ArgumentTypeException("lentityp", args[i]); } if (args[i].TypeCode == (short)LispDataType.Text) layer = (string)args[i++].Value; else { throw new ArgumentTypeException("stringp", args[i]); } using (Transaction tr = db.TransactionManager.StartTransaction()) { Viewport vp = tr.GetObject(vpId, OpenMode.ForRead) as Viewport; if (vp == null) { throw new LispException("bad entity type"); } LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); if (!lt.Has(layer)) { throw new LispException("unknown layer"); } LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(lt[layer], OpenMode.ForWrite); LayerViewportProperties lvp = ltr.GetViewportOverrides(vpId); if (args[i].TypeCode != (short)LispDataType.Nil) { if (args[i].TypeCode == (short)LispDataType.Int16) { short colorIndex = (short)args[i++].Value; if (colorIndex < 0 || colorIndex > 256) { throw new LispException("incorrect color index"); } switch (colorIndex) { case 0: lvp.Color = Color.FromColorIndex(ColorMethod.ByBlock, 0); break; case 256: lvp.Color = Color.FromColorIndex(ColorMethod.ByLayer, 256); break; default: lvp.Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex); break; } } else if (args[i].TypeCode == (short)LispDataType.Point3d) { Point3d pt = (Point3d)args[i++].Value; try { byte red = (byte)pt.X; byte green = (byte)pt.Y; byte blue = (byte)pt.Z; lvp.Color = Color.FromRgb(red, green, blue); } catch { throw new LispException("incorrect RGB values"); } } else if (args[i].TypeCode == (short)LispDataType.ListBegin) { if (args[i + 1].TypeCode == (short)LispDataType.Text) { string colorName = (string)args[++i].Value; if (args[++i].TypeCode != (short)LispDataType.Text) { throw new ArgumentTypeException("stringp", args[i]); } string bookName = (string)args[i].Value; try { lvp.Color = Color.FromNames(colorName, bookName); i += 2; } catch { throw new LispException("unknown color name"); } } else { throw new ArgumentTypeException("fixnump or stringp", args[i + 1]); } } else { throw new ArgumentTypeException("fixnump or listp", args[i]); } } if (args.Length > i + 3) { throw new TooManyArgsException(); } if (args.Length > i) { if (args[i].TypeCode != (short)LispDataType.Nil) { if (args[i].TypeCode != (short)LispDataType.Text) { throw new ArgumentTypeException("stringp", args[i]); } string lType = (string)args[i++].Value; LinetypeTable ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead); if (!ltt.Has(lType)) { throw new LispException("unknown line type"); } lvp.LinetypeObjectId = ltt[lType]; } if (args.Length > i) { if (args[i].TypeCode != (short)LispDataType.Nil) { if (args[i].TypeCode != (short)LispDataType.Int16) { throw new ArgumentTypeException("numberp", args[i]); } short lWeight = (short)args[i++].Value; try { lvp.LineWeight = (LineWeight)lWeight; } catch { throw new LispException("incorrect line weight"); } } if (args.Length > i) { if (args[i].TypeCode != (short)LispDataType.Nil && (short)AcAp.GetSystemVariable("pstylemode") == 0) { if (args[i].TypeCode != (short)LispDataType.Text) { throw new ArgumentTypeException("stringp", args[i]); } string plotStyle = (string)args[i].Value; try { lvp.PlotStyleName = plotStyle; } catch { throw new LispException("unknown plot style"); } } } } } object lrc = AcAp.GetSystemVariable("layoutregenctl"); AcAp.SetSystemVariable("layoutregenctl", 0); vp.UpgradeOpen(); vp.On = false; vp.On = true; AcAp.SetSystemVariable("layoutregenctl", lrc); tr.Commit(); } return new TypedValue((short)LispDataType.T_atom); } catch (LispException ex) { AcAp.ShowAlertDialog(ex.Message); throw; } catch (System.Exception ex) { AcAp.ShowAlertDialog(ex.Message); throw; } } Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Fraid Posté(e) le 22 avril 2020 Posté(e) le 22 avril 2020 Bonjour, Sujet qui m'a interrogé aussi Voir ici Une limitation du langage fonctionnel. https://github.com/Fraiddd
zebulon_ Posté(e) le 22 avril 2020 Posté(e) le 22 avril 2020 BonjourEn autolisp le nombre d'arguments des fonctions créées par défun est fixe, contrairement aux fonctions lisp elles-mêmes qui acceptent très souvent des arguments optionnels.Il y a la possibilité de contourner avec la solution évoquée par (gile) en utilisant un seul paramètre qui est une liste.Sinon, sachant que la possibilité de créer des arguments optionnels n'existe pas, je définis tous les arguments dans la liste et ceux qui peuvent être optionnels valent nil lorsqu'il ne faut pas en tenir compte et une valeur dans le cas contraire.Un argument qui vaut nil c'est facile à vérifier.AmicalementVincent C'est au pied du mur que l'on reconnaît le maçon ! (Anonyme) C’est en restant au pied du mur qu’on ne voit que le mur (Anonyme aussi)
Messages recommandés
Créer un compte ou se connecter pour commenter
Vous devez être membre afin de pouvoir déposer un commentaire
Créer un compte
Créez un compte sur notre communauté. C’est facile !
Créer un nouveau compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant