Aufgabe 11.6

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.

Aufgabe 11.6
Wie kann ich in dem object Endian auf die Enumeration EndianSkeleton.Bit zugreifen?


Durch Verwendung einer Import-Anweisung: import EndianSkeleton.Bit._

Falls man die Funktion power auch noch benötigt, dann vielleicht auch:

import EndianSkeleton._
import EndianSkeleton.Bit._

Warum import EndianSkeleton.Bit._ und nicht import EndianSkeleton.Bit?

Und weshalb geht es nicht wenn ich den ganzen Namen angebe. Also List[EndianSkeleton.Bit]?


EndianSkeleton.Bit macht nur das object Bit bekannt, nicht aber dessen Inhalt. Siehe hierzu auch Folien 11-37f.
Die zu verwendenden Konstanten High und Low sind aber Inhalte des objects. Folglich muss beim Import der Namensraum durch das “._” erweitert werden.

Möchte man eine Enumeration als Typparameter verwenden so kann man das wie folgt tun:

// Variante a)
val testA = List[EndianSkeleton.Bit.Bit](EndianSkeleton.Bit.High, EndianSkeleton.Bit.Low)

// Variante b)
import Bit._
val testB = List[Bit](High, Low)

Nur durch das import Bit._ verhält sich eine Scala-Enumeration so, wie man einen Aufzählungstyp z.B. aus Java kennt. Hintergrund ist der, dass Scala nativ keine Aufzählungstypen hat. Stattdessen gibt es die sog. case classes (siehe Folien 11-39ff.), mit denen man ebenfalls (Aufzählungs-)Konstanten definieren kann, die zudem eigene Felder und Methoden haben können (auch ähnlich zu den Java Enums). Als Alternative könnte man somit auch folgendes definieren:

trait Bit
case class Low extends Bit
case class High extends Bit
	
val testC = List[Bit](High(), Low()) 

Was hier aber stört sind die zusätzlichen Klammern, mit denen zudem jeweils neue Objekte vom Typ High oder Low erzeugt werden. Dadurch ist das keine echte Alternative. Als Lösung bringt Scala das Enumeration-Objekt mit und mit der richtigen Import-Anweisung geht alles problemlos.

Weiterführende Anmerkung:
Eine List[EndianSekeleton.Bit] macht kaum Sinn, da es von dem object Bit lediglich eine einzige Instanz gibt. Möchte man das aber trotzdem haben, so müsste man List[EndianSekeleton.Bit.type] schreiben. Man könnte in so eine Liste lediglich die eine Instanz packen (gerne aber auch mehrfach): List[EndianSekeleton.Bit.type](EndianSekeleton.Bit, EndianSekeleton.Bit, EndianSekeleton.Bit). Aber: was soll man damit tun? => das macht keinen Sinn.


Das „Störende“ kann man hingegen u.U. umgehen, indem man gleich Singletons definiert (welche Nachteile man sich damit einhandelt, bleibt dem geneigten Leser überlassen):

[m]trait Bit
case object Low extends Bit
case object High extends Bit

val testC = List[Bit](High, Low)
[/m]


Ich haette eine Frage bzgl. der 11.6 c)

Darf ich generell die Methode List.init verwendet, die bewirkt, dass das letzte Element abgeschnitten wird? So kann ich das ganze wunderbar mit Rekursion machen. In der Vorlesung hiess es ja, es ist ganz kompliziert, zum letzen Element zu kommen. Vllt ist diese Methode ja zu aufwaendig und irgendwas durften wir ja auch nicht benutzen, irgendwas mit mutable…

Danke schonmal :slight_smile:


Sofern die Aufgabenstellung es nicht verbietet, darf man alles verwenden, was keine Seiteneffekte hat. D.h. var und alle mutable, d.h. veränderbaren Objekte sind verboten. Meist sind aber Methoden/Funktionen die bei der Lösung helfen in der Aufgabenstellung angegeben, sofern sie nicht schon aus der Vorlesung bekannt sind.

List.init darf man verwenden, da keine Seiteneffekte.


D.h. ich darf auch Int.toBinaryString verwenden?


Darüber hatten wir uns hier am Lehrstuhl zum Zeitpunkt der Aufgabenerstellung unterhalten und sind zu dem Schluss gekommen, dass das auch erlaubt ist. Da wir mit High und Low anstelle von 0 und 1 arbeiten bietet toBinaryString lediglich eine Teillösung. Die Gesamtlösung ist unabhängig vom Lösungsweg vom Aufwand her nahezu immer gleich.


Sollen wir bei dieser Aufgabe also wirklich die Dinge aus der EndianSkeleton.scala importieren statt diese einfach als Vorlage für die Abgabe zu verwenden?

Edit: Und das mit Endianness üben wir aber nochmal. :wink:


Ja (wenn 1 bis 2 import-Anweisungen jemanden vor ein unüberwindliches Problem stellen). Um das import Bit._ kommt man aber nicht herum.

Man kann die Inhalte von EndianSkeleton.scala auch in die Datei Endian.scala kopieren und abgeben. Ist ja nur die Enumeration und evtl. die power-Funktion, sofern man diese überhaupt verwendet.


Mal ne andere Frage zu Currying:
Wenn man beispielsweise alle Elemente einer Liste mit einer bestimmten Zahl multiplizieren will, wie müsste die Funktion richtig lauten?

def mul : List[Int] => Int => List[Int] = { xs => for { x <- xs } yield a * x }
Eclipse unterringelt das a, wie schreibt man es richtig?


Du musst [m]a[/m] irgendwo deklarieren (oder wie man das hier nennen will/soll), also sagen, dass es auf etwas abgebildet werden soll:

def mul : List[Int] => Int => List[Int] = {
	  xs => a => for { x <- xs } yield a * x
}

Danke für die schnelle Antwort, so funktionierts.


Die umschließenden geschweiften Klammern braucht man eigentlich nicht.