„Und damit kommen wir zu der hässlichen Seite von Scala“

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

„Und damit kommen wir zu der hässlichen Seite von Scala“
Was ist eure Lieblingssyntax?

Finde ja folgendes von den Folien schon spannend ([m]<%[/m], [m]for[/m] … [m]forall(_)[/m]):

def sorted[T <% Ordered[T]](xs:List[T]) =
    (for {(x, y) <- pairs(xs)}
        yield {x <= y}).forall(_)

Oder das ([m].:\ [/m], [m]&&[/m]):

def forall[A]: (A=>Boolean) => List[A] => Boolean =
    p => xs => (for {x <- xs} yield p(x)).:\(true)(_&&_)

Auch ganz schön (wenn jetzt auch nicht syntaktisch) ist ja auch diese Zeile von den Folien: [m]case whatever => whatever[/m] :slight_smile:

Morgen wenn die Abgabefrist für die Hausaufgabe vorbei ist, poste ich auch mal meine Lieblingszeile aus der Pascal.scala.


Aber da hast du mich in der Vorlesung heute falsch verstanden und daher auch im falschen Kontext zitiert:
Die obigen Beispiele gehören noch zur „schönen (weil funktionalen) Seite von Scala“… :smiley:

Hier noch eine Eiswaffel für dich: [m]<%[/m]

Edith bietet zur Abstimmung:
http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List
=> alle Methoden zu Beginn der lexikographisch sortierten Liste, z.B. [m]def /:[B](z: B)(op: (B, A) ⇒ B): B[/m] - nicht zu verwechseln mit [m]def :\[B](z: B)(op: (A, B) ⇒ B): B [/m]!

=> Methode [m]protected final def Value: Value = Value(nextId)[/m] (Z.135) vs. Klasse [m]abstract class Value extends Ordered[Value][/m] (Z.191)
[Edith²: das erste [m]def Value[/m] ist ein Methodenname, das zweite [m]: Value =[/m] ist eine abstrakte Klasse als Rückgabetyp und das dritte [m]Value(nextId)[/m] ist eigentlich der Aufruf der Methode [m]apply[/m] des Companion-Objects der Klasse Value…]

und last but not least: Scala 3
[m]final case class ::[B](hd: B, tl: List[B]) extends List[B] with Product with Serializable[/m]
vs.
Methode [m]def ::(x: B): List[B][/m]


Ich weiß, ich fand das Zitat nur so schön.

Vielen Dank, bei den Termperaturen echt toll.

Edit: Hat das in Scala eigentlich auch so lustige Namen wie die ganzen Operatoren in Perl?


Siehe: https://www2.cs.fau.de/teaching/SS2013/PFP/secure/slides/pfp-12.pdf (F. 12-37 bzw. 12-40 bzw. 12-44): „View Bound


Naja, da war man bei Perl aber kreativer. perlsecret - Perl secret operators and constants - metacpan.org

Also Flaming X-Wing macht ja schon bisschen mehr her als View Bound.


Hier wie versprochen meine Lieblingszeile aus der [m]Pascal.scala[/m] (Wie war das mit diesen Tupeln eigentlich gedacht? Ich schlepp die ja nur mit, weil es die Aufgabestellung so fordert):

case l => for { p <- pairs(List((0,0,0)) ::: l ::: List((0,0,0))) } yield (p._1._2, p._1._2 + p._2._2, p._2._2)

Und jetzt beteiligt sicht hier doch auch mal jemand außer JohnDoe mit schönen Codebeispielen. :slight_smile:


Da das Pascalsche Dreieck bereits in der Vorlesung behandelt wurde, wurde die Aufgabe deshalb um eine “akademische” Fragestellung erweitert: Tupel.


Wenn ich doch nur so schönen Code hätte 0_o
Wobei ja Schönheit im Auge des Betrachters liegt. Ich hab mich mit pattern-matching und einer extra Funktion zum berechnen der nächsten Zeile zufrieden gegeben


Zur Abwechslung auch mal eine ernstgemeinte Frage: Gibt es einen Unterschied zwischen [m]for { x ← xs } yield x[/m] und [m]for ( x ← xs ) yield x[/m].

Wenn nein: Warum existieren dann überhaupt beide Möglichkeiten?


Ja es gibt einen kleinen Unterschied:
Die Variante mit der runden Klammer erwartet Semikolons zwischen mehreren Generatoren, wohingegen die Variante mit der geschweiften Klammer keine Semikolons braucht.
Letztere Variante scheint sich wie ein Code-Block zu verhalten und das letzte Ergebnis des Code-Blocks wird als sog. Sequence für das for verwendet. Durch die fehlenden Semikolons wird es aber schwer einzusehen, wo die letzte Sequence in dem Block beginnt, da sie aus einem Generator, einer evtl. vorhandenen Anweisung und evtl. einem Guard besteht.

Siehe hierzu auch Abschnitte 23.1 und 7.3 in http://www.artima.com/pins1ed/for-expressions-revisited.html)


Musterbeispiel an Hässlichkeit:

def fullAdder: (((Bit, Bit)) => (Bit, Bit)) => ((Bit, Bit), Bit) => (Bit, Bit) = { f => (a, c) => ((f((f(a._1, a._2))._1, c)._1), or((f((f(a._1, a._2))._1, c))._2, f(a._1, a._2)._2))}

Man muss aber nicht alles in eine Zeile schreiben, nur weil man es kann.

Man könnte sich auch Zwischenergebnisse definieren, wodurch das ganze dann verständlicher wird, z.B.

val ha1 = f(a)
// usw.
1 Like

a ist ein Tupel. f(a) hätts also auch jeweils getan statt f(a._1, a._2), sowie f(a._1, a._2)._1 statt (f(a._1, a._2)). Viel leserlicher wirds dadurch nicht aber immerhin. War schon ein ziemliches gefummel die Adder.scala.


Habe da noch was wunderschönes gesehen, weswegen ich den Thread leider wiederbeleben muss:

scala> null.asInstanceOf[Int] == null
<console>:8: warning: comparing values of types Int and Null using `==' will always yield false
              null.asInstanceOf[Int] == null
                                     ^
res0: Boolean = true
2 Likes

Eigentlich sollte das zur Laufzeit laut Spec eine NullPointerException werfen, siehe Diskussion hier: https://groups.google.com/forum/#!searchin/scala-user/null$20asInstanceOf/scala-user/f0c9lPMf1E0/gxik5fgWKZEJ