| |
| Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte |
| |
| PNY präsentiert die neue NVIDIA RTX A400 und die A1000 Grafikkarte, eine Pressemitteilung
|
Autor
|
Thema: Abfrage konstruktion (2482 mal gelesen)
|
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 06. Jun. 2013 15:24 <-- editieren / zitieren --> Unities abgeben:
Hallo Leute! Ein Thema, welches mich immer wieder beschäftigte: wie ich Abfragen eleganter veranschaulichen kann, ohne immer 2 neue Variablen für Ansicht-, Eingabewert einzugeben. Das Ergebnis sieht so aus oder findet ihr einen besseren Weg. Code:
(defun abfrage (aufruf ans str) (if (null ans) (setq ans " ")) (if (= "" (setq str (strcase (getstring (strcat "\n" aufruf ": <" ans ">"))) ) ) (setq str (strcase ans)) (setq ans (strcase str)) ) ) ; -------------------------- ; Abfrage eines Zahlenwertes ; -------------------------- (setq zahl (fix (distof (abfrage "\nZahl eingeben: " (if (null zahl) (setq zahl "0") (rtos zahl 2 0) ) zahl ) ) ) ) ; --------------------- ; Abfrage eines Strings ; --------------------- (setq string (abfrage "\nText eingeben: " (if (null string) (setq string " ") string ) string ) )
------------------ Gruss Dirk http://cadplayerlounge.blogspot.se Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
joern bosse Ehrenmitglied Dipl.-Ing. Vermessung
Beiträge: 1763 Registriert: 11.10.2004 Window 11 ACAD 2021 CIVIL 2021 BricsCAD ab V14 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz 2.80 GHz 32.0GB RAM NVIDIA GeForce MX450<P>
|
erstellt am: 06. Jun. 2013 16:11 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Hallo Dirk, ich würde über eine COND-Schleife in der Abfrage-Funktion eine TYPEn-Prüfung durchführen, und dann entsprend des Typ's auch die verschiedenen Eingabefunktion verwenden, GETSTRING, GETINT, GETREAL (könntest Du Dir noch mit einbauen). Ist aber nur ein Variante, das gibt es sicherlich sehr viele Ansätze, Deins hat doch auch funktioniert. Code:
(defun abfrage (aufruf ans / RETVAL) (if (cond ((=(type ans) 'INT) (setq retval(getint(abfrage:String aufruf (itoa ans))))) ((=(type ans) 'STR) (and(setq retval(getstring (abfrage:String aufruf ans))) (/= retval "")))) retval ans)) (defun abfrage:String (aufruf ans / ) (strcat "\n" aufruf ": <" ans ">")) ; -------------------------- ; Abfrage eines Zahlenwertes ; -------------------------- (setq zahl (abfrage "\nZahl eingeben" (if zahl zahl 0))) ; --------------------- ; Abfrage eines Strings ; --------------------- (setq string (abfrage "\nText eingeben" (if string string "")))
Eine Anmerkung noch, am Ende einer Funktion kannst Du Dir das SETQ grundsätzlich sparen, es wird der letzte Wert der Funktion auch so an die aufrufenden Funktion übergeben.
------------------ viele Grüße Jörn http://www.bosse-engineering.com Koordinatenausgabe Youtube Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 06. Jun. 2013 16:26 <-- editieren / zitieren --> Unities abgeben:
|
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 06. Jun. 2013 16:59 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
meine Variante Code:
(defun abfrage (txt default / get-x Out) (setq get-x (cond ((= (type default) 'STR) getstring) ((= (type default) 'INT) getint) ) ) (if get-x (if (setq Out (get-x (strcat "\n" txt " <"(vl-princ-to-string default) ">: "))) Out default ) ) );;;;; (abrage "Zahl eingeben" 0) (abfrage "Text eingeben" "---")
[Diese Nachricht wurde von reltro am 06. Jun. 2013 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 06. Jun. 2013 17:14 <-- editieren / zitieren --> Unities abgeben:
Hallo reltro! Ich sehe du hast den Code, um einiges verkürzen können. Nur eines fehlt mir, dass bei wiederholtem Aufruf, die zuletzt eingegebenen Werte nicht angezeigt werden. An meinem Beispiel speichere ich die Werte für Aufruf Zahl und Aufruf Text zuvor ab. ------------------ Gruss Dirk http://cadplayerlounge.blogspot.se Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 06. Jun. 2013 17:18 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
|
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 06. Jun. 2013 17:28 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Man könnte dem ganzen natürlich noch einen gloablen touch geben... Code:
(defun abfrage (txt default / ) (set default ( (lambda (d / get-x Out) (setq get-x (cond ((= (type d) 'STR) getstring) ((= (type d) 'INT) getint) ) ) (if get-x (if (setq Out (get-x (strcat "\n" txt " <"(vl-princ-to-string d) ">: "))) Out d ) d ) ) (eval default) ) ) )
Nun aber so...
Code:
(setq Zahl 0)(repeat 10 (abfrage "Zahl eingeben" 'Zahl) ) (princ Zahl)
Man beachte das 'Zahl gequotet übergeben wird Würde jedoch die erste Vraiante bevorzugen, weil sobald du bei dieser (2ter) anstatt das Symbol 'Zahl vielleicht das Symbol 'txt verwendest es nicht läuft; das hat den einfachen Grund dass die Funktion einen Seiteneffekt (das setzen der Variable; hier 'Zahl) beinhaltet. Die erste Variante enthält keine Seiteneffekte, läuft demnach "immer"...
lg [Diese Nachricht wurde von reltro am 06. Jun. 2013 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 06. Jun. 2013 18:33 <-- editieren / zitieren --> Unities abgeben:
|
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 07. Jun. 2013 15:16 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
kleiner Fehler... bei getstring unnötigerweise gibt ein enter bei (getstring) kein nil zurück sondern ein "" im nachfolgenden korrigiert... Code:
(defun abfrage (txt default / ) (set default ( (lambda (d / get-x Out) (setq get-x (cond ((= (type d) 'STR) getstring) ((= (type d) 'INT) getint) ) ) (if get-x (if (and (setq Out (get-x (strcat "\n" txt " <"(vl-princ-to-string d) ">: "))) (not (= Out "")) ) Out d ) d ) ) (eval default) ) ) )
bzw. Code:
(defun abfrage (txt default / get-x Out) (setq get-x (cond ((= (type default) 'STR) getstring) ((= (type default) 'INT) getint) ) ) (if get-x (if (and (setq Out (get-x (strcat "\n" txt " <"(vl-princ-to-string default) ">: "))) (not (= Out "")) ) Out default ) ) )
lg Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 13. Jun. 2013 08:26 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Liest du noch mit Cadplayer? Noch eine Variante; dieses Mal ein wenig anders... Da ich gerade "Objekte" programmiere, hier eine einfache Variante für die Abfrage... Dem gegebenen Symbol [ref_default] wird eine Funktion gegeben welche die eigentliche Abfrage beinhaltet, sowie den Default-Wert bzw. den letzten Wert der eingegeben wurde. Code:
(defun abfrage (txt ref_Default Default / ) ;---- (setq expr (lambda (currentDefault txt ask-p / get-x) (if ask-p (progn (setq get-x (cond ((= (type currentDefault) 'INT) getint) ((= (type currentDefault) 'STR) getstring) ) ) (setq Out (if get-x (get-x (strcat "\n" txt " <" (vl-princ-to-string currentDefault) ">:")))) (if (or (null Out) (= Out "")) currentDefault Out ) ) currentDefault ) ) ) ;---- ( (lambda (meta / ) (meta meta ref_Default expr Default txt) ) (lambda (meta name expr default txt / ) (set name (list '(ask-p / Out) (list 'quote default) (list meta meta (list 'quote name) expr (list 'setq 'Out (list expr (list 'eval (list 'nth 1 name)) txt 'ask-p)) txt ) 'Out ) ) ) ) ref_Default )
Zum Anwenden:
Code:
(abfrage "Gib mir eine Zahl!" 'meineAbfrage 10)(meineAbfrage 'T) ;;fragt ab und gibt den gegebenen Wert zurück und speichert diesen in sich selber. (meineAbfrage 'nil) ;;gibt den gespeicherten Wert ohne Abfrage zurück (meinAbfrage 'T) ;;fragt ab . . .
einfach testen
lg Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 13. Jun. 2013 12:35 <-- editieren / zitieren --> Unities abgeben:
|
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 14. Jun. 2013 15:58 <-- editieren / zitieren --> Unities abgeben:
Ehrlich gesagt, ich peil es nicht - es schaut echt interessant aus was du da fabrizierst nur kann ich dem schwer folgen In den oberen Teil erkenne ich die Zeilen aus dem vorangegangen Code. Desweiteren und jetzt wird es spannend was macht denn eigentlich
Code: (lambda (meta / ) (meta meta ref_Default expr Default txt) )
und gleich hinten drein
Code: (lambda (meta name expr default txt / ) (set name (list '(ask-p / Out) (list 'quote default) (list meta meta (list 'quote name) expr (list 'setq 'Out (list expr (list 'eval (list 'nth 1 name)) txt 'ask-p)) txt ) 'Out ) ) )
Warum tust du dir das eigentlich an so viele lambda einzubauen, kritisch aber nicht bös gemeint sehe ich keinen Nutzen darin. Ich freue mich auf deine Meinung Jetzt weiss ich nicht ob das vielleicht den Fragerahmen sprengt, aber ist es denn möglich in der Abrufanzeige eine, ich nenne es mal Pulldown einzubauen, um vielleicht auf ältere Eingaben als die letztere zurückzugreifen ? (Wird wohl kaum in einem Satz zu beantworten zu sein). Die Frage richtet sich gern auch an andere, die damit schon Erfahrungen gemacht haben.
------------------ Gruss Dirk http://cadplayerlounge.blogspot.se Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 14. Jun. 2013 17:26 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Hello... will es dir erläutern... Warum ich so "viele" lambdas verwende liegt daran dass ich ab und zu nicht die Rückgabe einer Funktion brauche sondern viel mehr die Funktion selbst. Ab und an verwende ich es um einen Block zusammenzufassen der von seiner Funktion her geschlossen agiert... Zur Erklärung des Code's... Zum ersten Teil:
Code:
;1] (setq expr (lambda (currentDefault txt ask-p / get-x) (if ask-p (progn (setq get-x (cond ((= (type currentDefault) 'INT) getint) ((= (type currentDefault) 'STR) getstring) ) ) (setq Out (if get-x (get-x (strcat "\n" txt " <" (vl-princ-to-string currentDefault) ">:")))) (if (or (null Out) (= Out "")) currentDefault Out ) ) currentDefault ) ) )
Dieser Teil wird hier nicht ausgeführt sondern an die Variable 'Expr gebunden 'Expr ist somit eine Variable des Typs 'SUBR... u know (type Expr) -> 'SUBR Das hat den vorteil dass man einfach (Expr) schreiben kann um die Funktion auszuführen. Dies mache ich weil diese Funktion an mehreren stellen gebraucht wird... im zweiten Teil... 2ter Teil:
Code:
;2] ( (lambda (meta / ) (meta meta ref_Default expr Default txt) ) (lambda (meta name expr default txt / ) (set name (list '(ask-p / Out) (list 'quote default) (list meta meta (list 'quote name) expr (list 'setq 'Out (list expr (list 'eval (list 'nth 1 name)) txt 'ask-p)) txt ) 'Out ) ) ) )
Dieser Teil der Funktion produziert die eigentliche Abfrage-Funktion und schreibt sie in die Variable, bzw. bindet sie an das Symbol die in 'ref_default angegeben ist. ;2] Aufgesplittet:
Code:
;2.1] ( (lambda (meta / ) (meta meta ref_Default expr Default txt) ) . . . )
Dieser kleine Teil ist der Beginn einer Anonymen Rekursion. Der Wert der an die lambda-expr als 'meta übergeben wird, wurde hier durch Punkte ersetzt. Das was oben Punkte sind:
Code:
;2.2] (lambda (meta name expr default txt / ) (set name (list '(ask-p / Out) (list 'quote default) ;;1te Aufgabe (list meta ;;3te Aufgabe meta (list 'quote name) expr (list 'setq 'Out (list expr (list 'eval (list 'nth 1 name)) txt 'ask-p)) ;;2te Aufgabe txt ) 'Out ) ) )
Dieser Teil wird hier zum type 'SUBR evaluiert und oben "2.1" an das Symbol 'meta gebunden. In "2.1" wird dann diese Funktion aufgerufen und übergibt sich an sich selbst (meta meta ...) und andere (... ... ref_default expr Default txt) In 2.2 wird aus diesem eingangswerten eine Funktion erzeugt die 3 Aufgaben hat: - 1te Aufgabe: an Stelle (nth 1 ...) wird der Wert für 'Default gespeichert - 2te Aufgabe: Führe die Funktion in ;1] aus, mit dem Wert aus der 1ten Aufgabe, dem Inhalt der Variable 'txt und dem Eingangswert der Funktion 'ask-p - 3te Aufgabe: Führe die Funktion "2.2" (führt sich selbst aus); und schreibe dich neu mit dem neuen Wert für Default, welcher aus 2terAufgabe zurückgegeben wird.
------------------------- Hoffe ich konnte dir näher bringen wie das ganze funktioniert?
Zu deiner anderen Frage: Jo geht. In der obigen Version wird immer nur der letzte Wert von Default gespeichert; siehe 1te-Aufgabe Wenn man jetzt aber alle eingegeben Werte in einer Art "History" ablegt, was in diesem Fall nichts anderes als eine Liste ist, dann kann man das Pulldown sehr leicht realisieren. Das Pulldown, wie auch immer du dir das vorstellst (als Dialog oder was auch immer) darfst du dann produzieren... ;)
Im folgenden eine Variante mit "History" Vergleiche das obige mit dem der nächsten Variante und du wirst die Veränderungen schon festmachen können... Ich Habe jetzt das Pulldown mit einem PopUp von Doslib gemacht...
Code:
(defun abfrage (txt ref_Default Default / expr) ;---- (setq expr (lambda (History currentDefault txt ask-p / get-x PopOut) ;neue Variable 'History (if ask-p (progn (setq get-x (cond ((= (type currentDefault) 'INT) getint) ((= (type currentDefault) 'STR) getstring) ) ) (initget "History") ;eingefügt (setq Out (if get-x (get-x (strcat "\n" txt " [History] <" (vl-princ-to-string currentDefault) ">:")))) (cond ((= Out "History") (setq PopOut (dos_popupmenu (mapcar 'vl-princ-to-string History))) ;POPUP von DosLib (if PopOut (nth PopOut History) ) ) ((or (null Out) (= Out "")) currentDefault) ('T Out) ) ) currentDefault ) ) ) ;---- ( (lambda (meta / ) (meta meta ref_Default expr Default txt) ) (lambda (meta name expr default txt / ) (set name (list '(ask-p / Out) (list 'quote (if (atom default) (list default) default)) ;Änderung - der gespeicherte Wert muss eine Liste sein (list meta meta (list 'quote name) expr (list (lambda (ExprOut History / ) ;eingefügt - anfügen des letzten Wertes an History (if ExprOut (cons ExprOut (vl-remove ExprOut History)) History ) ) (list 'setq 'Out (list expr (list 'eval (list 'nth 1 name)) ;eingefügt - History (list 'car (list 'eval (list 'nth 1 name))) ;Änderung - letzter Wert txt 'ask-p ) ) (list 'eval (list 'nth 1 name)) ) txt ) 'Out ) ) ) ) ref_Default )
lg
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 15. Jun. 2013 10:45 <-- editieren / zitieren --> Unities abgeben:
Tausend Dank für den Superstoff, das wird mich den Samstag beschäftigen. Echt ein Wunder für mich, wie man auf so tolle Ideen kommt. Bisher hat bei mir McNeel´s runtime noch wenig Anwendung gefunden. Sozusagen meine erste Funktion (dos_popupmenu. ------------------ Gruss Dirk http://cadplayerlounge.blogspot.se Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 15. Jun. 2013 12:06 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Freut mich... wenns dich intressiert, im Anhang eine "allgemeine" Variante um obiges bewerkzustelligen... (mit Tabs formatiert - Notepad++)
Zur Verwendung: Beim Laden der .lsp wird eine 'SUBR erzeugt, welche man mit 2 Inputs aufruft... ctrl und add...
ctrl: Eine gequotete lambda-expr mit mindestens 4 Inputs wobei die schlussendlich benötigte Zahl auch von dem 2ten Input (add) abhängt... zB. '(lambda (a b c d / ) ... ) Jeder zusätzliche InputVariable ist am Ende die InputVariable für die erzeugte Funktion... add: Eine Liste von Daten bzw. Funktionen die an die Funktion übergeben werden sollen... Ist diese Liste zB. 2 lang, braucht die obige Funktion mindestens 6 InputVariablen... zur ctrl-Expr: 1ter Input [SUBR]: nenn ich "self"; weil beim Aufruf dieser, die Funktion selbst wieder aufgerufen wird. (Anzahl der geforderten Argumente abhängig von der ctrl-lambda-expr) 2ter Input [SYM]: nenn ich "name"; weil das der Name der Funktion ist. 3ter Input [SUBR]: nenn ich "Update"; weil der übergebende Wert in die Funktion eingelagert/gespeichert wird; fordert ein Argument = die neuen Daten... 4ter Input [SUBR]: nenn ich "Data"; weil beim Aufruf (ohne Argument) die Daten aus der Funktion ausgelesen werden...
Gibt man der Funktion 'ctrl-expr und 'add-list dann erzeugt das eine Funktion die wiederrum 2Argumente will: 1tes ist der Name der Funktion als Symbol 2ter ist der "Body", sprich die Daten die eingelagert werde sollen...
als Beispiel mit der Abfrage: Code:
(defun Abfrage (name txt default / meta) (setq meta (load "meta.lsp") nil) ;Pfad anpassen!!! (if meta ( (meta '(lambda (self name update data add1 Steuerung / get-x PopOut Out) ;ctrl (cond ((= Steuerung 0) (setq get-x (cond ((= (type (car (data))) 'INT) getint) ((= (type (car (data))) 'STR) getstring) ) ) (initget "History") (setq Out (if get-x (get-x (strcat "\n" add1 " [History] <" (vl-princ-to-string (car (data))) ">:")))) (setq Out (cond ((= Out "History") (setq PopOut (dos_popupmenu (mapcar 'vl-princ-to-string (data)))) (if PopOut (nth PopOut (self -1))) ;hier zB. wird die Funktion rekusriv aufgerufen ) ((or (null Out) (= Out "")) (car (data))) ('T Out) ) ) (update (cons Out (vl-remove Out (data)))) Out ) ((= Steuerung 1) (car (data)) ) ((= Steuerung -1) (data) ) ) ) (list txt) ;add ) name ;name (list default) ;Body ) ) )
Wenn dann würd ich mir die "allgemeine" Variante ansehn...
lg
[Diese Nachricht wurde von reltro am 15. Jun. 2013 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 15. Jun. 2013 12:08 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von cadplayer: Tausend Dank für den Superstoff, das wird mich den Samstag beschäftigen. Echt ein Wunder für mich, wie man auf so tolle Ideen kommt.
Das ist eben Lisp: dass es keinen Unterschied gibt zwischen Programm und Daten, dass Funktionen genau so und auf dieselbe Weise manipulierbar sind wie Daten, und dass eine Funktion sich somit sogar zur Laufzeit selbst verändern kann. Im konkreten Fall ist es natürlich ein gewisser Manierismus, wenn man eine anonyme Funktion via setq an eine Variable bindet (das ist dann dasselbe wie diese Funktion mit gleichem Namen via defun zu definieren), aber was soll's: es gibt keinerlei Nachteile dabei. IMO wird im Bereich AutoLisp/VisualLisp das Konstrukt der anonymen Funktion viel zu selten verwendet. Wenn überhaupt, dann kennen die Anwender das nur in Zusammenhang mit mapcar. Wenn man sich dagegen mal "richtigen" Lisp Code (also Common Lisp) ansieht, dann erkennt man schnell, dass die Lambda-Funktion eine der zentralen Funktionen überhaupt ist. Defun und Lambda sind in CL allerdings keine Funktionen, sondern spezielle Formen von Makros. Lisp Funktionen verwenden Werte als Input und geben Werte als Output zurück, Makros hingegen nehmen Lisp Code als Input und geben Lisp Code zurück. Bei Makros kann festgelegt werden, welche Teile davon wann evaluiert werden - bei einem Aufruf von defun wird bekanntlich gar keines seiner Argumente evaluiert. Das Fehlen von Makros ist eines der größten Handicaps, die AutoLisp-Programmierer ausbremsen. Mehr zu Makros z.B. hier: http://cl-cookbook.sourceforge.net/macros.html Reltro hat hier also eines der leider viel zu seltenen Beispiele gezeigt, wie man auch in AutoLisp/VisualLisp "richtig" Lisp programmieren kann, Das, was wir hier zu 99,99% machen, ist nämlich nur simples algorithmisches Programmieren in einer Sprache, die eigentlich für funktionales Programmieren entwickelt wurde.
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 15. Jun. 2013 20:22 <-- editieren / zitieren --> Unities abgeben:
Das ist ein ganz neuer Wind für mich. Echt cool, reltro deine Einwürfe hier zu lesen. Archtools hat ganz recht, dass von lambda oft nur gewohnte Standards zu lesen sind. Für mich stecken da noch viele Rätsel dahinter, da ich nicht genau weiss, was gibt lambda zurück. Ein simple Lisp routine, wie ich es oft nur kann, rattert Zeile für Zeile runter, stopft variablen und spuckt sie wieder aus. Was ich an lambda so spannend finde (ähnlich wie bei Hieroglyphen) es ist doch irgendwie ein Geheimnis. Erste Klasse hier, danke für Eure Beiträge. Bei Gelegenheit gebe ich mal neue Erkenntnisse zurück. ------------------ Gruss Dirk http://cadplayerlounge.blogspot.se Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 15. Jun. 2013 20:51 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Hey... lambda ist ein verdammt einfaches Ding Wie alles in Lisp gibt es etwas zurück. Bei lambda ist das eine Funktion... ähnlich wie defun nur eben ohne namen, eine anonyme Funktion... wenn du zB. schreibst und ausführst: Code:
(defun sample (a / ) (print a))(setq b (lambda (a / ) (print a)))
Und dann in der Acad-Console eintipps:
Code:
!a ;bzw !b
Kannst du die "Geimsamkeit" ausmachen...Der Aufruf ist grundätzlich ähnlich/gleich:
Code:
(a "das war defun") (b "das war lambda")
Das Beispiel ist nicht sonderlich originell (bzw. wie archtools auch schon erwähnt hat) macht es nicht viel sinn eine anonyme Funktion an eine Variable zu binden. Ich mach es aber gern, da ich es zu vermeiden versuche, für eine (Main-)Funktion lauter externe benannte SubFunktionen zu verwenden. Die Subfunktionen halte ich dabei stets anonym und lagere sie in die MainFunktion ein um sie dort lokal zu benennen. Das braucht natürlich ein kleines Workaround um nicht stets das selbe immer und immer wieder zu schreiben... Was mich zu diesem (meine persönlichen Standard) gebracht hat, war der Teil von Mapcar (auf seinen Seiten; du kennst sie sicher) wo es um Funktionsschablonen bzw. mapin ging. Meiner bescheidenen Meinung, gibt es neben dem Vorteil der Lokalität einige weitere Vorteile.................................................. lg Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 15. Jun. 2013 22:26 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von reltro: Hey... Das Beispiel ist nicht sonderlich originell (bzw. wie archtools auch schon erwähnt hat) macht es nicht viel sinn eine anonyme Funktion an eine Variable zu binden. Ich mach es aber gern, da ich es zu vermeiden versuche, für eine (Main-)Funktion lauter externe benannte SubFunktionen zu verwenden.
Du kannst in einer Main-Funktion die intern in dieser Funktion definierten defun-Funktionsnamen genau so als lokale Variablen deklarieren, wie Du das mit den Variablennamen machst, an die Du die anonymen Funktionen bindest. Ich bin mir sehr sicher, dass in AutoLisp/VisualLisp das Defun nichts anderes ist als eine an einen Variablennamen gebundene Lambda-Funktion. Es gibt da keinen erkennbaren Unterschied, und da man Funktionen ohnehin nicht überladen kann, braucht man auch keine aufgeblasene Funktionsverwaltung. (defun foo ...) ist nichts anderes als (setq foo (lambda ...)). In beiden Fällen hast Du eine Funktion, die an eine Variable gebunden ist. Deshalb wundert es mich, wenn Du schreibst:
Zitat: Original erstellt von reltro: Meiner bescheidenen Meinung, gibt es neben dem Vorteil der Lokalität einige weitere Vorteile
Welche Vorteile wären das denn? Ich bin neugierig :-) Meine Vermutung gilt übrigens auch für defun-q und die völlig unsinnigen Funktionen defun-q-list-set und defun-q-list-ref. Beispiel: _$ (defun-q test (a b) (* a b)) TEST _$ (defun-q-list-ref 'test) ((A B) (* A B)) _$ (setq test1 '((a b) (+ a b))) ((A B) (+ A B)) _$ (defun-q-list-ref 'test1) ((A B) (+ A B)) _$ (defun-q-list-set 'test2 '((a b) (- a b))) TEST2 _$ (defun-q-list-ref 'test2) ((A B) (- A B)) _$ test ((A B) (* A B)) _$ test1 ((A B) (+ A B)) _$ test2 ((A B) (- A B)) Bei all diesen defun-q-Funktionen gibt's nichts, was man nicht sogar kürzer mit setq und normaler Evaluierung bekommen kann. Autodesk baut da IMO ein potemkinsches Dorf für uns ... [Diese Nachricht wurde von archtools am 15. Jun. 2013 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 16. Jun. 2013 00:55 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Hey hey Zunächst zum letzten Teil
Zitat:
Meine Vermutung gilt übrigens auch für defun-q und die völlig unsinnigen Funktionen defun-q-list-set und defun-q-list-ref. Beispiel: _$ (defun-q test (a b) (* a b)) TEST _$ (defun-q-list-ref 'test) ((A B) (* A B)) _$ (setq test1 '((a b) (+ a b))) ((A B) (+ A B)) _$ (defun-q-list-ref 'test1) ((A B) (+ A B)) _$ (defun-q-list-set 'test2 '((a b) (- a b))) TEST2 _$ (defun-q-list-ref 'test2) ((A B) (- A B)) _$ test ((A B) (* A B)) _$ test1 ((A B) (+ A B)) _$ test2 ((A B) (- A B))
=D das ist echt witzig was es da so alles gibt... noch nie davon gehört... scheint ziemlich unnötig... Außer von defun-q das anscheind dazu da ist um abwärtskompatibel zu sein, hab ich irgendwo gelesen; wo keine Ahnung mehr... Was es für eine Sinn macht kein schimmer ;------------------ Zum einlagern von Funktionen in eine Mainfunktion habe ich mich vielleicht nicht deutlichst ausgedrückt... Meine Vorgehensweise ist die, dass ich die Mainfunktion so aufbaue, dass sich diese beim Laden selber mit den nötigen Subfunktionen bestückt, sprich diese aus einer Bibliothek lädt und in sich lokal absetzt. Also in etwa so:
Code:
(eval (list 'defun 'main '(a b c / s1 s2) (list 'mapcar ''set '(s1 s2) (list (load "Sub1.lsp") (load "Sub2.lsp") ) ) '(progn . . . ) ) )
(In diesem Fall liegt meine Bib im SupportPfad von Acad)Dabei liegen die SubFunktionen in einer .lsp Datei die eine(!) lambda-expr beihaltet, sprich sowas:
Code:
(lambda (a b / ) (+ a b))
Dies produziert beim Start von Acad bzw. dem Laden der Main, natürlich einen Mehraufwand an Ladevorgängen, aber, weil sie ja nicht bei jedem Aufruf stattfinden behaupte ich mal das man das getrost vernachlässigen kann... (Acad2014 und TrustedPath sind natürlich killer :nozwinker Deine Vermutung (wenn ich sie richtig verstanden habe), dass mit defun erzeugt funktionen nichts anderes sind als lambda's mit namen, scheint der Fall zu sein. Nur erkenne ich eine kleinen aber entscheidenden Unterschied (bei oben genannten vorgehn) Das gleiche einmal mit defun und einmal mit lambda:
Code:
(setq a (eval (list 'lambda '(input / sub1) (list 'setq 'sub1 (eval (defun b (c / ) (print c)) ) ) '(sub1 input) ) ) )(print b) ;; hm, es gibt b, klar, muss so sein, wurde ja benannt (setq b nil) (a 20) ;funktioniert
Code:
(setq a (eval (list 'lambda '(input / b) (list 'setq 'b (lambda (c / ) (print c))) '(b input) ) ) )(print b) ;; kein b da (a 20)
Also ich bevorzuge die Version mit lambda ;) Die Vorteile die ich daran festmache sind nicht explizit programmiertechnisches Natur sondern viel mehr solche der organisation. Durch dieses Vorgehn zwinge ich mich selbst in einer Datei explizit eine Funktion zu beherbergen ;) klingt nach einem Nachteil, empfinde ich aber genau andersrum. Da auftretende Fehler leicht festzumachen sind und leicht korrigiert werden können. Das austauschen von Subfunktionen durch vielleicht umfangreichere/bessere ist leichter denn je... OT: Bei der Weitergabe von Programmen kann es natürlich zu Problemen mit dem Pfad führen; dies hab ich aber über ein externes von Acad unabhängiges VBScript und eine .ini gelöst die den SuchPfad an die Main weitergibt (oben nicht enthalten). klingt vielleicht kompliziert ist es aber nicht wirklich ;) Programmiertechnischer "Vorteil" (?) wenn man zB. die Subfunktionen direkt in der MainFunktion schreibt...
Code:
(defun main (a / sub1) (defun sub1 (b / ) (print b)) (sub1 a) )
... könnt ich mir vorstellen dass die stets auszuführende evaluierung von defun und die Bindung an das entsprechende Symbol nicht so "schnell" ist, wie wenn da nur eine bereits "kompilierte(?)" lambda-expr an ein Symbol geheftet wird... Ist aber nur eine Vermutung... klär mich auf lg
[Diese Nachricht wurde von reltro am 16. Jun. 2013 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 16. Jun. 2013 14:15 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von reltro:
Außer von defun-q das anscheind dazu da ist um abwärtskompatibel zu sein, hab ich irgendwo gelesen; wo keine Ahnung mehr... Was es für eine Sinn macht kein schimmerDefun-q macht immerhin noch ein klein wenig Sinn, beispielsweise für die Funktion S::STARTUP, die sich mehrere Applikationen teilen müssen. Es ist halt leichter zu erklären, dass man dazu defun-q verwenden soll, als (setq s::startup '(....)) ;
Zitat:
Code:
(setq a (eval (list 'lambda '(input / sub1) (list 'setq 'sub1 (eval (defun b (c / ) (print c)) ) ) '(sub1 input) ) ) ) (print b) ;; hm, es gibt b, klar, muss so sein, wurde ja benannt (setq b nil)
Da hast Du etwas anders programmiert als in Deinem Gegenbeispiel mit den Lambdas. Du hättest hier b ebenfalls als lokale Variable deklarieren müssen: (list 'lambda '(input / sub1 b) ... Das defun verhält sich nämlich ganz exakt genau so wie Dein (setq b (lambda ...)). Wenn b lokal definiert ist, dann ist es lokal, egal ob es mit defun oder mit setq an eine Variable gebunden ist.
Zitat: ... könnt ich mir vorstellen dass die stets auszuführende evaluierung von defun und die Bindung an das entsprechende Symbol nicht so "schnell" ist, wie wenn da nur eine bereits "kompilierte(?)" lambda-expr an ein Symbol geheftet wird... Ist aber nur eine Vermutung... klär mich auf
Naja, wenn die anonyme Funktion erst in der Main-Funktion definiert wird, dann gibt es wohl keinerlei Unterschied, denn dann muss die ja auch bei jedem Aufruf der Main "kompiliert" werden. Lädst Du die anonyme Funktion aber aus einer Datei, dann stehst Du schlechter da, denn dann muss sie erst aus der Datei gelesen und dann ja auch noch kompiliert werden. Die bereits kompilierte lambda-expression kannst Du ja nur dann direkt an eine lokale Variable der Main binden, wenn sie schon vorher geladen und an eine globale Variable gebunden ist. Dann gibt es keinen Unterschied zu einer globalen defun-Funktion, die Du nur lokal an eine andere Variable bindest.
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
cadplayer Ehrenmitglied CADniker
Beiträge: 1833 Registriert: 28.04.2009 Windows 10 64bit system Autocad Civil3d 2020 ENGLISH Visual Studio 2019 OpenDCL.Runtime.9<P>
|
erstellt am: 16. Jun. 2013 14:22 <-- editieren / zitieren --> Unities abgeben:
Mal dazwischen gehakt, warum nicht seine Subfunktionen getrennt in der startup (acad.lsp) laden, dann brauch man das Rad eigentlich nicht immer wieder neu erfinden und ruft das auf was man in dem aktuellen code braucht. Weiss nicht ob das sehr elegant ist?! ------------------ Gruss Dirk http://cadplayerlounge.blogspot.se Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 16. Jun. 2013 14:43 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von cadplayer: Mal dazwischen gehakt, warum nicht seine Subfunktionen getrennt in der startup (acad.lsp) laden, dann brauch man das Rad eigentlich nicht immer wieder neu erfinden und ruft das auf was man in dem aktuellen code braucht. Weiss nicht ob das sehr elegant ist?!
Nein, das geht nicht. Die S::STARTUP Funktion wird nämlich zu einem genau definierten Zeitpunkt ausgeführt, an dem AutoCAD und die geladene Datei vollständig initialisiert sind. Das wäre bei Deinem Beispiel nicht möglich, und ebenso wenig ginge das, wenn man das in einer eigenen MNL Datei machen will. Da es ziemlich häufig vorkommt, dass Applikationen unmittelbar nach erfolgter Initialisierung von AutoCAD und DWG die eigene Initialisierung vornehmen müssen (beispielsweise Reaktoren an Objekte binden), und weil Autodesk nur den Funktionsnamen S::STARTUP dafür vorgesehen hat (man könnte auch alle Funktionen ausführen, deren Name mit S::STARTUP beginnt, um das Problem zu vermeiden), müssen sich Applikationen diese Funktion teilen können. Das geht aber nicht, wenn diese mit defun definiert wird. Deshalb ist hier zwingend defun-q notwendig, weil dann jede Applikation ihre eigenen Initialisierungsfunktionen an eine schon bestehende S::STARTUP anhängen kann. Hier mal als Beispiel die ARCHTOOLS.MNL. Wie man sieht, schmeisse ich hier eine fehlerhaft definierte S::STARTUP gnadenlos raus (und gebe einen Hinweis an den Anwender):
Code:
;;; ARCHTOOLS MNL Datei (defun-q archtoolsstart () (cond ((= "VISUAL" (strcase (substr (ver) 1 6))) (if (not c:archdim) (load "ARCHTOOLS.VLX")) ) ('T (load "ARCHTOOLS.DES") ) ) (prin1) )(cond ((not S::STARTUP) (setq S::STARTUP archtoolsstart) ) ((AND S::STARTUP (= 'LIST (type S::STARTUP))) (setq S::STARTUP (append S::STARTUP (cdr archtoolsstart))) ) ('T (setq S::STARTUP archtoolsstart) (princ (strcat "\nArchTools Warnung:" "\nEine fremde Applikation hat die S::STARTUP Funktion" "\nfehlerhaft eingerichtet." "\nSie wird u.U. nicht korrekt initialisiert" ) ) ) ) (prin1)
[Diese Nachricht wurde von archtools am 16. Jun. 2013 editiert.]
[Diese Nachricht wurde von archtools am 16. Jun. 2013 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 16. Jun. 2013 14:54 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat:
Da hast Du etwas anders programmiert als in Deinem Gegenbeispiel mit den Lambdas. Du hättest hier b ebenfalls als lokale Variable deklarieren müssen: (list 'lambda '(input / sub1 b) ... Das defun verhält sich nämlich ganz exakt genau so wie Dein (setq b (lambda ...)). Wenn b lokal definiert ist, dann ist es lokal, egal ob es mit defun oder mit setq an eine Variable gebunden ist.
Nö... Da es folgendermaßend aussieht:
Code:
(progn (setq a ;(eval (list 'lambda '(input / sub1 b) (list 'setq 'sub1 (eval (defun b (c / ) (print c)) ) ) '(sub1 input) ) ;) ) (print b) ;; hm, es gibt b, klar, muss so sein, wurde ja benannt (setq b nil) (print a) ((eval a) 20) )
gibt bei ausührung
Code:
#<SUBR @00000000303dfa20 B> ;;(print b) (LAMBDA (INPUT / SUB1 B) (SETQ SUB1 #<SUBR @00000000303dfa20 B>) (SUB1 INPUT)) ;;(print a) 20 20 ;;der Aufruf
Das lokale 'b in der Main ist dabei ziemlich sinnfrei, weil b in der Main nie "erzeugt" wird; nur bei zusammenbau wird bei defun die Funktion an 'b gebunden, und das ist einen anderer Namespace als jener der Main, den es zu diesem Zeitpunkt ja noch gar nicht gibt... und
Zitat:
Naja, wenn die anonyme Funktion erst in der Main-Funktion definiert wird, dann gibt es wohl keinerlei Unterschied, denn dann muss die ja auch bei jedem Aufruf der Main "kompiliert" werden. Lädst Du die anonyme Funktion aber aus einer Datei, dann stehst Du schlechter da, denn dann muss sie erst aus der Datei gelesen und dann ja auch noch kompiliert werden. Die bereits kompilierte lambda-expression kannst Du ja nur dann direkt an eine lokale Variable der Main binden, wenn sie schon vorher geladen und an eine globale Variable gebunden ist. Dann gibt es keinen Unterschied zu einer globalen defun-Funktion, die Du nur lokal an eine andere Variable bindest.
Nö beim einlagern sieht man hier dass die eingelagert Funktion bereits kompiliert vorliegt und nur noch an das Symbol gebunden wird. Das laden fällt demnach nur einmal an...
Code:
(setq a ;(eval (list 'lambda '(input / b) (list 'setq 'b (lambda (c / ) (print c))) '(b input) ) ;) ) ;-> (LAMBDA (INPUT / B) (SETQ B #<SUBR @00000000303dfb88 -lambda->) (B INPUT))
@cadplayer
Zitat:
Mal dazwischen gehakt, warum nicht seine Subfunktionen getrennt in der startup (acad.lsp) laden, dann brauch man das Rad eigentlich nicht immer wieder neu erfinden und ruft das auf was man in dem aktuellen code braucht. Weiss nicht ob das sehr elegant ist?!
Genau das will ich ja vermeiden; dass es globale definierte SubFunktionen gibt... außerdem wird die acad.lsp nur einmal pro Start von Acad geladen, nicht aber für jedes Dokument... lg
[Diese Nachricht wurde von reltro am 16. Jun. 2013 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 16. Jun. 2013 15:29 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von reltro: beim einlagern sieht man hier dass die eingelagert Funktion bereits kompiliert vorliegt und nur noch an das Symbol gebunden wird. Das laden fällt demnach nur einmal an...
Naja, und dieser Fall ist eben vollkommen identisch mit dem einer geladenen defun-Funktion, die Du dann in der Main einfach nur an einen anderen Variablennamen bindest. Das ist so wie (setq plus +) :-) Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 16. Jun. 2013 15:37 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von archtools:
Naja, und dieser Fall ist eben vollkommen identisch mit dem einer geladenen defun-Funktion, die Du dann in der Main einfach nur an einen anderen Variablennamen bindest. Das ist so wie (setq plus +) :-)
wie du meinst... erkenne einen Unterschied, der darin besteht dass die geladene Funktion im globalen Namespace nicht anzutreffen (bei der Variante mit lambda) ist und demnach keine weiteren Main's stören kann... Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 16. Jun. 2013 15:39 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von reltro:
wie du meinst... erkenne einen Unterschied, der darin besteht dass die geladene Funktion im globalen Namespace nicht anzutreffen (bei der Variante mit lambda) ist und demnach keine weiteren Main's stören kann...
Das ist aber doch nur der Fall, weil Du auch die Main erst zur Laufzeit zusammenbaust. Das kannst Du mit defun genauso. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 16. Jun. 2013 15:42 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von archtools:
Das ist aber doch nur der Fall, weil Du auch die Main erst zur Laufzeit zusammenbaust. Das kannst Du mit defun genauso.
Jo, das ist mir schon klar dass es daher kommt, und das mach ich auch bewusst so; und dabei ist die Variante mit lambda deutlich besser... Was meinst du mit: Das kannst du mit defun genauso?
Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 16. Jun. 2013 15:46 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von reltro:
Jo, das ist mir schon klar dass es daher kommt, und das mach ich auch bewusst so; und dabei ist die Variante mit lambda deutlich besser... Was meinst du mit: Das kannst du mit defun genauso?
Damit meine ich, dass es keinerlei Unterschied gibt zwischen (defun test ()...) und (setq test (lambda ()....)). Alles, was man mit dem einen machen kann, kann man auch mit dem anderen. Du kannst ja auch das interne (defun ) eben so als Liste basteln und beim Erzeugen der Main-Funktion via eval ausführen, wie Du das mit dem (setq b (lambda )) machst. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 16. Jun. 2013 16:37 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von archtools:
Damit meine ich, dass es keinerlei Unterschied gibt zwischen (defun test ()...) und (setq test (lambda ()....)). Alles, was man mit dem einen machen kann, kann man auch mit dem anderen.
Das haben wir ja festgestellt
Zitat: Original erstellt von archtools:
Du kannst ja auch das interne (defun ) eben so als Liste basteln und beim Erzeugen der Main-Funktion via eval ausführen, wie Du das mit dem (setq b (lambda )) machst.
Natürlich kann man das machen... empfinde ich aber als ein wenig (mehr) rumgeflicke... man könnte auch gänzlich auf lambda und defun verzichten und stattdessen nur (setq b '((a) (print a))) nehmen, es gibt viele möglichkeiten... Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 16. Jun. 2013 16:57 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von reltro: Natürlich kann man das machen... empfinde ich aber als ein wenig (mehr) rumgeflicke... man könnte auch gänzlich auf lambda und defun verzichten und stattdessen nur (setq b '((a) (print a))) nehmen, es gibt viele möglichkeiten...
Naja, warum ein (defun b ...) mehr Rumgeflicke sein soll als ein (setq b (lambda ...)) wollte ich ja gerade von Dir erfahren. Beides ist wohl identisch, und deshalb ist es höchstens eine Frage des persönlichen Geschmacks. Das Binden einer als Funktion ausführbaren Liste an eine Variable hingegen ist nicht mit diesen beiden Methoden identisch, sondern mit dem defun-q. Diese Variante bietet diverse Vor- und Nachteile gegenüber den beiden anderen, die diese Variante je nach Anforderung als die bessere oder schlechtere Wahl erscheinen lassen. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 16. Jun. 2013 17:10 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Code:
(eval (list 'defun 'main '(a b c / s1 s2) (list 'mapcar ''set '(s1 s2) (list (load "Sub1.lsp") (load "Sub2.lsp") ) ) '(progn . . . ) ) )
hier wäre es ein rumgeflicke... und ja, natürlich ist es persönliche Vorliebe, Gesetz gibt es keines dafür ;)Zitat:
Das Binden einer als Funktion ausführbaren Liste an eine Variable hingegen ist nicht mit diesen beiden Methoden identisch, sondern mit dem defun-q. Diese Variante bietet diverse Vor- und Nachteile gegenüber den beiden anderen, die diese Variante je nach Anforderung als die bessere oder schlechtere Wahl erscheinen lassen.
Wohl wahrEine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
archtools Mitglied
Beiträge: 965 Registriert: 09.10.2004 Entwickler für AutoCAD, BricsCAD u.a., alle Systeme
|
erstellt am: 16. Jun. 2013 17:16 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Zitat: Original erstellt von reltro:
Code:
(eval (list 'defun 'main '(a b c / s1 s2) (list 'mapcar ''set '(s1 s2) (list (load "Sub1.lsp") (load "Sub2.lsp") ) ) '(progn . . . ) ) )
hier wäre es ein rumgeflicke...
Ich sehe das genau anders herum. Schon die dadurch implizite Anforderung hinsichtlich des Aufbaus der zu ladenden LSP Dateien ist doch schon ein irres Rumgeflicke, das in Summa keinerlei Vorteil bringt. Aber jeder Jeck ist anders, und wenn's Spaß macht ... Gruß Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
reltro Mitglied student
Beiträge: 125 Registriert: 08.11.2009 Acad 2012 - VBA,Lisp Revit 2012 3dsMax 2012 Rhino 5 - GH,Pyhton 3,rhino.Common<P>Win 7 - i7 4x3.2GHz - 8Gb DDR3
|
erstellt am: 16. Jun. 2013 18:23 <-- editieren / zitieren --> Unities abgeben: Nur für cadplayer
Ich mag es Schreibe einfach jede Funktion als lambda-Funktion und lass es bei Laufzeit dann zusammenbauen, vergebe am ende einen Namen dafür, gut is... Bei (anonymen) Rekursionen, kann ich dann den Namen (eben weil sie intern anonym/abgeschlossen sind) sehr leicht ändern ohne den Rest zu töten... Es macht Spaß, keine Sorge anonyme Rekursion macht besonders Spaß
Code:
(setq Rekursion-lambda ( (lambda (rekursiv / ) (eval (list 'lambda '(i / )(list rekursiv rekursiv 'i)))) ) (lambda (rekursiv i / ) (if (/= i 0) (list i (rekursiv rekursiv (- i 1))) i ) ) ) ) ;------------------------------------ (defun Rekursion-defun (i / ) (if (/= i 0) (list i (Rekursion-defun (- i 1))) i ) )
Die erste Variante schaut doch um einiges Spaßiger aus, nicht? Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |