# Arithmetik in Scala



## Spin (5. Sep 2011)

Hallo liebe Community,

ich habe mich jetzt ein wenig in Scala reingelesen und kompiliere immer über die Konsole.
Erste frage: Kann ich da mehrere oder ein Ordner mit .scala Dateien kompilieren?

Weiter habe ich folgendes Anliegen.
Ich möchte gerne mein Trait(Merkmal, Characteristik) generisch machen und zwar für einen Taschenrechner.


```
/**
 * Trait: ArithmenticOperation.
 * A trait encapsulates method and field definitions, which can
 * be reused by mixing them into a class.
 */
trait ArithmeticOperation {
	
	/**
	 * add two integer values (concrete implementation)
	 */
	def add(x:Int, y:Int) = x.+(y) // same like x + y
	
	/**
	 * sub two integer values (concrete implementation)
	 */
	def sub(x:Int, y:Int) = x.-(y) // same like x - y
	
	/**
	 * multiply two integer values (concrete implementation)
	 */
	def mul(x:Int, y:Int) = x.*(y) // same like x * y
	
	/**
	 * divide two integer values (concrete implementation)
	 */
	def div(x:Int, y:Int){ 
	  require(y.!=(0)) // precondition that y must be non-zero
	  x./(y) // same like x / y
	} 
}
```


Ich kenne das aus Java mit [T] am Klassennamen. 
Der Trait soll mit Int,Float und Double , Long funktionieren.

Vielen Dank für Tipps und Tricks, grüße spin:rtfm:


----------



## Landei (5. Sep 2011)

1.) Sollte eigentlich ähnlich wie in Java funktionieren (außer dass man mehrere Klassen in ein Scala-File packen kann). Ich selbst nehme NetBeans mit Scala-Plugin, und bin ganz zufrieden damit. Eclipse mit Scala gibt es fix und fertig: Scala IDE for Eclipse.

2.) Spar dir die Arbeit und nimm Numeric: Scala Standard Library 2.9.1.final


----------



## 0x7F800000 (5. Sep 2011)

0) Ich bevorzuge es, einfach alles direkt mit maven von der Konsole aus zu kompilieren, und einen einfachten texteditor mit syntax-highlighting zu benutzen, damit kannst du dir Elefantenherde kompilieren

1) wozu.-(die komische syntax).? Genau dafür hat man doch die infix-syntax für methoden mit einem Argument

2) Eine solche Klasse ist eigentlich unnötig: zum einen gibt's schon Numeric[T], zum anderen Function[X, Y], je nach dem was besser passt.

3) Parser Combinators sind lustig: damit könnte man nämlich eine ordentliche eingabe basteln, ohne diesen ganzen gui-murks


----------



## Spin (6. Sep 2011)

Vielen Dank.

Ich bin dabei ein Scala Seminar für mein Studium vorzubereiten und brauche daher ein Sample Projekt.

Deswegen versuche ich es so strange wie mgl aufzubauen, damit man die unterscheide sofort zu java erkennt.

Ich habe wirklich ein problem mit der funktionalen Schreibweise:


```
/**
   * list of digits
   */
  private var digitList:List[String] = List("0","1","2","3","4","5","6","7","8","9") // same like List.apply()
  
  /**
   * list of buttons
   */
  private var digitButtonList:List[Button] = List() 
  
  /**
   * swing main method ( top level GUI component )
   */
  override def top = new MainFrame {
    title = "Calculator" // def title_=(s:String)
    
    digitList.zipWithIndex.foreach{
        digitButtonList =>
        case (digit,index) => new Button {
          text = digit
        }
    }
```

Meine foreach geht nicht 

Ich möchte gerne button von 1-9 haben. In Java ist das ziemlich einfach, aber in Scala tut man sich ziemlich schwer damit.

Bitte bitte um Hilfe, werde den Thread sicherlich noch öfters brauchen.;(

Alternativ:


```
digitList.zipWithIndex.foreach{
        case (digit,index) => 
          val button = new Button {
          text = digit
        }
        digitButtonList.apply(index) = button
    }
```

:/


----------



## Antoras (6. Sep 2011)

```
val buttons = digitList.zipWithIndex map {
  case (digit, index) => new Button { text = digit }
}
```


```
foreach
```
 gibt die erzeugten Buttons nicht zurück. 
	
	
	
	





```
map
```
 hingegen schon. Guck dir mal die Signaturen der beiden Methoden in der API an.


----------



## 0x7F800000 (6. Sep 2011)

Spin hat gesagt.:


> Deswegen versuche ich es so strange wie mgl aufzubauen, damit man die unterscheide sofort zu java erkennt.


Alles klar, aber dann weise bitte vor dem Vortrag ausdrücklich darauf hin, dass dieser "so stsnge wie mgl"-Code auf deinem Mist gewachsen ist, und dass kein normaler scala-Programmierer das so schreiben würde. 

Wenn du ein "Scala-Versuchstier" suchst, stelle ich mich gerne zur Verfügung, und schreibe dir einen gut kommentierten Taschenrechner, aber in _klaren_ Scala, nicht im _möglichst obskuren_ Scala.


```
private var digitList: List[String] = List("0","1","2","3","4","5","6","7","8","9") // same like List.apply()
```
das ist Unfug, welcher normaler Mensch schreibt ziffern von 0 bis 9 per hand aus?
Warum ist es "var" und kein val?

Wenn du wirklich haufen Strings haben willst, dann schreib

```
val digitStrings = for ( i <- 0 to 9 ) yield i.toString
```
wobei ich in deinem code nicht nachvollziehen kann, wozu die behämmerten Strings gut sein sollen...


```
private var digitButtonList:List[Button] = List()
```
Was das schon wieder? Wieso "var"? Wieso leer?

Wenn du einfach nur eine Liste mit zehn Buttons erstellen willst, dann geht das so:

```
val buttons = for (i <- 0 to 9) yield new Button(i)
```

Die methoden foreach, map, flatMap und filter sollte man ohne Grund nicht explizit im Scala-Code verwenden, für all das sind for-Konstrukte wesentlich besser geeignet.

Dass das hier ebenfalls gröbster Unfug ist, ist dir hoffentlich auch bewusst:

```
digitButtonList.apply(index) = button
```
???:L


----------



## Spin (6. Sep 2011)

Ja 

Ich versuche mich vorsichtig an Scala heran und bin euch sehr dankbar für konstruktive Kritik.

Mein Vortrag muss ich spätestens mitte Oktober halten und entsprechend eine Power-Point Präsi und 20 Seiten (English) Dokumentation fertigstellen. 

Um die jeweiligen Konzepte darzustellen, wollte ich einen Taschenrechner programmieren, der zum einen Funktionallen und Objektorientierten Stil verbindet. Weiterhin wollte ich alle Built-In Control Structures verwenden, Traits, Inheritance, Currying, Lists, Generics, Literals, Closures, Anonymous, Infix, Type Bounds

Der Taschenrechner kann also so komisch aussehen wie er will, hauptsache es sind die Konzepte zu erkennen.

Ich erwarte hier von keinen, dass hier jemand für mich lange Zeit investiert. Ich freue mich immer auf Kritik und gott sei dank gibt es immer wieder den einen oder andern, der einfach besser Bescheid weiss 

Der Taschenrechener soll eine kleine Swing Anwendung. Da bietet Scala anscheind auch verschiedene Patterns , wie das Actor Pattern.

Ich lese gerade das Buch : Programming in Scala 
Doch habe ich immense Schwierigkeiten gleich los zu programmieren. Die Syntax ist ein Problem und die Konzepte sind für mich neu.

Ich progge dann gerne den Taschenrechner mal weiter, werde aber sicher wieder an meine Grenzen kommen. 

PS: Ich bin gerne Bereit mein Doku und Präsi dann hier für neue zu Verfügung zu stellen, soweit sie von euch auch gesegnet ist 

Vielen lieben Dank -:toll:

grüße spin


----------



## Antoras (6. Sep 2011)

Wieso hält man einen Vortrag über ein Thema von dem man keine Ahnung hat? Wenn derjenige, der das Projekt bewertet, sich mit Scala auskennt, dann kannst du ganz schön auf die Nase fallen.

Um Konzepte wie Currying und Closures im Detail zu verstehen benötigt es mehr Zeit als den Monat, der dir noch bleibt.


----------



## Landei (6. Sep 2011)

Ich würde vorschlagen, du beschränkst dich ein wenig, und zeigst lieber einige interessante Features etwas detaillierter, anstatt eine Tour de Force durch unbekanntes Gebiet zu reiten.


----------



## 0x7F800000 (6. Sep 2011)

Spin hat gesagt.:


> Der Taschenrechner kann also so komisch aussehen wie er will, hauptsache es sind die Konzepte zu erkennen.


Was du hier bis dahin geboten hast war aber fürchterlich und radikal anti-idiomatisch, so bringst du garantiert keine Scala-Konzepte rüber, sondern sabotierst im besten Fall 20-25 Leuten den Spaß an Scala^^ 



> Actor Pattern.


Actors sind kein Swing-Gedöns, sonden eine andere herangehensweise an paralleles Programmieren.



> Ich lese gerade das Buch : Programming in Scala


Über ein ganzes Buch kannst du garantiert kein Referat halten, da bräuchte man schon eher eine Vorlesungsreihe. Alle Techniken wirst du auch nicht für einen Taschenrechner verbraten können, schränk das ein.


----------



## Spin (6. Sep 2011)

Title:* „Objects, Functions and the JVM - Software development in Scala“*


Introduction
Origin of Scala
Quality and Design Goals
 Characteristics
    Types
    Classes and Inheritance
    Singelton Objects
    Ploymorphism 
    Inheritance
    Mixin-Composition
    Generics
    Functions
 Frameworks - JAVA - Interoperability
 Example Application

Ungefähr so baue ich es denn jetzt auf. Alle Konzepte sind sicherlich nicht mit einmal lesen und ausprobieren verstanden, aber ich versuch mein bestes.

Den Taschenrechner lasse ich mir denn nicht nehmen - dann versuche ich den simple zu gestalten.
Wobei ich ja nicht mal die for hinbekommen habe ^^.

Gilt also noch viel auszuprobieren 
Anregungen sind super herzlich willkommen. 
Welche Themen würde euch denn spontan einfallen um zu zeigen wie sich Scala und Java differenzieren.

Danke.


----------



## 0x7F800000 (6. Sep 2011)

Spin hat gesagt.:


> Title:* „Objects, Functions and the JVM - Software development in Scala“*
> 
> 
> Introduction
> ...


- Spar dir den Geschichtsunterricht, erwähne in einer Zeile, von welchen Sprachen Scala inspiriert wurde.
- Was sollen diese "Design Goals" sein? Wenn du da was von übersichtlichkeit des Codes erzählst, und später mit "arr.apply(3) = 5" kommst, kannst du dir das ganze eigentlich sparen.
- Was verstehst du unter "Characteristics"? 
- Functions kommt an 2. Stelle, nicht an letzte, es ist doch funktionale Sprache
- Sowas wie "Vererbung" und "Polymorphismus" ist nichts Scala-Spezifisches, sondern seit zwei jahrzehnten durchgekaute OOP-basics, darf man ja wohl voraussetzen
- Traits erwähnen, die ganzen spezielleren konstrukten wie modifikationen mit [c]with[/c] bei der instantiierung sollte man weglassen: wird viel seltener verwendet, und kriegt man eh nicht in einer Minute erklärt.
...

Allgemein: mach weniger Blah-Blah, welches allen eh schon bekannt ist, entferne Details, die eh keiner verstehen kann, mach kurze beispiele, bei langen beispielen schaltet das publikum eh ab.



> Ungefähr so baue ich es denn jetzt auf. Alle Konzepte sind sicherlich nicht mit einmal lesen und ausprobieren verstanden, aber ich versuch mein bestes.


Warum ist das ganze auf Englisch? Ist das für die Uni oder wofür?
Warum erklärst du die einzelnen Konzepte nicht an kleinen isolierten Beispielen? Das bringt tausend mal mehr, als irgendein unübersichtliches Taschenrechner-Programm, in dem du nach einem Monat selbst nicht mehr durchblickst.




> Den Taschenrechner lasse ich mir denn nicht nehmen - dann versuche ich den simple zu gestalten.
> Wobei ich ja nicht mal die for hinbekommen habe ^^.


Erzählt mir bitte endlich mal einer, wieso alle so scharf auf diese GUI-Taschenrechner sind? Hast du den Taschenrechner von Google gesehen, siehst du da irgendwelche Knöpfe und Hebel dran? Warum machst du nicht stattdessen irgendetwas sinnvolleres und übersichtlicheres (ohne GUI-Rumgedöns).


> Welche Themen würde euch denn spontan einfallen um zu zeigen wie sich Scala und Java differenzieren.


nenn du mir lieber mal was, wo sie sich nicht differenzieren... Beide compilieren zu JVM-bytecode, das war's eigentlich auch schon... :autsch:


----------



## Spin (6. Sep 2011)

Hallo,

der komplette 1h Vortrag soll auf English sein und die Dokumentation natürlich auch.
Das schreckt mich eher weniger ab 

Ok versuche ich doch einfach nochmal zu erzählen, was ich gerne erreichen möchte bzw. was die Ziele des Vortrages sind. Wir sollen eine Einführung in die Sprache geben und einen indirekten Vergleich mit Java machen, weil das die Sprache ist die uns bis zum 4ten Semester an der Uni begleitet hat.

Da Scala auf Java aufgebaut ist und irgendwie nur die nativen Java Methoden mappt, gibt es sicherlich keine riesigen semantischen Unterschiede. Die Art und Weise ist aber eine komplett Andere und vorallem der funktionale Teil ist gewöhnungsbedürftig --- viel von ML und Haskell , Erlang.

Ich möchte schon mit einem geschichtlichen Einstieg starten und vorallem warum Scala entwickelt wurde sowie welche neuen Vorteile sich dadurch ergeben haben.

Mit Design Goals meine ich halt Ziele des Entwurfs von Scala.

Natürlich ist dann ein syntaktischer Einstieg erstmal interessant und anschließend die neuen Konzepte.


--

Wir sollen eine kleine Anwendung dazu bauen, egal ob viel Code oder nicht. Sie muss auch keine GUI Anwendung sein-

Was würdest du denn für einen Anfänger vorschlagen?

Einen Algorithmus  Bubblesort, Quicksort, A* , Greedy Best Search, oder so?

Einen Konsolen Taschenrechner?
Eine Bewegte Animation?

Was weiss ich - irgendetwas wo man viele Built-In Controll Structures sieht. --- Ich will ja Scala auch bischen können --- 

Danke für eure Zeit!


----------



## Landei (7. Sep 2011)

Spin hat gesagt.:


> Da Scala auf Java aufgebaut ist und irgendwie nur die nativen Java Methoden mappt, gibt es sicherlich keine riesigen semantischen Unterschiede. Die Art und Weise ist aber eine komplett Andere und vorallem der funktionale Teil ist gewöhnungsbedürftig --- viel von ML und Haskell , Erlang.



Scala ist keine "Java-Erweiterung", sondern eine eigenständige Sprache mit eigener Syntax, genau wie Clojure oder JRuby. Was Scala mit Java gemeinsam hat, ist im Prinzip nur die Abarbeitung auf der JVM, also das Bytecode-Format der class-Dateien. Deshalb ist es auch möglich, Java aus Scala aufzurufen (hier wurde darauf geachtet, dass das recht reibungslos funktioniert) und umgekehrt (das ist schon wesentlich tückischer).

"Native Methoden" sind Methoden, die bei Aufruf an externe C/C++  Funktionen (z.B. in DLLs) über das Java Native Interface weitergeleitet werden. Du meinst wahrscheinlich etwas anderes, aber "native Methoden" ist hier der falsche Begriff.


----------



## 0x7F800000 (7. Sep 2011)

Spin hat gesagt.:


> Da Scala auf Java aufgebaut ist und irgendwie nur die nativen Java Methoden mappt, gibt es sicherlich keine riesigen semantischen Unterschiede.


N. E. I. N. Nein. Scala ist kein umdekoriertes Java, es verhält sich auch nicht wie C++ zu C oder irgendsowas ähnliches, trotz aller Kompatibilität. Das ist eine ganz falsche Start-Voraussetzung. Beim OOP-Teil gibt es zwar einige syntaktisch-semantische Gemeinsamkeiten, aber darüber und darunter sieht es bis zum Byte-Code ziemlich anders aus, und das sollte man als Java-Programmierer verstehen, wenn man damit anfängt, sich die Sprache anzuguggen.



> Ich möchte schon mit einem geschichtlichen Einstieg starten und vorallem warum Scala entwickelt wurde sowie welche neuen Vorteile sich dadurch ergeben haben.
> 
> Mit Design Goals meine ich halt Ziele des Entwurfs von Scala.


Okay, wenn du eine ganze Stunde hast...



> Wir sollen eine kleine Anwendung dazu bauen, egal ob viel Code oder nicht. Sie muss auch keine GUI Anwendung sein-


Dann verschwende auf GUI auch keine Zeit: Scala Swing ist einfach gewrappter Java-Swing, und verrät wenig neues über die Sprache. 



> Einen Algorithmus  Bubblesort, Quicksort, A* , Greedy Best Search, oder so?


klingt schon besser, imho


> Einen Konsolen Taschenrechner?



Wenn du unbedingt was mit "rechnen" haben willst, da habe ich was geiles für dich: ein Plotter der Newton-Fraktale für Polynome der Gestalt

```
x^5-4*x^7-13*x^2+x-7
```

Daran könntest du ganz einfach folgende Sachen demonstrieren:
- implementierung der Complexen Zahlen: jeder weiß worum's geht, perfekt um Grundlagen der OOP, case-classes, pattern matching, object-statt-static-methoden und "Operator-überladung" zu demonstrieren
- perfekt um implizite conversions der doubles zu complex zu demonstrieren
- Für ableitung der polynome braucht man eine Schleife, Auswertung der Polynome könnte man mit hilfe von foldLeft o.ä. demonstrieren  
- Newton-verfahren zu implementieren ist ganz leicht, einzeiler mit einer while- oder for-schleife
- Parser-Combinators sollten für polynome ganz simpel sein (viel einfacher als ganzer Taschenrechner), aber genug, um die technik zu demonstrieren
- Auswertung eines solchen Fraktals kann trivial parallelisiert werden: jeder pixel kann einfach einzeln berechnet werden, daran kann man parallele collections demonstrieren
- Ein _bisschen_ GUI, um die rückwärtskompatbilität mit den tollen Java-Bibliotheken zu demonstrieren, indem man das Bild anzeigt.
- Die Bilder sehen geil aus 

Du siehst: ich studiere halt mathe, ich hab nur komische mathematische beispiele auf Lager :bae:


----------



## Spin (7. Sep 2011)

Hallo,

ich habe ziemliche Angst, dass ich dass dann nich schaffe.

Klar kann ich loslegen die Complexen Zahlen zu implementieren, aber ich wäre dann über deine Hilfestellung sehr erfreut. Alleine werde ich dass nicht schaffen.

Hier habe ich schonmal die komplexen Zahlen abgebildet.


```
/**
 * Trait: ArithmenticOperation.
 * A trait encapsulates method and field definitions, which can
 * be reused by mixing them ComplexNumbero a class.
 */
trait Arithmetic {
	
	/**
	 * add two complex numbers (concrete implementation)
	 */
	def add(x:ComplexNumber, y:ComplexNumber): ComplexNumber = 
			new ComplexNumber(
								x.real + y.real ,
								x.im + y.im
			)
	/**
	 * sub two complex numbers values (concrete implementation)
	 */
	def sub(x:ComplexNumber, y:ComplexNumber): ComplexNumber = 
			new ComplexNumber(
								x.real - y.real ,
								x.im - y.im
			)
	/**
	 * multiply two complex numbers values (concrete implementation)
	 */
	def mul(x:ComplexNumber, y:ComplexNumber): ComplexNumber =
			new ComplexNumber(
								x.real * y.real - x.im * y.im,
								x.real - y.im + x.im * y.real
			)
	/**
	 * divide two complex numbers values (concrete implementation)
	 */
	def div(x:ComplexNumber, y:ComplexNumber): ComplexNumber =
			new ComplexNumber(
							(x.real * y.real + x.im * y.im)/(y.real * y.real + y.im * y.im),
							(-x.real * y.im + y.real * x.im)/(y.real * y.real + y.im * y.im)
			)
}
```




```
/**
 * Class to design a complex number.
 */
class ComplexNumber(r:Double,i:Double) {
	
	/**
	 * real part of a complex number
	 */
	var real:Double = r
	
	/**
	 * imaginary part of a complex digit
	 */
	var im:Double = i
	
	/**
	 * absolute value 
	 */
	def abs = Math.sqrt(r*r + i*i);

}
```



```
jeder weiß worum's geht, perfekt um Grundlagen der OOP, case-classes, pattern matching, object-statt-static-methoden und "Operator-überladung" zu demonstrieren
```

Ich habe jetzt in den Klassen OOP drin ^^. Polymorphismus aber mehr auch nicht an spannenden sachen.

Wo würdest du hier jetzt case classes hinpacken?

Bzw.. an welcher Stelle kann ich Konzepte besser verdeutlichen?

So ich schau mal wie ich das Polynom reinbekomme.:rtfm:


----------



## 0x7F800000 (7. Sep 2011)

Hey, Spin, nein, vergiss erstmal dieses "Numeric[T]"-pattern, okay? Das ist ein bisschen zu viel rocket-Science erstmal, hier geht es nicht darum, code für irgendwelche speziellen nativen datentypen zu optimieren, sondern um die Basics, Numeric[T] ist dagegen schon eher fortgeschrittenes Thema. 

Also, ich kann mir sehr gut vorstellen, dass man all diese Konzepte wie folgt demonstrieren kann:

```
package spinsExampleProject

// hier werden gleich Traits und einfache Generics demonstriert
trait Arithmetic[X <: Arithmetic[X]]{ 
  self: X => // definition des self-types, sehr nützlich, um festzulegen, dass "this" später Typ X haben wird

  // haufen abstrakter methoden, die von der Art der Zahlen abhängt
  def one: X
  def *(other: X): X 
  def inverse: X
  def /(other: X) = this * other.inverse // das lässt sich bereits durch andere methoden ausdrücken!
  
  def zero: X
  def +(other: X): X
  def unary_- : X // ein typisches Beispiel für "Operator Overloading"
  def -(other: X) = this + -other // das lässt sich auch durch andere methoden ausdrücken, obwohl's ineffezient ist
  
  // einige nützliche methoden, die _nicht_ von der Art der Zahlen abhängen, 
  // sondern überall gleich sind (für reelle und komplexe zahlen, endliche körper usw.)
  // Das ist der entscheidende Unterschied von Interfaces und traits: bei traits kann man etwas
  // implementieren!
  
  // einfaches quadrieren:
  def square = this * this // hier kommt ins spiel, dass self vom typ X ist, und an *(x: X) übergeben werden kann
  
  // hier könnte man das square-and-multiply verfahren (bauern-multiplikation) basteln,
  // aber du kannst dich ruhig mit einfachen linearen rekursion begnügen, soll ja nur Demo sein
  def pow(i: Int): X = {
    if (i < 0) 
      inverse.pow(-i) 
    else if (i == 0) 
      one 
    else 
      this * this.pow(i - 1)
  }
}
```


```
package spinsExampleProject

// Demo eines case-classes
case class Complex(re: Double, im: Double) extends Arithmetic[Complex]{
  
  // hier muss man nur 6 methoden implementieren und kriegt so "komplizierten" Kram wie pow() geschenkt
  // [es ist nicht kompliziert, aber für die Idee der "Rich interfaces" sollte's reichen]
  def zero = Complex(0, 0)
  def +(c: Complex) = Complex(re + c.re, im + c.im)
  def unary_- = Complex(-re, -im)
  
  def one = Complex(1, 0)
  def *(c: Complex) = Complex(re * c.re - im * c.im, re * c.im + im * c.re)
  def inverse = {
    val sqLen = re * re + im * im
    Complex(re / sqLen, -im / sqLen)
  }
}

object Complex{
  // statische member werden in Scala in companion-objects gespeichert
  val I = Complex(0, 1) 
  
  // sehr wichtig: implicite casts
  implicit def castDoubleToComplex(d: Double) = Complex(d, 0)
  
}
```


```
package spinsExampleProject

import Complex._
import math._

object UsageExample1 {

  def main(args: Array[String]){
    // hier sieht man, dass man nichts sieht:
    // Dank impliciten casts benehmen sich Doubles plötzlich wie Complex!
    val x = 1.5 + 0.3 * I 
    val y = 7.2 - 0.2 * I
    
    // man achte darauf, dass die Ausgabe einigermaßen leserlich ist, obwohl toString nicht ünerschrieben wurde
    println( x * y ) 
    
    // und so funktioniert pattern-matching, man "dekonstruiert" eine Komplexe zahl wieder in Einzelteile:
    val Complex(a, b) = x * ( y + 23.0 - 7.3 * I)
    println("a = " + a + " b = " + b)
    
    // hier ist die anwendung von "pow", welches uns durch Arithmetic umsonst hinterhergeworfen wurde:
    val seventhUnityRoot = cos(2 * Pi / 7) + I * sin(2 * Pi / 7)
    println(seventhUnityRoot pow 7)
  }
  
}
```
Wie Du siehts: alleine mit einem so simplen und allgemein-bekannten Beispiel wie den komplexen zahlen kann man schon Folgendes abdecken:

- OOP basics (classes, methods, member-variables, static variables in companion objects)
- traits (and "rich" interfaces)
- generics
- type-bounds
- self-types
- operator overloading
- implicit casts
- case classes
- pattern matching (at least a single basic example)
- general structure of typical programm with a main-method

Und dabei überforderst du dein Publikum (hoffentlich) nicht mit irgendwelchen völlig unbekannten Konzepten, die von der Sprache ablenken (Komplexe zahlen sollen allgemein bekannt sein, alle Knöpfe und hebel des Swing-frameworks dagegen nicht).

Für Polynome könntest du eine generische classe anlegen, etwa Poly[X <: Arithmetic[X] : Manifest] (das bedeutet, dass die Polynome nur irgendwie geartete "Zahlen" speichern können sollen), in der du das polynom einfach in einem array abspeicherst: dabei kannst du hoffentlich klar machen, dass dank Manifest type-erasure gar nicht mehr soo nervtötend ist. Auswerten könntest du das einfach mit dem Horner-Schema, das wäre imho eine hübsche einzeilige anwendung des foldLeft's, auf der man allerdings nicht rumhacken sollte: Horner schema ist zwar sehr billig, ist aber vielleicht nicht jedem ein begriff...

EDIT: achso, noch was wollte ich loswerden: bei Scala präferiert man kurze Notation, in Anlehnung an andere funktionale Sprachen, einfach weil so viele methoden nach einer zeile schon zu ende sind, und für geübtes Auge auch selbsterklärend implementiert. Bei einer Präsentation würde ich den ganzen Dokumentations-Kram weglassen: Dokumenation ist allgemein bekannt, und wurde nicht erst extra für Scala erfunden, und es ist eh klar, dass "+" die complexen zahlen schon nicht logarithmieren und durcheinanderdividieren wird. Und es gibt überhaupt keinen guten Grund, einen zweiparametrigen Komplex-Konstruktor auf vier Zeilen zu ziehen. Warum "r, c, real und im" alle doppelt, und auch noch mutabel gespeichert werden, ist mir rätselhaft: es macht aus performance gründen schon durchaus sinn, sie mutabel zu machen, aber es geht grad nicht um performance, sondern um ein möglcihst minimales Beispiel, welches in 10 Minuten erklärt ist.


----------



## Spin (7. Sep 2011)

Hallo vielen dank für deine Mühe.

Ich schaue mir denn jetzt erstmal deinen Code genauer an und versuche diesen nachzuvollziehen.
Anhand meines Buches : Programming in Scala kann ich dieses vielleicht schnell hinbekommen.

Weiterhin vielen Dank auch für deine Tipps. Du spricht immer wieder von neuen Sachen, die ich immer nur gehört aber noch nie angewendet habe. 

Mit dennen muss ich mich jetzt erstmal auseinandersetzen bevor ich mit dem Polynom anfange.

Habe mir dazu :
https://dgronau.wordpress.com/tag/type-erasure/

angeschaut.


Du hast mir bisher sehr viel schweiß und Arbeit erspart...und kann ich dir mit programmier kenntnissen schlecht entgegenkommen. ;(

Ich kommentiere das ganze mal ausführlicher und poste das denn. Im Vortrag werde ich dass denn entsprechend entfernen, da sie wirklich nur ablenken.


----------



## 0x7F800000 (8. Sep 2011)

Spin hat gesagt.:


> Hallo vielen dank für deine Mühe.


Nein, ist keine Mühe, diesen Kram habe ich schon so viele hundert mal geschrieben, dass ich inzwischen zum copy-pasten übergegangen bin 



> Mit dennen muss ich mich jetzt erstmal auseinandersetzen bevor ich mit dem Polynom anfange.


Okay. Ich will was sagen: sorry. Ich schmeiß dir ab jetzt keinen fertigen Code an den Kopf, ich versuch's etwas herausfordernder und didaktisch sinnvoller rüberzubringen, ich will eigentlich dein Beispiel nicht highjacken, aber bei Complexen zahlen rutschen mir gleich große Codeblöcke raus 



> Habe mir dazu :
> https://dgronau.wordpress.com/tag/type-erasure/
> angeschaut.


Je oh je... Das ist alles zwar sehr schön, aber zumindest den letzten Vorschlag muss ich als ganz üblen Hack einstufen: es ist lustig, aber ich würde niemandem ernsthaft empfehlen, das so zu machen. Außerdem sind es genau die Beispiele, wo manifest eben _nicht_ hilft. Für dich sollte manifest erstmal lediglich ein schreibtechnisch angenehmer Trick sein, der es ermöglicht, generische Arrays ohne viel Schmerz anzulegen: das könntest du imho bei der Berechnung der Ableitung der Polynome gut demonstrieren.



> Du hast mir bisher sehr viel schweiß und Arbeit erspart...und kann ich dir mit programmier kenntnissen schlecht entgegenkommen. ;(


ja, ich seh's es tut mir leid, ich versuch dich ab jetzt nicht gleich so zu erschlagen^^


----------



## 0x7F800000 (8. Sep 2011)

http://www.java-forum.org/scala-groovy-jython-javafx/124064-freies-ebook-scala-impatient.html#post803412
Bemerkt? Könnte in deinem Fall nützlicher sein, als das etwas zu abgefahrene Buch von Odersky selbst.


----------



## Spin (8. Sep 2011)

Hallo ,

ich gehe gerade deinen Code durch und verstehe so langsam immer mehr  Endlich.

Aber trotzdem habe ich ein paar Fragen :


```
def unary_- = Complex(-re, -im)
```

Warum hat deine Variable hier ein _-  ????
See Question in comments , plz.


```
package spin;

/**
 * Class: Complex 
 * Trait: Arithmetic[T]
 * 
 * A complex number is a number consisting of a real part (re:Double) and an 
 * imaginary (im:Double) part.
 * Class Complex uses a trait called Arithmetic[Complex] to reuse code. This trait
 * encapsulates method and field definitions. (Class Mix in)
 * 
 * 
 * In Addition Class Complex is a case class (sub class).
 * Advantages:	- no new statement, because it adds a factory method
 *				- all arguments get a val prefix, so they are maintained as fields
 *				- adds natural implementations if toString , hashCode, equals
 *				- adds method copy 
 * 
 * Only instances methods:
 * 
 */
case class Complex(re: Double, im: Double) extends Arithmetic[Complex]{
  
  /**
   * A complex number with zero real and zero imaginary part.
   */
  override def zero = Complex(0, 0)
  
  /**
   * A complex number with a real but with a zero imaginary part.
   */
  override def one = Complex(1, 0)
  
  /**
   * Adds two complex numbers.
   */
  override def +(c: Complex) = Complex(re + c.re, im + c.im)
  
  /**
   * Multiply two complex numbers.
   */
  override def *(c: Complex) = Complex(re * c.re - im * c.im, re * c.im + im * c.re)
  
  /**
   * unary complex number
   */
  override def unary_- = Complex(-re, -im)
  
  /**
   * Was ist das? Das Inverse Element? Was ist mit der Dibision?
   */
  override def inverse = {
    val sqLen = re * re + im * im
    Complex(re / sqLen, -im / sqLen)
  }
}

/**
 * This object is called companion object, because it has the same name like class Complex
 * and it can access other's private features.
 * 
 * Only static methods:
 */
object Complex{
  /**
   * define constant : I
   */
  final val I = Complex(0, 1) // Fehler in der Console : Woher weiss ich jetzt ob ich das object oder die klasse meine.
  
  /**
   * implicit cast from double to complex because this cast is not exiting yet.
   * Therefore set imaginary part to zero.
   */
  implicit def castDoubleToComplex(d: Double) = Complex(d, 0)
  
}
```


```
package spin;

/**
 * Trait: Arithmetic[T]
 * 
 * A trait is the same like a java interface. 
 * But in addition traits can be contain definitions (implentation).
 * 
 * Trait Arithmetic[T] uses a Upper Bound - this means that the element type
 * of the X must be a subtype of Arithmetic
 */
trait Arithmetic[X <: Arithmetic[X]]{ 
  /**
   * define a self type - "this" has type X now
   */
  self: X =>
  /**
   * abstract methods:
   */
  def one: X
  def *(other: X): X 
  def inverse: X
  def /(other: X) = this * other.inverse // Wie meinst du dass???
  
  def zero: X
  def +(other: X): X
  def unary_- : X // ein typisches Beispiel für "Operator Overloading", Warum ist das operator overloading?
  def -(other: X) = this + -other 
  
  /**
   * A trait feature : method definitions.
   * "this" is type X
   */
  def square = this * this 
  
  /**
   * potenz function - exponent must be a int
   */
  def pow(i: Int): X = {
    if (i < 0) 
      inverse.pow(-i) 
    else if (i == 0) 
      one 
    else 
      this * this.pow(i - 1)
  }
}
```

Kannst du mir nochmal kurz inverse.pow erklären?
Da fehlt mir gölaube ich das verständnis zu Komplexen Zahlen gerade 


Danke und dann schaue ich mal nach dem Polynom. 

Und nein ich bin sehr dankbar das du mir viel Arbeit bisher abgenommen hast , denn so habe ich einiges an Verständnis gewonnen.  Vielen Dank.

Weiter dank für den Link , der ist auch sehr hilfreich.

Ich nimm mir jetzt ein Polynom.
Dann muss ich es in ein Real Teil und Imaginär teil zerlegen.
Dann Gleichung aufstellen
Dann Ableiten nach Newton , damit ich die gleichung lösen kann.

Also so implementieren wie ich es hier mathematisch gefunden habe :
http://didaktik.mathematik.hu-berlin.de/files/2011_fraktale.pdf

Vielen Dank!

grüße spin


----------



## Landei (8. Sep 2011)

Spin hat gesagt.:


> Hallo ,
> 
> ich gehe gerade deinen Code durch und verstehe so langsam immer mehr  Endlich.
> 
> ...



Bei Bezeichnern dürfen Buchstaben/Zahlen und Sonderzeichen nicht gemixt werden - es muss ein _ dazwischenstehen. Ist auch logisch, sonst wären auch Sachen wie [c]a+b*c[/c] gültige Bezeichner. Das [c]unary_[/c]-Prefix wird natürlich benötigt, um zwischen der unären und binären Verwendung des Operators unterscheiden zu können. Für ein normales binäres Minus kannst du einfach [c]def -(c: Complex) = Complex(re - c.re, im - c.im)[/c] schreiben


----------



## 0x7F800000 (8. Sep 2011)

Spin hat gesagt.:


> ```
> def unary_- = Complex(-re, -im)
> ```
> 
> Warum hat deine Variable hier ein _-  ????


Das ist keine "Variable", das ist ein unäres Minus. Minus braucht nämlich nicht 2 Argumente: ein unäres Minus subtrahiert nichts, sondern dreht das Vorzeichen um. Wenn du eine Variable x = 7 hast, dann kannst du "-x" schreiben, und es liefert den Wert -7.

Diese Konstruktion mit "unary_" funktioniert eigentlich nur für Operatoren - und ~, spart aber solchen ärger wie "negate(x)" oder "x.negative" statt dem vertrauten "-x".



> * In Addition Class Complex is a case class (sub class).


Was heißt "sub class"?



> * Advantages:	- no new statement, because it adds a factory method


Heb das "new"-irgendwie hervor, also "no "new" keyword is required for instantiation, because a factory method is added automatically"




> * A complex number with a real but with a zero imaginary part.


Warum nicht einfach "complex one"? Bzw warum nicht gleich Kommentar sparen... Ist doch wirklich selbsterklärend, aber dazu habe ich mich ja schon geäußert...



> /**
> * unary complex number
> */


klingt irgendwie nach nichts, sollte wohl "unary minus for complex numbers" sein



> /**
> * Was ist das? Das Inverse Element? Was ist mit der Dibision?
> */
> override def inverse = {
> ...


Joah, so wird halt das Inverse der komplexen Zahlen berechnet, wenn ich mich nicht gröbst verhauen habe. Division *sollte* im "echten Leben" zwar aus performance gründen überschrieben werden, dies ist aber nicht dringend notwendig, weil Arithmetic eine default-implementierung mitliefert: a/b ist ja nichts anderes als a*(b^-1) bzw a * (b.inverse) in unserer notation hier.



> final val I = Complex(0, 1) // Fehler in der Console : Woher weiss ich jetzt ob ich das object oder die klasse meine.


wie, was, welche Konsole? Das alles kompilliert eigentlich einwandfrei. Complex(0, 1) ruft hier eigentlich das apply() des Companion objektes auf, dieses apply() wird durch case-classes automatisch bereitgestellt: wie gesagt, kein "new" erforderlich.



```
* A trait is the same like a java interface. 
 * But in addition traits can be contain definitions (implentation).
```
eine Formulierung mit "similar to" fänd ich hier angebrachter



> def unary_- : X // ein typisches Beispiel für "Operator Overloading", Warum ist das operator overloading?


naja, man definiert eigene operatoren: das kennt man in C++ als "operator-overloading", welches (zumindest mir) so schmerzlich in Java fehlte.



> * "this" is type X


"this" *has* type X 
oder
"this" is of type X
und dann fehlt da noch
because of the self-type definition, so method *() can be called on "this"
  */
  def square = this * this 



> /**
> * potenz function - exponent must be a int
> */


Es heißt "power", keine "potenz"... "Potency" ist im Englischen nur noch "Manneskraft"^^ 




> Kannst du mir nochmal kurz inverse.pow erklären?
> Da fehlt mir gölaube ich das verständnis zu Komplexen Zahlen gerade


Das ist Arithmetic: es funktioniert für _alles_, was du unter "Zahl" verstehst, also auch gewöhnliche reelle Zahlen oder Brüche.

Hier steht im Prinzip nichts anderes, als folgende Banale rekursion:
a^0 = 1
a^n = a*a^(n-1)
so viel Mathe dürfte niemanden überfordern 
Diese rekursion verringert den exponenten, und funktioniert natürlich nur für positive exponenten. Damit es auch mit negativen klappt, macht man davor eine zusätzliche Abfrage, und wenn der exponent negativ ist, dann verwendet man
a^-n = (a^-1)^n = a.inverse pow n 



> Ich nimm mir jetzt ein Polynom.
> Dann muss ich es in ein Real Teil und Imaginär teil zerlegen.


Nenene, mach Polynom schön generell für beliebige "Zahlen", (also das, was wir hier "Arithmetic" getauft haben), also sowas in der Art:

```
class Poly[A <: Arithmetic[A]]
```
Ableiten funktioniert immer gleich: du multiplizierst den koeffizienten mit dem exponenten, und verringerst den exponenten um 1. Wenn du die Koeffizienten einfach in einem Array abspeicherst, müsste sowas rauskommen:

a*x^3 + b*x^2 + c*x + d
wird gespeichert als [d, c, b, a]  (index im array = exponent)
beim ableiten ergibt sich [c * 1, b * 2, a * 3] (das ist eine einzige, ganz leichte schleife),
was nichts anderes bedeutet, als
3*a*x^2 + 2*b*x + c

Ich merke gerade: man sollte bei Arithmetic noch multiplikation mit ints hinzufügen, und bei complex auch implementieren. Das funktioniert dann aber wirklich für alles, was sich halbwegs wie eine Zahl benimmt: von irgendwelchen Imaginärteilen ist da gar nicht die Rede: man braucht solche gruseligen Details nicht zu kennen, wenn man ein Polynom ist 




> Dann Gleichung aufstellen
> Dann Ableiten nach Newton , damit ich die gleichung lösen kann.


Welche "Gleichung aufstellen"? Nein nein, ich hab's eben deswegen vorgeschlagen, weil es vergleichsweise leicht ist, aber hübsche resultate liefert. Du musst lediglich ein Polynom einlesen, ihn wie oben beschrieben ableiten, und dann für jedes x_0 aus deinem "Bild" (also einem Quadratischen Ausschnitt der Komplexen Ebene) einfach 30-50 Mal in schleife Folgende Rechnung ausführen:

```
x = x - f(x) / fDerivative(x)
```
und am ende einfach guggen, wo du landest. Mehr ist das nicht, nur stures rechnen. Nochmal in pseudocode:

```
f = (polynom einlesen)
fDerivative = f.derive

für jede zeile r aus dem bild{
  für jeden pixel an der stelle c aus der zeile{
    var x = Complex( (c / Bildbreite - 0.5) * 10, (r / Bildhöhe - 0.5) * 10 )

    wiederhole 50 mal
      x -= f(x)/fDerivative(x)

    färbe den pixel (r,c) mit der farbe Color(127 + cos(x.im)*127, 127 + sin(x.re)*127, 0)  
  }
}
```
Nix mit gleichungssystemen auflösen hier, nur ganz stures rechnen.



> Also so implementieren wie ich es hier mathematisch gefunden habe :
> http://didaktik.mathematik.hu-berlin.de/files/2011_fraktale.pdf


Ojojojojoj, was zur brennenden Hölle... 

Also, kurze Erläuterung:
Es ist nicht vom Mathematikern, sondern von 6 Kiddies aus 5 Gymnasien Geschrieben, und es hat entsprechendes Niveau.
Wenn irgendwo "didaktisch sinnvoll" hervorgehoben wird, dann ist es mit größter Wahrscheinlichkeit irgendein von Lehrämtlern fabrizierter Murks.
In diesem fall ist sieht's für mich nach murks aus. Wie kommen die leute auf irgendwelche Jakobi-Matrizen?

Sieh dir lieber das da an: Newton fractal - Wikipedia, the free encyclopedia Da steht die ganz normale Iteration, völlig harmlos, keine Matrizen weit und breit.

Außerdem: wenn dir der Kram mit Polynomen nicht zusagt, dann ist es genau der Richtige zeitpunkt, um auf Julia-Mengen umzuspringen: man müsste lediglich statt

x = x - f(x)/f'(x)

einfach nur

x = x*x + c

mit c  = Complex(0.285, 0.01) hinschreiben, sieht auch hübsch aus, und an Polynomen erkennt man vielleicht dann doch nicht soo viel... Hm: vielleicht sparst du dir lieber wirklich die Polynome, und bastelst lieber stattdessen doch noch eine kleine GUI, wenn du die GUI's so magst  Nur halt ohne viele Knöpfe, sondern mit nur einer Eingabe-Zeile und einem "draw"-Button.


----------



## Spin (9. Sep 2011)

Vielen lieben Dank auch für diese ausführliche Darstellung und Erklärung.

Die GUI habe ich jetzt fertig und jetzt muss ich eine komplexe zahl parsen und in deren einzelteile (real teil und imaginär teil zerlegen ... quasi eine komplexe zahl draus machen (Complex(r,i))


```
package spin
import scala.swing._
import scala.swing.event._
import scala.swing.Swing._


object FractalGUI extends SimpleSwingApplication {

  override def top = new MainFrame {
    title = "Newton Fractale (Julia Set)"
    size = new java.awt.Dimension(500,400)
    location = new java.awt.Point(100,100)
    visible = true
    
    class DrawComp extends Panel {
      preferredSize = new Dimension(200, 200)
      
       override def paintComponent(g: Graphics2D) {
    	  g.setColor(java.awt.Color.GRAY)
          g.fillRect(0, 0, size.width, size.height)
       }
    }

    // button draw
    val buttonDraw = new Button { text = "Draw" }
    val inputField = new TextField(10)
    val inputLabel = new Label("Plz insert a complex number: ")
      
    // view panels
    val panelTop = new FlowPanel {
    	contents += new DrawComp
    }
    
    val panelBottom = new FlowPanel {
    	contents += buttonDraw
    	contents += inputLabel
    	contents += inputField
    }
    
    // add to content
    contents = new BorderPanel {
      import BorderPanel.Position._
      add(panelTop,BorderPanel.Position.Center)
      add(panelBottom,BorderPanel.Position.South)
    }
      
    listenTo(buttonDraw)
    reactions += {
      case ButtonClicked(e) =>
        
        println(inputField.text)
    }
  }
}
```

Weiterhin habe ich alle deine Anmerkungen mir sehr zu Herzen genommen und entsprechend angepasst im Quellcode.

Du hattest mit deinem Kommentar  - "Subclass???" vollkommen recht, denn dieser war unsinnig!!




GUI:

Ich hoffe dass du dir das so ungefähr vorgestellt hast. In der Klasse DrawComp werde ich dann alles zeichnen.

Ich mache denn mal weiter  Kommentare sind von allen herzlich willkommen.


----------



## Landei (9. Sep 2011)

Vielleicht kannst du dir hier etwas abschauen: Mischmasch  eSCALAtion Blog

Es verwendet allerdings kein Scala-Swing und auch keine komplexen Zahlen.


----------



## Spin (9. Sep 2011)

Danke Landei,

ich verzweifel am parsing und entscheide mich jetzt für ein Textfeld für den Realanteil und eins für den Imaginär anteil.


----------



## Spin (9. Sep 2011)

```
package spin
import scala.swing._
import scala.swing.event._
import scala.swing.Swing._
import Complex._
import java.awt.image.BufferedImage


object FractalGUI extends SimpleSwingApplication {

  var complexNumber :Complex = null
  
  
  override def top = new MainFrame {
    title = "Newton Fractale (Julia Set)"
    size = new java.awt.Dimension(500,400)
    location = new java.awt.Point(100,100)
    visible = true
    
    class DrawComp extends Panel {
      preferredSize = new Dimension(200, 200)
      
       override def paintComponent(g: Graphics2D) {
    	  
    	  if(complexNumber != null){
    	    //g.drawString(complexNumber.toString(),50,50)
    	    
    	    // image to show newton fractal
    	    val bi = new BufferedImage(200+1, 200+1, BufferedImage.TYPE_INT_RGB)
    	    
    	    var scale = 100
    	    
    	    for(x <- 0 to 200; y <- 0 to 200){
    	      
	    	     var value = Complex( (x/ 200 - 0.5) * 10, (y/ 200 - 0.5) * 10)
	    	     var count = 0
	    	     
	    	     while(count <= 50){
	    	       value += value * value + complexNumber 
count +1
	    	     }
	    	     
	    	     bi.setRGB(127 + Math.cos(value.im).toInt *127, 127 + Math.sin(value.re).toInt *127, 0)
    	     }
		      g.drawImage(bi, 0, 0, null)
    	  }
       }
    }

    // button draw
    val buttonDraw = new Button { text = "Draw" }
    val inputFieldReal = new TextField(10)
    val inputFieldIm = new TextField(10)
    val inputLabelReal = new Label("Real Part: ")
    val inputLabelIm = new Label("Imaginary Part: ")
      
    // view panels
    val panelTop = new FlowPanel {
    	contents += new DrawComp
    }
    
    val panelBottom = new FlowPanel {
    	contents += buttonDraw
    	contents += inputLabelReal
    	contents += inputFieldReal
    	contents += inputLabelIm
    	contents += inputFieldIm
    }
    
    // add to content
    contents = new BorderPanel {
      import BorderPanel.Position._
      add(panelTop,BorderPanel.Position.Center)
      add(panelBottom,BorderPanel.Position.South)
    }
      
    listenTo(buttonDraw)
    reactions += {
      case ButtonClicked(e) =>  
        
        try {
          var real = inputFieldReal.text.toDouble
          var im = inputFieldIm.text.toDouble

          complexNumber = real + im * I
          
        } catch {
          	case error: NumberFormatException => 
          		"Number Format Exception - real input is invalid."
        }
        repaint
    }
  } // end main frame
}
```

Hallo, ich schaue mir jetzt schon zum 10ten mal den Algorithmus an und ich verstehe ohne Kommentare überhaupt nichts außer dass als aller erstes ein neues Bild erstellt wird.

Ich habe jetzt zweimal alles versucht, aber das Programm hängt sich immer auf und ich muss alles schließen.

1. BufferedImage erstellen ( Bildpixel schreiben ) 
-  R,G,B Werte liegen zwischen 0 - 255

Muss ich für jeden Pixel noch eine Complexe Zahl definieren?

2. Bild durchlaufen von oben links bis unten rechts.

3. Dann den Algo

4. Pixel setzen

5. Bild neuzeichnen.

Was habe ich falsch gemacht und kann mir nochmal jemand erkären 
wieso: 127 + cos(x.im)*127

??

Vielen lieben dank.


----------



## 0x7F800000 (9. Sep 2011)

ja, das ist es doch schon fast 

Aber irgendwie hast du da angefangen wilde "global vars" in den code zu streuen, ich hab's ein klein wenig umgepackt:

```
package spinsExampleProject

import scala.swing._
import scala.swing.event._
import scala.swing.Swing._
import spinsExampleProject.Complex._
import java.awt.image.BufferedImage
import math._
 
 
object FractalGUI{
  def main(args: Array[String]){
    println("huhu")
    //*
    val top = new MainFrame {
    title = "Julia Set"
    size = new java.awt.Dimension(500,400)
    location = new java.awt.Point(100,100)
    visible = true
    
    class DrawComp extends Panel {
      val resolution = 512
      preferredSize = new Dimension(resolution, resolution)
      protected val bi = new BufferedImage(resolution, resolution, BufferedImage.TYPE_INT_RGB)
      var c: Complex = -0.835 - 0.2321 * I
      calculateImage() // passiert bei initialisierung
      
      def calculateImage(){
        val w = bi.getWidth
        val h = bi.getHeight
        
        println("recalc for" + c)
        
        for(x <- 0 until w; y <- 0 until h){
              
          var value = Complex( (x/w.doubleValue - 0.5) * 4, (y/h.doubleValue - 0.5) * 4) // SO teilt man ints vernünftig
          
          // geschachtelte def's hattest du auch noch nicht gezeigt, wird mal langsam Zeit
          def countIterationsUntilBailout(max: Int, bailOut: Double): Int = {
            var count = 0
            while(count < max){
              value = value * value + c // so sollt's klappen, schlag wiki seite nach
              count += 1
              if( value.absSq > bailOut) return(count);
            }
            (value.absSq / bailOut * max).intValue
          }
          
          val maxIters = 20
          val iters = countIterationsUntilBailout(maxIters, 10)
          
          // konstruktion "sin(x).toInt" macht keinen sinn: es ist fast immer 0
          // und überhaupt: wie hast du denn hier rgb gesetzt? Es erwartet doch nicht (r,g,b), sondern (x,y,argb)!!
          val argb = 
            0xFF000000 + 
            (127 + cos(iters/maxIters.doubleValue * 0.98 +123)*120).toInt << 24 + 
            (127 + sin(iters/maxIters.doubleValue * 0.4 + 89)*120).toInt << 16 +
            (127 + sin(iters/maxIters.doubleValue * 7 + 23)*120).toInt 
          // die farbe ist von der anzahl der iterationen abhängig und mehr oder weniger zufällig
          bi.setRGB(x, y, argb)
        }
      }
      
      override def paintComponent(g: Graphics2D) {
        g.drawImage(bi, 0, 0, bi.getWidth, bi.getHeight, null)
      }
    }
 
    // button draw
    val buttonDraw = new Button { text = "Draw" }
    val inputFieldReal = new TextField(10)
    val inputFieldIm = new TextField(10)
    val inputLabelReal = new Label("Real Part: ")
    val inputLabelIm = new Label("Imaginary Part: ")
    
    // draw component
    val drawComponent = new DrawComp{
      listenTo(buttonDraw)
      reactions += {
      case ButtonClicked(e) =>  
        
        try {
          val real = inputFieldReal.text.toDouble
          val im = inputFieldIm.text.toDouble
          c = real + im * I
          calculateImage()
          repaint()
        } catch {
            case error: NumberFormatException => c = 0 // auf default zurücksetzen, kreis malen
        }
      }
    }
    
    // view panels
    val panelTop = new FlowPanel {
        contents += drawComponent
    }
    
    val panelBottom = new FlowPanel {
        contents += buttonDraw
        contents += inputLabelReal
        contents += inputFieldReal
        contents += inputLabelIm
        contents += inputFieldIm
    }
    
    // add to content
    contents = new BorderPanel {
      import BorderPanel.Position._
      add(panelTop,BorderPanel.Position.Center)
      add(panelBottom,BorderPanel.Position.South)
    }
  } // end main frame
  //*/
  }
}
```

Der Grund, warum du nichts gesehen hast: es ist viel zu schnell nach Unendlich abgehauen, also war alles schwarz. Die Färbe-taktik, die ich zuerst vorgeschlagen hatte, funzte nur für Newton-Fraktale, weil die eben _gegen Nullstellen konvergieren_, statt einfach abzuhauen.

Ich habe jetzt den code umgeändert, der vergibt die Farbe jetzt nicht nach der Distanz zum Ursprung am Ende der Iteration, sondern nach der Anzahl der schritte, nach der die Iterationsfolge aus dem Kreis mit radius sqrt(bailOut) rausspringt.

Die farben sind irgendwie voll finster geraten, kann man aber später noch abändern.

Kann's später gerne genauer erläutern, bin an diesem Wochenende erstmal voll unter Stress, sorry.

EDIT: Achso, "SimpleSSwingApplication" ist sicher tolle Sache, aber Eclipse wollte nicht, also hab ich's kurzerhand weggeworfen^^


----------



## Spin (9. Sep 2011)

Ich wollte es mal ausprobieren, aber ichj habe zwei Fehler beim kompilieren:


```
.\FractalGUI.scala:41: error: value absSq is not a member of Complex
              if( value.absSq > bailOut) return(count);
                        ^
.\FractalGUI.scala:43: error: value absSq is not a member of Complex
            (value.absSq / bailOut * max).intValue
                   ^
two errors found
```

Du hast sicherlich in der Klasse Complex noch eine Methode hinzugefügt.
Kannst du die noch posten? Bitte , danke.


----------



## 0x7F800000 (9. Sep 2011)

Steht für "Absolute Value squared"

Das Quadrat des Betrages für eine komplexe zahl auszurechnen kriegst du sicherlich auch so hin


----------



## Spin (10. Sep 2011)

Jupp ich denke schon 


```
def absSq = {
    val sqLen = re * re + im * im
    sqrt(sqLen) * sqrt(sqLen)
  }
```



Achso :


```
def countIterationsUntilBailout(max: Int, bailOut: Double): Int = {
            var count = 0
            while(count < max){
              value = value * value + c // so sollt's klappen, schlag wiki seite nach
              count += 1
              
              if( value.absSq > bailOut) return(count);
            }
            (value.absSq / bailOut * max).intValue
          }
          
          val maxIters = 20
          val iters = countIterationsUntilBailout(maxIters, 10)
          
          // konstruktion "sin(x).toInt" macht keinen sinn: es ist fast immer 0
          // und überhaupt: wie hast du denn hier rgb gesetzt? Es erwartet doch nicht (r,g,b), sondern (x,y,argb)!!
          val argb = 
            0xFF000000 + 
            (127 + cos(iters/maxIters.doubleValue * 0.98 +123)*120).toInt << 24 + 
            (127 + sin(iters/maxIters.doubleValue * 0.4 + 89)*120).toInt << 16 +
            (127 + sin(iters/maxIters.doubleValue * 7 + 23)*120).toInt 
          // die farbe ist von der anzahl der iterationen abhängig und mehr oder weniger zufällig
          bi.setRGB(x, y, argb)
        }
      }
```

Kannst du mir diesen Teil noch ein wenig genauer erkären?
Wie ist dass mit den Iterationsschritten gemeint?:rtfm:

Woher kommen die Werte die du bei der val argb benutzt?
Das shiften verstehe ich 

Vielen dank


----------



## Landei (10. Sep 2011)

[c]sqrt(sqLen) * sqrt(sqLen)[/c] ist gleich [c]sqLen[/c] (für positive Werte).


----------



## 0x7F800000 (10. Sep 2011)

Spin hat gesagt.:


> ```
> def absSq = {
> val sqLen = re * re + im * im
> sqrt(sqLen) * sqrt(sqLen)
> ...


Du ziehst doch keine Wurzel aus dem Zeug, um's gleich zu quadrieren?


Also, du hast eine Folge von komplexen Zahlen, die ganz lustig in der Ebene rumhüpft.
Du beobachtest sagen wir mal 50 Schritte. Wenn die folge nach diesen 50 schritten im Kreis vom Radius sqrt(bailOut) bleibt, dann färbst du den dazugehörigen Startpunkt zum beispiel schwarz. Ansonsten schaust du, nach wie vielen Schritten die Folge aus diesem Kreis herausspringt, und färbst den Startwert entsprechend der Anzahl der Sprünge.



> Woher kommen die Werte die du bei der val argb benutzt?


Die sind irgendwie zufällig hingehackt, und nicht besonders gelungen. Ich beschreibe dir am Dienstag eine etwas schönere Strategie, hab im Moment etwas wenig Zeit, sorry. Aber ab Dienstag bin ich wieder da.


----------

