Probleme bei eigenem Makro

Antwort erstellen


Diese Frage dient dazu, das automatisierte Versenden von Formularen durch Spam-Bots zu verhindern.
Smilies
:D :) :( :o :shock: :? 8) :lol: :-x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen:

Markdown is OFF

BBCode ist eingeschaltet
[img] ist eingeschaltet
[flash] ist ausgeschaltet
[url] ist eingeschaltet
Smilies sind eingeschaltet

Die letzten Beiträge des Themas

Ich habe die Datenschutzerklärung gelesen und bin damit einverstanden.

   

Wenn du eine Datei oder mehrere Dateien anhängen möchtest, gib die Details unten ein.

Ansicht erweitern Die letzten Beiträge des Themas: Probleme bei eigenem Makro

von sLy » Mi 27. Jan 2010, 12:20

KOMA hat geschrieben: Da funktioniert diverses nicht. Zum einen fehlen pst-circ, \makeatletter und \makeatother. Dann definierst Du hier:

Code: Alles auswählen

\newcommand*{\csname#1\endcsname}[1]{%
\csname neu. Noch deutlicher wird das bei

Code: Alles auswählen

\def\csname@#1
, wobei hier eben nicht \csname, sondern \csname@ neu definiert wird. Es fehlt also auch noch ein Leerzeichen nach \csname.

Bevor Du Dich an derart komplizierte Dinge wagst, solltest Du im TeXbook oder min. in TeX by Topic mal nachlesen, wie die Expansion in TeX generell und Dinge wie \expandafter und \csname...\endcsname funktionieren. Im Beispiel müsste man erst \csname #1\endcsname expandierten und dann \newcommand, also

Code: Alles auswählen

\expandafter\newcommand\expandafter*\expandafter{\csname #1\endcsname}
Das ist dann aber noch nicht das Ende der Probleme. Du hast auch wieder Umwege über \protected@edef, wo diese sicher nicht erforderlich sind. Dafür sollte man überlegen, bei der \def\csname-Geschichte eher auf diesem Weg vorzugehen. Desweiteren macht wohl auch:

Code: Alles auswählen

 \expandafter\csname @#1\endcsname\@tempa\@nil
nicht das, was Du willst. Denn hier wird lediglich die Expansion von \csname verzögert. Du willst aber vermutlich die Expansion des Makros der Expansion von \csname @#1\endcsname verzögern.

Ich glaube aber, dass es den Rahmen dieses Forums sprengt, Dir die low-level TeX-Grundlagen und die Feinheiten der Expansion beizubringen. Du begibst Dich da schon recht tief in den Teil von TeX, in dem man sich leicht verirren kann und auch ein Experte gut aufpassen muss.

Um es kurz zu machen: Neben anderen Fehlern funktioniert die komplette Expansionslogik Deines Codes nicht.
trotzdem danke, dass du dir die mühe gemacht hast, mir meine fehler zu erklären. ich werde mir bei gelegenheit evtl. mal das texbook o. ä. zu gemüte führen. Tex by topic lese ich gerade.
Das Problem bei dem ganzen ist, dass die tiefgründige literautr (z.b. texbook & tex by topic) auf englisch ist, was das erlernen nicht gerade vereinfacht.
phi hat geschrieben: Ehrlich gesagt ist mir der Sinn des Ganzen auch etwas schleierhaft. Du betreibst hier seit Wochen einen riesigen Aufwand, nur um die Syntax der pstricks-Befehle ein bisschen zu verändern. Neue Funktionalität wird dadurch ja gar nicht hinzugefügt. Bei deinem letzten Beispiel würde der Befehl \Diode exakt dasselbe wir der schon vorhandene Befehl \diode machen, nur müsste der Benutzer ein paar Klammern und Kommata anders setzen. Ich würde hier einfach die schon vorhandene Syntax benutzen.
Ich betreibe das ganze deswegen seit wochen, weil ich nicht nur meine Facharbeit (K13 gymnasium) mit latex schreibe, sondern weil auch das Thema meiner Facharbeit Darstellung von physikalischer Schaltbilder mit Hilfe von Latex und PSTricks lautet, wie ich in in diesem post bereits erwähnt habe.
Natürlich fragt man sich jetzt, wieso ich eine Facharbeit mit dem Thema schreibe eine Darstellungweise von Schaltbildern zu entwickeln, wenn es bereits seit langem pst-circ gibt. Die antwort ist ganz einfach, dass der betreffende Themensteller dieses paket nicht gekannt hat.
Der Sinn des Ganzen aufwandes, den ich hier betreibe, ist, die Darstellungsweise durch einschränkungen soweit zu vereinfachen, dass man ein einfaches schaltbild mit nur einem befehl erstellen kann. Ob das jetzt für die Augen eines erfahrenen Tex-Spezialisten (oder gar Latex-Entwicklers) sinnvoll erscheint, wage ich zu bezweifeln. Aber tatsache ist, dass das jetzt mein Thema ist und ich es auch nicht mehr ändern kann (abgabe ist übermorgen). Von daher habe ich es -in meinen augen- geschafft, die themenstellung zumindest auf dem nivau eines gymnasiasten befriedigend zu bearbeiten. Natürlich habe ich das nicht alleine geschafft, sondern nur dank eurer hilfe, für die ich mich an dieser stelle nochmal ausdrücklich bedanken will.

Von daher, werdet ihr spätestens am freitag keine anfänger-fragen von mir zu diesem thema beanworten müssen.

Mit freundlichen Grüßen,
sLy

von phi » Mi 27. Jan 2010, 11:34

Ehrlich gesagt ist mir der Sinn des Ganzen auch etwas schleierhaft. Du betreibst hier seit Wochen einen riesigen Aufwand, nur um die Syntax der pstricks-Befehle ein bisschen zu verändern. Neue Funktionalität wird dadurch ja gar nicht hinzugefügt. Bei deinem letzten Beispiel würde der Befehl \Diode exakt dasselbe wir der schon vorhandene Befehl \diode machen, nur müsste der Benutzer ein paar Klammern und Kommata anders setzen. Ich würde hier einfach die schon vorhandene Syntax benutzen.

von KOMA » Mi 27. Jan 2010, 10:31

Da funktioniert diverses nicht. Zum einen fehlen pst-circ, \makeatletter und \makeatother. Dann definierst Du hier:

Code: Alles auswählen

\newcommand*{\csname#1\endcsname}[1]{%
\csname neu. Noch deutlicher wird das bei

Code: Alles auswählen

\def\csname@#1
, wobei hier eben nicht \csname, sondern \csname@ neu definiert wird. Es fehlt also auch noch ein Leerzeichen nach \csname.

Bevor Du Dich an derart komplizierte Dinge wagst, solltest Du im TeXbook oder min. in TeX by Topic mal nachlesen, wie die Expansion in TeX generell und Dinge wie \expandafter und \csname...\endcsname funktionieren. Im Beispiel müsste man erst \csname #1\endcsname expandierten und dann \newcommand, also

Code: Alles auswählen

\expandafter\newcommand\expandafter*\expandafter{\csname #1\endcsname}
Das ist dann aber noch nicht das Ende der Probleme. Du hast auch wieder Umwege über \protected@edef, wo diese sicher nicht erforderlich sind. Dafür sollte man überlegen, bei der \def\csname-Geschichte eher auf diesem Weg vorzugehen. Desweiteren macht wohl auch:

Code: Alles auswählen

 \expandafter\csname @#1\endcsname\@tempa\@nil
nicht das, was Du willst. Denn hier wird lediglich die Expansion von \csname verzögert. Du willst aber vermutlich die Expansion des Makros der Expansion von \csname @#1\endcsname verzögern.

Ich glaube aber, dass es den Rahmen dieses Forums sprengt, Dir die low-level TeX-Grundlagen und die Feinheiten der Expansion beizubringen. Du begibst Dich da schon recht tief in den Teil von TeX, in dem man sich leicht verirren kann und auch ein Experte gut aufpassen muss.

Um es kurz zu machen: Neben anderen Fehlern funktioniert die komplette Expansionslogik Deines Codes nicht.

von sLy » Di 26. Jan 2010, 20:16

danke für eure Hifle soweit. Ich bin dank eurer Vorschläge ein ganzes stück weiter gekommen.

Leider habe ich ein neues Problem:

Ich möchte, dass sich der Benutzer mit Hilfe eines Befehls (\ElemDef) ein eigenes Element, das auf pst-circ aufbaut, definieren kann.
Ich bin bei der vorigen definition der Elemente geblieben und habe \Schaltung dafür verändert.
Hier noch mal die Definition eines Kondensators:

Code: Alles auswählen

\newcommand*{\Kondensator}[1]{%
  \protected@edef\@tempa{#1}%
  \expandafter\@Kondensator\@tempa\@nil
} 

\newcommand*{\@Kondensator}{}
\def\@Kondensator#1,#2\@nil{%
  \ifcsname#1\endcsname
    \protected@edef\@tempb{%
      \protect\capacitor\csname#1\endcsname{$#2$}%
    }%
    \@tempb
  \else
    \protected@edef\@tempb{%
    	\protect\capacitor#1{$#2$}%
    }%
    \@tempb
  \fi
}
 
Ich habe mir vorgestellt, dass der Benutzer sich mit der Eingabe \ElemDef{Diode,diode} ein neuen Befehl \Diode definieren kann.
Der zweite Parameter stellt den pst-circ-befehl dar.

Hier mein Minimalbeispiel:

Code: Alles auswählen

\documentclass{minimal}

\newcommand*{\ElemDef}[1]{\@ElemDef#1\@nil} 
\newcommand*{\@ElemDef}{}
\def\@ElemDef#1,#2\@nil{%
	\newcommand*{\csname#1\endcsname}[1]{%
  	\protected@edef\@tempa{##1}%
  	\expandafter\csname@#1\endcsname\@tempa\@nil
	} 
	\newcommand*{\csname@#1\endcsname}{}
		\def\csname{}@#1\endcsname##1,##2\@nil{%
  		\ifcsname##1\endcsname
    		\protected@edef\@tempb{%
      		\protect\csname#2\endcsname\csname##1\endcsname{$##2$}%
    		}%
    		\@tempb
  		\else
    		\protected@edef\@tempb{%
    		\protect\csname#2\endcsname##1{$##2$}%
    		}%
    		\@tempb
  		\fi
		} 
}
\begin{document}

\ElemDef{Diode,diode}

\begin{pspicture}[showgrid=true](-1,-1)(15,6)
  \pnode(0,5){Y}
  \pnode(0,0){A}
  \pnode(14,0){B}
  \pnode(14,5){Z}
  \battery(Y)(Z){$U_0$}
  \wire(Y)(A)
  \wire(B)(Z)
  \Diode{(A)(B),R_1}
\end{pspicture}

\end{document}

von KOMA » Mo 25. Jan 2010, 11:12

Das kann deshalb nicht funktionieren, weil \Lampe aus den Argumenten von \Schaltung bereits beim \protected@edef expandiert wird. Die Definition von Schaltung ist also zu ändern:

Code: Alles auswählen

\newcommand*{\Schaltung}[1]{%
  \@Schaltung#1\@nil
}
Da ich nicht die gesamte Diskussion gelesen habe, stellt sich mir aber die Frage, warum bei nur 9 verwendeten Argumenten überhaupt mit einer Liste gearbeitet wird, statt einfach 9 Argumente zu verwenden. Außerdem erscheint mir die Definition von \Lampe ebenfalls unnötig umständlich. Wenn ich mir erlaube, das ganze einmal etwas zu vereinfachen:

Code: Alles auswählen

\documentclass{minimal}

\usepackage{pst-circ}


\def \PosA {(B)(C)}
\def \PosB {(C)(D)}
\def \PosC {(D)(E)}
\def \PosD {(E)(F)}
\def \PosE {(F)(G)}
\def \PosF {(G)(H)}

\makeatletter
\newcommand*{\Lampe}[2]{%
  \expandafter\lamp#1{$L_#2$}%
}
\newcommand*{\Schaltung}[1]{%
  \@Schaltung#1\@nil
}
\newcommand*{\@Schaltung}{}
\def\@Schaltung#1,#2,#3,#4\@nil{%
  \psset {unit=#1cm}%
   \newcounter{x}
   \newcounter{y}
   \newcounter{xmax}
   \newcounter{ymax}
   \setcounter{x}{#2}
   \setcounter{y}{#3}
   \setcounter{xmax}{\value{x}}
   \setcounter{ymax}{\value{y}}
   \addtocounter{xmax}{1}
   \addtocounter{ymax}{1}
   \begin{pspicture}[showgrid=false](-1,-1)(\value{xmax},\value{ymax})
      \def\Standard{%
         \pnode(0,\value{y}){A}%
         \pnode(0,0){B}%
         \pnode(\value{x},0){Y}%
         \pnode(\value{x},\value{y}){Z}%
         \pnode(2,0){C}%
         \pnode(4,0){D}%
         \pnode(6,0){E}%
         \pnode(8,0){F}%
         \pnode(10,0){G}%
         \pnode(12,0){H}%
         \battery (Z)(A){$U_0$}%
          \wire (A)(B)%
          \wire (Y)(Z)%
          \wire (H)(Y)%
          #4
       }%
      \Standard%  
   \end{pspicture}%
}
\makeatother
\begin{document}

\begin{center}
  \Schaltung{1,13,4,%
    \Lampe\PosA1
    \Lampe\PosB2
    \Lampe\PosC3
    \Lampe\PosD4
    \Lampe\PosE5
    \Lampe\PosF{10}% Zur Verdeutlichung von mehrstelligen Nummern
  }
\end{center}
\end{document}
Das erscheint mit im Ergebnis deutlich einfacher. Die Fehlermeldung für nicht definierten \PosA etc. überlasse ich dabei einfach TeX. Man könnte jetzt natürlich \Schaltung auch einfach als Anweisung mit vier Argumenten definieren. Man spart sich dann auch gleich noch die Verwendung von \makeatletter und \makeatother. Dass man bei Schaltung alle Lampen mit einem Argument übergibt, sollte auch noch funktionieren, wenn man eure Definition von \Lampe und dann natürlich auch eure Schreibweise der Argumente von \Lampe verwendet.

von sLy » Mi 6. Jan 2010, 20:15

danke funktioniert einwandfrei.
Ich werde mir TeX by Topic mal zu gemüte führen...

mfg
sLy


EDIT:

mein neues Problem: ich will die zugehörige Schaltung zu den Teilen bauen.
Hier mein Code

Code: Alles auswählen

\newcommand*{\Schaltung}[1]{% die übliche Befehlsdefinition
  \protected@edef\@tempa{#1}%
  \expandafter\@Schaltung\@tempa\@nil
} 
\newcommand*{\@Schaltung}{}
\def\@Schaltung#1,#2,#3,#4,#5,#6,#7,#8,#9\@nil{% Parameter 1-3 sind Einheit in cm, max. X-Wert, max. Y-Wert; Parameter 4-9 stellen die Teile dar
  \psset {unit=#1cm}%
	\newcounter{x}% counter zur ermittlung von xmax und ymax
	\newcounter{y}
	\newcounter{xmax}
	\newcounter{ymax}
	\setcounter{x}{#2}
	\setcounter{y}{#3}
	\setcounter{xmax}{\value{x}}
	\setcounter{ymax}{\value{y}}
	\addtocounter{xmax}{1}
	\addtocounter{ymax}{1}
	\begin{pspicture}[showgrid=false](-1,-1)(\value{xmax},\value{ymax}) %das Standard-Schaltbild
		\def\Standard{%
			\pnode(0,\value{y}){A}%
			\pnode(0,0){B}%
			\pnode(\value{x},0){Y}%
			\pnode(\value{x},\value{y}){Z}%
			\pnode(3,0){C}%
			\pnode(6,0){D}%
			\pnode(9,0){E}%
			\pnode(12,0){F}%
			\pnode(15,0){G}%
			\pnode(18,0){H}%
			\battery (Z)(A){$U_0$}%
		 	\wire (A)(B)%
		 	\wire (Y)(Z)%
		 }%
		\def\bc{\noexpand#4} %hier sollen die Teile zur Schaltung hinzugefügt werden
		\def\cd{\noexpand#5}
		\def\de{\noexpand#6}
		\def\ef{\noexpand#7}
		\def\fg{\noexpand#8}
		\def\gh{\noexpand#9}
		\eappto\Standard{\bc}
		\eappto\Standard{\cd}	
		\eappto\Standard{\de}
		\eappto\Standard{\ef}
		\eappto\Standard{\fg}
		\eappto\Standard{\gh}
		\Standard%	
	\end{pspicture}%
}
Leider funktioniert das nicht so wie es soll.
Fehler:
! Argument of \@Lampe has an extra }.
! Paragraph ended before \@Lampe was complete.
! File ended while scanning use of \@Schaltung.
! Emergency stop.

Minimalbeispiel:

Code: Alles auswählen

\documentclass{minimal}

\usepackage{etoolbox}
\usepackage{pst-circ}
\usepackage{multido}

\makeatletter

\def \PosA {(B)(C)}
\def \PosB {(C)(D)}
\def \PosC {(D)(E)}
\def \PosD {(E)(F)}
\def \PosE {(F)(G)}
\def \PosF {(G)(H)}

\newcommand*{\Lampe}[1]{%
  \protected@edef\@tempa{#1}%
  \expandafter\@Lampe\@tempa\@nil
} 
\newcommand*{\@Lampe}{}
\def\@Lampe#1,#2\@nil{%
  \ifcsname#1\endcsname
    \protected@edef\@tempb{%
      \protect\lamp\csname#1\endcsname{$#2$}%
    }%
    \@tempb
  \else
    \PackageError{xyz}{Command `\@backslashchar#1' not defined}{\@ehc}%
  \fi
} 
\newcommand*{\Schaltung}[1]{%
  \protected@edef\@tempa{#1}%
  \expandafter\@Schaltung\@tempa\@nil
} 
\newcommand*{\@Schaltung}{}
\def\@Schaltung#1,#2,#3,#4,#5,#6,#7,#8,#9\@nil{%
  \psset {unit=#1cm}%
	\newcounter{x}
	\newcounter{y}
	\newcounter{xmax}
	\newcounter{ymax}
	\setcounter{x}{#2}
	\setcounter{y}{#3}
	\setcounter{xmax}{\value{x}}
	\setcounter{ymax}{\value{y}}
	\addtocounter{xmax}{1}
	\addtocounter{ymax}{1}
	\begin{pspicture}[showgrid=false](-1,-1)(\value{xmax},\value{ymax})
		\def\Standard{%
			\pnode(0,\value{y}){A}%
			\pnode(0,0){B}%
			\pnode(\value{x},0){Y}%
			\pnode(\value{x},\value{y}){Z}%
			\pnode(2,0){C}%
			\pnode(4,0){D}%
			\pnode(6,0){E}%
			\pnode(8,0){F}%
			\pnode(10,0){G}%
			\pnode(12,0){H}%
			\battery (Z)(A){$U_0$}%
		 	\wire (A)(B)%
		 	\wire (Y)(Z)%
		 	\wire (H)(Y)%
		 }%
		\def\bc{\noexpand#4}
		\def\cd{\noexpand#5}
		\def\de{\noexpand#6}
		\def\ef{\noexpand#7}
		\def\fg{\noexpand#8}
		\def\gh{\noexpand#9}
		\eappto\Standard{\bc}
		\eappto\Standard{\cd}	
		\eappto\Standard{\de}
		\eappto\Standard{\ef}
		\eappto\Standard{\fg}
		\eappto\Standard{\gh}
		\Standard%	
	\end{pspicture}%
}
\makeatother
\begin{document}

\begin{center}
\Schaltung{1,13,4,%
		\Lampe{PosA,L_1},%
		\Lampe{PosB,L_2},%
		\Lampe{PosC,L_3},%
		\Lampe{PosD,L_4},%
		\Lampe{PosE,L_5},%
		\Lampe{PosF,L_6}%					
		}
\end{center}
\end{document}

von phi » Di 5. Jan 2010, 17:30

sLy hat geschrieben:Naja ich dachte dabei an sowas:

Code: Alles auswählen

\newcommand*{\@Lampe}{}
\def\@Lampe#1,#2\@nil{%
  \def\@lamp{\lamp}
  \appto \@lamp{ \}
  \appto \@lamp{#1} 
  \appto \@lamp{{$#2$}}
  \@lamp
}
Also der backslash wird erst innerhalb der Befehlsdefinition vor den ersten Parameter gesetzt. Ich gebe zwar \Lampe{a,L} ein, aber aus dem ersten Parameter wird \a, das ich ja als (B)(C) definiert habe.
Aber wenn du sagst, dass das nicht funktioniert hat sich die Sache erledigt.
Das funktioniert schon, wenn der zweite Parameter immer einen Befehlsnamen bezeichnet:

Code: Alles auswählen

% ungetestet
\def\L@mpeI#1,#2\@nil{%
  \ifcsname#2\endcsname
    \protected@edef\@tempb{%
      \protect\lamp\csname#2\endcsname{$#1$}%
    }%
    \@tempb
  \else
    \PackageError{xyz}{Command `\@backslashchar#2' not defined}{\@ehc}%
  \fi
}
phi hat geschrieben: Die beiden Namen sind bedeutungslos, ich habe sie nur verwendet, weil sie in ähnlicher Bedeutung auch im LaTeX-Kernel verwendet werden.
Wenn sie bedeutungslos sind, wozu hast du sie dann verwendet?
Heißt das ich könnte sie auch weglassen?
Welche bedeutung haben sie im LaTeX-Kernel?
[/quote]
Mit "bedeutungslos" meine ich, dass man auch andere einsetzen kann.
Wenn du das alles verstehen möchtest, musst du dich in die TeX-Programmierung einlesen. Fang mal mit TeX by Topic an, insbesondere den Kapiteln 11, 12 und 13. Danach kannst du im LaTeX-Kernel (source2e.pdf) nach Vorkommnissen von \@tempa und \@nil suchen. \@tempa wird einfach als temporäre Variable verwendet, \@nil als Begrenzer von Makroargumenten.[/code]

von sLy » Di 5. Jan 2010, 11:48

Naja ich dachte dabei an sowas:

Code: Alles auswählen

\newcommand*{\@Lampe}{}
\def\@Lampe#1,#2\@nil{%
  \def\@lamp{\lamp}
  \appto \@lamp{ \}
  \appto \@lamp{#1} 
  \appto \@lamp{{$#2$}}
  \@lamp
}
Also der backslash wird erst innerhalb der Befehlsdefinition vor den ersten Parameter gesetzt. Ich gebe zwar \Lampe{a,L} ein, aber aus dem ersten Parameter wird \a, das ich ja als (B)(C) definiert habe.
Aber wenn du sagst, dass das nicht funktioniert hat sich die Sache erledigt.
phi hat geschrieben: Die beiden Namen sind bedeutungslos, ich habe sie nur verwendet, weil sie in ähnlicher Bedeutung auch im LaTeX-Kernel verwendet werden.
Wenn sie bedeutungslos sind, wozu hast du sie dann verwendet?
Heißt das ich könnte sie auch weglassen?
Welche bedeutung haben sie im LaTeX-Kernel?

mfg
sLy

von phi » Mo 4. Jan 2010, 23:53

sLy hat geschrieben: lässt sich der code auch so umschreiben, dass ich nur noch

Code: Alles auswählen

\Lampe{L,a}
schreiben müsste?
also dass ich mir den backslash sparen könnte?
Das würde eine Mehrdeutigkeit einbauen. Wie soll das Makro ermitteln, ob mit „a“ ein PSTricks-Punkt oder ein Makroname gemeint ist?
Wo kann ich mich über die makros \@nil und \@tempa informieren??
Die beiden Namen sind bedeutungslos, ich habe sie nur verwendet, weil sie in ähnlicher Bedeutung auch im LaTeX-Kernel verwendet werden.

von sLy » Mo 4. Jan 2010, 19:07

danke, funktioniert!

lässt sich der code auch so umschreiben, dass ich nur noch

Code: Alles auswählen

\Lampe{L,a}
schreiben müsste?
also dass ich mir den backslash sparen könnte?

UND

Wo kann ich mich über die makros \@nil und \@tempa informieren??

mfg
sLy

Nach oben