|
545 | 545 | \SubtaskSolved
|
546 | 546 | \begin{REPL}
|
547 | 547 | 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) |
549 | 549 | \end{REPL}
|
550 | 550 |
|
551 | 551 | \QUESTEND
|
|
613 | 613 |
|
614 | 614 | \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.
|
615 | 615 | \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.* |
618 | 618 | xs.zip(xs.tail).forall(x => x._1 <= x._2)
|
619 |
| -} |
620 | 619 | \end{CodeSmall}
|
621 | 620 |
|
622 | 621 |
|
623 | 622 | \SOLUTION
|
624 | 623 |
|
| 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 | +- |
625 | 686 |
|
626 |
| -\TaskSolved \what --- \TODO |
| 687 | +\SubtaskSolved |
| 688 | +- |
627 | 689 |
|
628 | 690 | \QUESTEND
|
629 | 691 |
|
|
685 | 747 |
|
686 | 748 | \SOLUTION
|
687 | 749 |
|
688 |
| - |
689 | 750 | \TaskSolved \what
|
690 | 751 |
|
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. |
692 | 776 |
|
693 |
| -\SubtaskSolved \TODO |
| 777 | +\SubtaskSolved |
| 778 | +- |
694 | 779 |
|
695 |
| -\SubtaskSolved \TODO |
| 780 | +\SubtaskSolved |
| 781 | +- |
696 | 782 |
|
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. |
698 | 801 |
|
699 | 802 |
|
700 | 803 | \QUESTEND
|
|
720 | 823 | case class Team(name: String, rank: Int) extends Ordered[Team]:
|
721 | 824 | override def compare(that: Team): Int = ???
|
722 | 825 | \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. |
724 | 827 |
|
725 | 828 | \begin{REPLnonum}
|
726 | 829 | scala> -(2.compare(1))
|
|
741 | 844 | \SubtaskSolved
|
742 | 845 |
|
743 | 846 | \begin{Code}
|
744 |
| -case class Team(name: String, rank: Int) extends Ordered[Team]: |
| 847 | +case class Team(name: String, rank: Int) extends Ordered[Team]: |
745 | 848 | override def compare(that: Team): Int = -rank.compare(that.rank)
|
746 | 849 | \end{Code}
|
747 | 850 |
|
|
752 | 855 | val res1: Boolean = true
|
753 | 856 | \end{REPLnonum}
|
754 | 857 |
|
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. |
756 | 871 |
|
757 | 872 | \QUESTEND
|
758 | 873 |
|
|
0 commit comments