[SCALA] Sprawdź, czy liczby z listy są mniejsze od parametru

Odpowiedz Nowy wątek
2019-10-17 00:44
1

Napisz funkcję, która na wejściu przyjmuje dwa parametry: listę liczb całkowitych oraz liczbę.
Na wyjściu zwraca wartość logiczną.
Funkcja zwraca wartość "prawda" jeśli wszystkie liczby z listy są mniejsze niż liczba podana
w drugim parametrze. W przeciwnym przypadku funkcja zwraca wartość "fałsz".

Mój kod:

def less [A](list:List[A], number:Int):Boolean =
  if (list == Nil) false
  else ((List.head < number) && less[A](list:List.tail, number:Int))

less(List(1, 2, 3, 4), 5)
less(List(6,1,2,3),6)

Otrzymuję komunikat o błędzie:

On line 3: error: value head is not a member of object List

else (List.head < number) && less[A](list:List.tail, number:Int) //2

^

On line 3: error: type tail is not a member of object List

Co powinienem poprawić, żeby było poprawnie?

Pozostało 580 znaków

2019-10-17 06:47
0

Nie napisałem w Scali linijki nigdy, ale nie jest przypadkiem tak, że raz wykorzystujesz listę z parametru (list) a innym razem, jak np. w List.head odwołujesz się do typu/konstruktora typu? Wydaje mi się, że tam powinno być z małej litery.
Poza tym w Scali chyba jest pattern matching, a sama funkcja zwróci zły wynik, bo wywołanie less(List([], n) czy jak to tam się w Scali pustą listę zapisuje powinno zwracać prawdę.

Pozostało 580 znaków

2019-10-18 00:47
0

To moj drugi kontakt ze Scala (pierwszym byl HelloWorld), wiec moge pisac herezje, ale nie powinno byc tak?

  • Nie wiem czemu mialoby sluzyc [A] ktore pisales ?
  • jak w porownaniu do Nil dasz false, to tail zwraca w pewnym momencie pusta liste i zawsze dostaniesz false.
  def less (list:List[Int], number:Int) : Boolean = {
    if (list == Nil) true
    else ((list.head < number) && less(list.tail,number))
  }

Pozostało 580 znaków

2019-10-18 06:30
2

W Scali ta sama nazwa może oznaczać zarówno wartość (np object List) jak i typ (np class List). W kodzie, który przytoczyłeś:

def less [A](list:List[A], number:Int):Boolean =
  if (list == Nil) false
  else ((List.head < number) && less[A](list:List.tail, number:Int))

używasz dwukrotnie List jako wartości (czyli odnosisz się do object List) - w List.head i List.tail. Tymczasem głowy i ogona powinieneś szukać w instancji klasy List którą dostałeś jako parametr o nazwie list.

Kolega @WhiteLightning podał raczej dobre rozwiązanie (nie testowałem).


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 2x, ostatnio: Wibowit, 2019-10-18 06:30

Pozostało 580 znaków

2019-10-18 07:56

A czy ta rekurencja jest wymagana w treści zadania?
Bo jeśli nie to można napisać:

def less(list: List[Int], number: Int): Boolean = list.filter(_  >= number).isEmpty

Ogólnie jak pisał Pierre-Yves Saumont w Java. Programowanie funkcyjne rekurencja jest takim goto programowania funkcyjnego.
I jeśli da się uniknąć rekurencji to lepiej unikać używając np. funkcji bibliotecznych

Wersja z rekurencją:

def less(list: List[Int], number: Int): Boolean = list == Nil || list.head < number && less(list.tail, number)

edytowany 2x, ostatnio: Kamil Żabiński, 2019-10-18 08:00
Chyba, że optymalizujesz rekurencję, w Scali, na przykład, mamy TCO; wtedy nie ma czego unikać. - lion137 2019-10-18 08:09
O czywiście o ile się nie pomylisz lub dasz adnotację @tailrec (wtedy jak się pomylisz to będzie błąd kompilatora). Ale nawet wtedy wersja z map wydaje mi się czytelniejsza niż wersja z rekurencją - Kamil Żabiński 2019-10-18 08:13

Pozostało 580 znaków

2019-10-18 08:03
0

@Wibowit: @Kamil Żabiński -> a co daje w tym kodzie to [A] ? Bo k awalek ktory napisalem dziala bez tego, ale moze to jakis wazny kawalek Scali ktory warto rozumiec :)

Pozostało 580 znaków

2019-10-18 08:06
0
WhiteLightning napisał(a):

@Wibowit: @Kamil Żabiński -> a co daje w tym kodzie to [A] ? Bo k awalek ktory napisalem dziala bez tego, ale moze to jakis wazny kawalek Scali ktory warto rozumiec :)

Błąd kompilacj :D
[A] to Generyk. W Javie by było <A>. A tutaj potrzebujemy listy liczb wię cowinno być List[A] lub coś podobnego


edytowany 1x, ostatnio: Kamil Żabiński, 2019-10-18 08:07
@Kamil Żabiński: to teraz nastepne pytanie, czym jest Number i czemu za zadne skarby nie moge na niego Inta zrzutowac ? Btw. chcialem sie upewnic, w Scali nie ma typow prostych? - WhiteLightning 2019-10-18 08:13
Nie rozumiem, u mnie zmienna number jest typu Int. W Scali typy proste dziedziczą po AnyVal - Kamil Żabiński 2019-10-18 08:15
@Kamil Żabiński: no np. chcialbym zamienic Int na Number. def less (list:List[Number], number:Number) : Boolean = { ... Ma to wogole sens ? - WhiteLightning 2019-10-18 08:19
Ładuje Ci się Number ze Scali który jest trochę bezsensowny. Powinieneś użuć java.lang.Number - Kamil Żabiński 2019-10-18 08:45
Scala nie ma typu Number (za to jest dostępne wspomniane java.lang.Number). Jest typeclassa o nazwie Numeric ale na typeclassy się nie rzutuje. Int ze Scali czasami wymazuje się do Javowego int (gdy jest użyty bezpośrednio lub jako element tablicy niegenerycznej), a czasami do java.lang.Integer (przy generykach). Żeby zmienić scala.Int na java.lang.Integer możesz użyć metody Int.box. - Wibowit 2019-10-18 12:31

Pozostało 580 znaków

2019-10-18 08:07
1
Kamil Żabiński napisał(a):

Ogólnie jak pisał Pierre-Yves Saumont w Java. Programowanie funkcyjne rekurencja jest takim goto programowania funkcyjnego.

Śmiem się nie zgodzić :] Rekurencja jest bardziej odpowiednikiem imperatywnych pętli. Rekurencyjne wywołanie to continue, powrót z funkcji rekurencyjnej to break, zamiast mutowania zmiennych mamy obliczanie nowego zestawu argumentów. Największą różnicą jest to, że w pętlach mamy miejsce na warunek stopu (np while (condition) { doSomething() }), a w rekurencji trzeba strzelić sobie ifa i zadecydować czy kontynuujemy rekurencyjnie czy może już zwracamy wartość.

Odpowiednikiem goto jest "call with current continuation". https://wiki.haskell.org/Continuation :

At its heart, call/cc is something like the goto instruction (or rather, like a label for a goto instruction); but a Grand High Exalted goto instruction... The point about call/cc is that it is not a static (lexical) goto instruction but a dynamic one (David Madore's A page about call/cc)

.

@Wibowit: @Kamil Żabiński -> a co daje w tym kodzie to [A] ? Bo k awalek ktory napisalem dziala bez tego, ale moze to jakis wazny kawalek Scali ktory warto rozumiec :)

Jak już @Kamil Żabiński napisał, [A] w Scali to to samo co <A> w Javie. Żeby to się skompilowało z generycznym typem to ten generyczny typ albo musi dziedziczyć po np Comparable[A] ([A <: Comparable[A]]) albo musi mieć w zasięgu implicit np Ordering[A] ([A: Ordering]). Nic takiego nie widać w sygnaturze, więc kod się nie skompiluje bo będzie brakować metod do porównywania.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 4x, ostatnio: Wibowit, 2019-10-18 08:38
Rekurencja oczywiście odpowiada pętli, ale z tego co zrozumiałem Pierre-Yves Saumon to chodziło mu o to że rekurencji nie należy nadużywać. Jeśli są ładne funkcje biblioteczne fold, map, filter i tak dalej to nie ma sensu samodzielnie pisać tego za pomocą rekurencj - Kamil Żabiński 2019-10-18 08:10
Z tym się zgodzę, tylko czemu porównanie jest do goto? Goto dzisiaj już prawie nikt nie używa. - Wibowit 2019-10-18 08:14

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0