Skip to content

Commit c7c9964

Browse files
authored
Merge pull request #856 from EliasAAradsson/w11
Fix #647, together with some other related suggestions
2 parents f0127f2 + f305031 commit c7c9964

File tree

1 file changed

+128
-13
lines changed

1 file changed

+128
-13
lines changed

compendium/modules/w11-context-exercise.tex

Lines changed: 128 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@
545545
\SubtaskSolved
546546
\begin{REPL}
547547
scala> given stringComparator: CanCompare[String] with
548-
override def compare(a: String, b: String): Int = (a.compareTo(b))
548+
override def compare(a: String, b: String): Int = a.compareTo(b)
549549
\end{REPL}
550550

551551
\QUESTEND
@@ -613,17 +613,79 @@
613613

614614
\Subtask \emph{Importera implicita ordningsoperatorer från en \code{Ordering}.} Om man gör import på ett \code{Ordering}-objekt får man tillgång till implicita konverteringar som gör att jämförelseoperatorerna fungerar. Testa nedan variant av \code{isSorted} på olika sekvenstyper och verifiera att \code{<=}, \code{>}, etc., nu fungerar enligt nedan.
615615
\begin{CodeSmall}
616-
def isSorted[T](xs: Seq[T])(given ord: Ordering[T]): Boolean = {
617-
import ord._
616+
def isSorted[T](xs: Seq[T])(using ord: Ordering[T]): Boolean =
617+
import ord.*
618618
xs.zip(xs.tail).forall(x => x._1 <= x._2)
619-
}
620619
\end{CodeSmall}
621620

622621

623622
\SOLUTION
624623

624+
\TaskSolved \what
625+
626+
\SubtaskSolved
627+
Exempel på tester:
628+
\begin{REPLnonum}
629+
scala> isSorted(Vector(1,2,3))
630+
val res0: Boolean = true
631+
632+
scala> isSorted(Vector(1,2,4,3))
633+
val res1: Boolean = false
634+
635+
scala> isSorted(List(1,2,3))
636+
val res2: Boolean = true
637+
638+
scala> isSorted(List(1,2,4,3))
639+
val res3: Boolean = false
640+
\end{REPLnonum}
641+
642+
\SubtaskSolved
643+
\begin{REPLnonum}
644+
scala> def isSorted[T](xs: Seq[T]): Boolean = xs == xs.sorted
645+
-- [E172] Type Error: --------------------------------------------------------------------------
646+
1 |def isSorted[T](xs: Seq[T]): Boolean = xs == xs.sorted
647+
| ^
648+
| No implicit Ordering defined for T..
649+
| I found:
650+
|
651+
| scala.math.Ordering.ordered[T](/* missing */summon[scala.math.Ordering.AsComparable[T]])
652+
|
653+
| But no implicit values were found that match type scala.math.Ordering.AsComparable[T].
654+
|
655+
| The following import might make progress towards fixing the problem:
656+
|
657+
| import scala.math.Ordered.orderingToOrdered
658+
|
659+
1 error found
660+
\end{REPLnonum}
661+
Felmeddelandet innebär att kompilatorn inte kan härleda en ordning för den generiska typen \code{T}.
662+
663+
\SubtaskSolved
664+
\begin{REPLnonum}
665+
scala> isSorted(persons)
666+
-- [E172] Type Error: ------------------------------------------------------------------------------------
667+
1 |isSorted(persons)
668+
| ^
669+
| No implicit Ordering defined for Person..
670+
| I found:
671+
|
672+
| scala.math.Ordering.ordered[Person](/* missing */summon[scala.math.Ordering.AsComparable[Person]])
673+
|
674+
| But no implicit values were found that match type scala.math.Ordering.AsComparable[Person].
675+
|
676+
| The following import might make progress towards fixing the problem:
677+
|
678+
| import scala.math.Ordered.orderingToOrdered
679+
|
680+
1 error found
681+
\end{REPLnonum}
682+
Felmeddelandet ges därför att kompilatorn inte känner till någon ordning för klassen \code{Person}.
683+
684+
\SubtaskSolved
685+
-
625686

626-
\TaskSolved \what --- \TODO
687+
\SubtaskSolved
688+
-
627689

628690
\QUESTEND
629691

@@ -685,16 +747,57 @@
685747

686748
\SOLUTION
687749

688-
689750
\TaskSolved \what
690751

691-
\SubtaskSolved \TODO
752+
\SubtaskSolved
753+
\begin{REPLnonum}
754+
scala> xs.sorted
755+
-- [E172] Type Error: ---------------------------------------------------------------------------------------------------------------
756+
1 |xs.sorted
757+
| ^
758+
| No implicit Ordering defined for Team..
759+
| I found:
760+
|
761+
| scala.math.Ordering.comparatorToOrdering[Team](/* missing */summon[java.util.Comparator[Team]])
762+
|
763+
| But no implicit values were found that match type java.util.Comparator[Team].
764+
|
765+
| One of the following imports might make progress towards fixing the problem:
766+
|
767+
| import scala.math.Ordering.comparatorToOrdering
768+
| import scala.math.Ordering.ordered
769+
|
770+
1 error found
771+
\end{REPLnonum}
772+
Felmeddelandet ges därför att kompilatorn inte känner till någon ordning för klassen \code{Team}.
773+
774+
Efter tilldelningen \code{given Ordering[Team] = Ordering.by(t => t.rank)} existerar en given ordning för \code{Team} i den nuvarande kontexten.
775+
Därför fungerar nu det efterföljande anropet \code{xs.sorted} som tänkt.
692776

693-
\SubtaskSolved \TODO
777+
\SubtaskSolved
778+
-
694779

695-
\SubtaskSolved \TODO
780+
\SubtaskSolved
781+
-
696782

697-
\SubtaskSolved \TODO
783+
\SubtaskSolved
784+
\begin{REPLnonum}
785+
scala> Team("fnatic",1499) < Team("gurka", 2)
786+
-- [E008] Not Found Error: ------------------------------------------------------------
787+
1 |Team("fnatic",1499) < Team("gurka", 2)
788+
|^^^^^^^^^^^^^^^^^^^^^
789+
|value < is not a member of Team, but could be made available as an extension method.
790+
|
791+
|One of the following imports might fix the problem:
792+
|
793+
| import scala.math.Ordered.orderingToOrdered
794+
| import scala.math.Ordering.Implicits.infixOrderingOps
795+
|
796+
1 error found
797+
\end{REPLnonum}
798+
Precis som kompilatorn säger är \code{<} inte en metod definierad för \code{Team}.
799+
Däremot, efter \code{import Team.highestRankFirst.given} importeras även de implicita konverteringar som finns definierade för \code{highestRankFirst: Ordering[Team]} (eftersom det är ett objekt av typen \code{Ordering}).
800+
Därmed fungerar \code{<}. Se uppgift 7e för mer bakgrund.
698801

699802

700803
\QUESTEND
@@ -720,7 +823,7 @@
720823
case class Team(name: String, rank: Int) extends Ordered[Team]:
721824
override def compare(that: Team): Int = ???
722825
\end{Code}
723-
\emph{Tips:} Du kan anropa metoden \code{compare} på alla grundtyper, t.ex. \code{Int}, eftersom de implementerar gränssnittet \code{Oredered}. Genom att negera uttrycket blir ordningen den omvända.
826+
\emph{Tips:} Du kan anropa metoden \code{compare} på alla grundtyper, t.ex. \code{Int}, eftersom de implementerar gränssnittet \code{Ordered}. Genom att negera uttrycket blir ordningen den omvända.
724827

725828
\begin{REPLnonum}
726829
scala> -(2.compare(1))
@@ -741,7 +844,7 @@
741844
\SubtaskSolved
742845

743846
\begin{Code}
744-
case class Team(name: String, rank: Int) extends Ordered[Team]:
847+
case class Team(name: String, rank: Int) extends Ordered[Team]:
745848
override def compare(that: Team): Int = -rank.compare(that.rank)
746849
\end{Code}
747850

@@ -752,7 +855,19 @@
752855
val res1: Boolean = true
753856
\end{REPLnonum}
754857

755-
\SubtaskSolved Ad hoc polymorfism är mer flexibel. \TODO{mer diskussion om likheter och skillnader här...}
858+
\SubtaskSolved
859+
Subtypspolymorfism, alltså användande av arv och gränssnitt \Eng{interface} bygger på att varje subtyp måste implementera vissa medlemmar.
860+
Kompilatorn kan därmed garantera att \emph{något} kommer att ske vid anrop med en subtyp.
861+
Den kan däremot inte garantera \emph{vad} som kommer att ske. Detta avgörs på plats under körtid,
862+
så kallad dynamisk bindning.
863+
864+
Ad hoc polymorfism å andra sidan bygger på att den anropade funktionen är definierad
865+
så att den beter sig olika för olika typer. Till detta används någon form av typklasser.
866+
Det är alltså typen som ges vid anrop som avgör vad som sker,
867+
inte vilket beteende som är definierat i den subtyp som typen ''råkar'' ha.
868+
Redan då koden kompileras kan alltså kompilatorn avgöra vad som kommer att ske baserat på
869+
typen, alltså statisk bindning. Detta innebär att det blir lättare att resonera om
870+
hur programmet beter sig.
756871

757872
\QUESTEND
758873

0 commit comments

Comments
 (0)