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

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?

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ę.

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))
  }
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).

0

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)
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 :)

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

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.

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