Scala core Flashcards

1
Q

Q.29. Explain sealed classes in Scala.

A

Когда мы помечаем trait или класс как sealed, мы должны объявить все подтипы этого класса или трейта в этом же файле. Таким образом, мы можем убедиться, что инициализации подтипа родительского типа не будут раскиданны по всему проекту - мы их все видеть в одном файле.

*****

When we mark a trait or a class as sealed, we must declare all subtypes in the same file. This way, we can make sure that we know all subtypes.
-----------
scala\> sealed abstract class Transport
defined class Transport
scala\> case class Scooter() extends Transport
defined class Scooter
scala\> case class Car() extends Transport
defined class Car
scala\> def show(vehicle:Transport):String=vehicle match{
| case a: Scooter=\>"Two wheels"
| case b: Car=\>"Four wheels"
| }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q
  1. What is Unit?
A

Unit - это тип, который представляет отсутствие значения, как Java void. Это подтип scala.AnyVal. Существует только одно значение типа Unit, представленное (), и оно не представлено ни одним объектом , а служит определенным маркером для обозначения участков кода которые являются процедурами а не выражениями ( expression ) результат действия, которых будет side effect.

http://https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

*****

Unit is a type which represents the absence of value, just like Java void. It is a subtype of scala.AnyVal. There is only one value of type Unit, represented by (), and it is not represented by any object in the underlying runtime system.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Q.13. What is a Guard in a for-comprehension?

A

Когда in-for comprehension мы хотим фильтровать элементы, мы можем использовать условие if. Мы можем назвать это условие if «охранником». Когда охранник имеет значение True, Scala добавляет этот элемент в новую коллекцию. В противном случае он не выполняет никаких действий. Давайте возьмем пример.

val nums = список (0,1,2,3,4,5,6,7,8,9,10)
для {num <-nums если num% 3 == 0
} yield num

res0: List [Int] = List (0, 3, 6, 9)
Этот код объявляет список и добавляет в другой список только те элементы, которые делятся на 3.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
  1. What is a case class?
A

case class является синтаксическим сахаром для класса, объекты которого является неизменным и разложимым посредством patten maching (потому что у них есть методы apply и unapply). Быть разложимым означает, что можно извлекать параметры его конструкторов при сопоставлении с образцом ( при приминение к нему конструкции pattern matching ) .

Case Классы содержат сопутствующий объект, который содержит метод apply, который создается по умолчанию без написания дополнительного кода. Этот факт делает возможным создание экземпляра класса case без ключевого слова new. Объекты Case classes также по дефолту поставляются с некоторыми вспомогательными методами, такими как метод .copy, который облегчает создание слегка измененной копии с оригинала, метод HashCode , equal , toString, все возможноные конструкторы и тд

Наконец, case классы сравниваются по значение полей объекта вместо сравнения по ссылке, т. Е. Они идут с методом, который сравнивает два объекта кейс класса по их значениям / полям вместо сравнения только ссылок ( если все поля 2х объектов кейс классов(одинакого типа ) совпадают то оператор == вернет true . В java для активации такого функционала надо было explicitly ( явно ) override ( переопределять ) метод equal специальным образом, т.е. писать много boilerplate code ( стандартного кода )

Классы Case особенно полезны для использования в качестве DTO - data transfer object pattern. Так же case classes активно используются в akka actor И при работе с json.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

*****

A case class is syntactic sugar for a class that is immutable and decomposable through pattern matching (because they have an apply and unapply methods). Being decomposable means it is possible to extract its constructors parameters in the pattern matching.

Case classes contain a companion object which holds the apply method. This fact makes possible to instantiate a case class without the new keyword. They also come with some helper methods like the .copy method, that eases the creation of a slightly changed copy from the original.

Finally, case classes are compared by structural equality instead of being compared by reference, i.e., they come with a method which compares two case classes by their values/fields, instead of comparing just the references.

Case classes are specially useful to be used as DTOs.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
  1. What is function currying?
A

def add (a: Int) (b: Int) = a + b

val add2 = add (2) (_)

scala> add2 (3)
res0: Int = 5
—————
Карри полезно во многих различных контекстах, но чаще всего, когда вам приходится иметь дело с функциями высшего порядка.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

*****

Currying is a technique of making a function that takes multiple arguments into a series of functions that take a part of the arguments.
---------------
def add(a: Int)(b: Int) = a + b

val add2 = add(2)(_)

scala> add2(3)
res0: Int = 5
—————
Currying is useful in many different contexts, but most often when you have to deal with Higher order functions.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
  1. What is the difference between a call-by-value and call-by-name parameter?
A

The difference between a call-by-value and a call-by-name parameter, is that the former is computed before calling the function, and the later is evaluated when accessed.
As it may be seen, the call-by-name example makes the computation only when needed, and every time it is called, while the call-by-value only computes once, but it computes before invoking the function (callByName).

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

https://prnt.sc/oet1d5

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q
  1. What is the difference between a var, a val and def and lazy val ?? and method vs function ??
A

Методы это выражения связанные с объектом класса. Таким образом, мы можем вызвать его в рамках экземпляра класса, но не можем вызвать его напрямую без объекта в отличие от функции. Мы можем определить метод только в ассоциации с классом или с трейдом.
Функция, однако, не ассоциируется с классом или трейтом. Мы можем получить к ней доступ без объекта ( экземпляра класса ) , и мы можем определить ее в пакете Scala без какой либо ассоциации с трейтом или с классом.

Var - это переменная. Это изменчивая ссылка на значение. Поскольку она изменчива, ее значение может изменяться в течение времени жизни программы. Имейте в виду, что тип переменной не может изменяться в Scala. Вы можете сказать, что var ведет себя подобно переменным в Java.

Val - это константа. Это неизменная ссылка, означающая, что значенние этой константы никогда не меняется. После назначения val всегда будет иметь одинаковое значение. Это похоже на константы в других языках. В java это похоже на инициализацию переменной с ключ словом final
https://stackoverflow.com/questions/25417450/how-is-val-in-scala-different-from-const-in-java

Def создает метод (а метод отличается от функции см выше ). Оценивается по вызову.

Бонус: что такое lazy val ? Это почти как val, но его значение вычисляется только при необходимости ( как def ) и только один раз ( как val ) в отличие от def. Это особенно полезно, чтобы избежать тяжелых вычислений .
https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def
??? Там, где тщательная оценка выполняется во время компиляции, ленивая оценка выполняется во время выполнения. \ ???

****

Methods associated with an object. So we can call it on an instance of a class, but cannot call it directly without an object. We can define it in a class or in a trait.
A function, however, doesn’t associate with a class or with a trait. We can access it without an object, and we define it in a Scala package.

A var is a variable. It’s a mutable reference to a value. Since it’s mutable, its value may change through the program lifetime. Keep in mind that the variable type cannot change in Scala. You may say that a var behaves similarly to Java variables.

A val is a value. It’s an immutable reference, meaning that its value never changes. Once assigned it will always keep the same value. It’s similar to constants in another languages.

A def creates a method (and a method is different from a function - thanks to AP for his comment). It is evaluated on call.

Bonus: what’s a lazy val? It’s almost like a val, but its value is only computed when needed. It’s specially useful to avoid heavy computations (using short-circuit for instance).

??? Where eager evaluation is at compile-time, lazy evaluation is at run-time.\???

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Q.30. Can you reassign parameters for case classes?

A

Нет, мы не можем, поскольку case классы помогают моделировать неизменяемые данные. Его параметры неявно public val . Мы могли бы использовать var здесь, но Скала не рекомендует делать это. Если уж больно надо мы можем использовать метод .copy создать новый кейс объект с изменнеными полями от искомого кейс объекта.

*****

No, we cannot, since case classes help model immutable data. Its parameters are implicitly public val. We could use vars here, but Scala discourages doing so.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q
  1. What is the difference between the following terms and types in Scala: Nil, Null, None, Nothing?
A

None - это пустое представление монады Option - решение проблемы null pointer exception

Null - это trait Scala, где null - единственный его экземпляр. The null value пришгло из Java и является экземпляром любого объекта, то есть это подтип всех ссылочных ( AnyRef ) типов ( см иерархию типов в скале ), но не типов значений ( AnyVal ) . Он существует для того, чтобы ссылочные типы могли иметь нулевое значение, а типы значений (например, Int или Long) не могут обращаться в null ( но это не точно -перепроверить ??? ) .

Nothing является другим трейтом Скалы. Это подтип любого другого типа ( см иерархию ) , и у него нет подтипов. Он существует благодаря сложной системе типов, которую имеет Scala. У него ноль экземпляров. Это тип возврата метода, который никогда не возвращается нормально, например, метод, который всегда выдает исключение ( эксепшен ) . Причина, по которой Scala имеет тип bottom, связана с его способностью выражать ( чо бля ??? ) дисперсию в параметрах типа. Nothing удобно использовать в левой части монады Either - для обозначения что левая часть выкидывает какие либо исключения или ошибки.

Наконец, Nil представляет пустой List, т.е. List c нулевым размером. Nil имеет тип List [Nothing].

Все эти типы могут создать чувство пустоты, верно? Вот небольшая помощь в понимании пустоты в Scala.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

****

The None is the empty representation of the Option monad (see answer #11).

Null is a Scala trait, where null is its only instance. The null value comes from Java and it’s an instance of any object, i.e., it is a subtype of all reference types, but not of value types. It exists so that reference types can be assigned null and value types (like Int or Long) can’t.

Nothing is another Scala trait. It’s a subtype of any other type, and it has no subtypes. It exists due to the complex type system Scala has. It has zero instances. It’s the return type of a method that never returns normally, for instance, a method that always throws an exception. The reason Scala has a bottom type is tied to its ability to express variance in type parameters..

Finally, Nil represents an empty List of anything of size zero. Nil is of type List[Nothing].

All these types can create a sense of emptiness right? Here’s a little help understanding emptiness in Scala.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q
  1. What are High Order Functions?
A

Функции высокого порядка - это функции, которые могут получать или возвращать другие функции. Типичными примерами в Scala являются функции .filter, .map, .flatMap, которые получают другие функции в качестве аргументов.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

*****

High order functions are functions that can receive or return other functions. Common examples in Scala are the .filter, .map, .flatMap functions, which receive other functions as arguments.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Q.21. It is impossible to mark constructor parameters as private in Scala?

A

Нет, это не так. Мы можем объявить параметр(поле) класса как закрытый, если объявим его без ключевого слова var или val. Тогда мы можем получить доступ к значениям его полей(параметров) только внутри класса.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q
  1. How does yield work? What operations is a for comprehension syntactic sugar for?
A

scala> for (i <- 1 to 5) yield i * 2
res0: scala.collection.immutable.IndexedSeq [Int] = Vector (2, 4, 6, 8, 10)

А для понимания - это альтернативный синтаксис для составления нескольких операций над монадами.

Для понимания можно заменить операции for compehension => map / flatMap и filter ( withFilter).
for {
х <- с1
у <- с2
z <- c3, если z> 0
} yield {…}
c1.flatMap (x => c2.flatMap (y => c3.withFilter (z => z> 0) .map (z => {…})))

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

***

scala> for (i <- 1 to 5) yield i * 2
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)

A for comprehension is a alternative syntax for the composition of several operations on monads.

A for comprehension can be replaced by foreach operations (if no yield keyword is being used), or by map/flatMap and filter (actually, while confirming my words I found out about the withFilter method).
for {
x <- c1
y <- c2
z <- c3 if z > 0
} yield {…}
c1.flatMap(x => c2.flatMap(y => c3.withFilter(z => z > 0).map(z => {…})))

****

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Q.26. What is a closure in Scala?

A

объект Demo {
def main (args: Array [String]) {
println (“multiplier (1) значение =” + multiplier (1))
println (“multiplier (2) значение =” + multiplier (2))
}
var factor = 3
val multiplier = (i: Int) => i * factor
}
————-
multiplier - will be a closure

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q
  1. What is Tail recursion?
A

В «нормальных» рекурсивных методах, метод вызывает сам себя внутри самого себя в определенном этапе хода выполнение кода. Этот метод используется, например, в наивной реализации числа Фибоначчи. Проблема с этим подходом состоит в том, что на каждом рекурсивном шаге в memory стеке необходимо сохранять другую порцию информации ( промежуточное вычисление предыдущих шагов этой рекурсии ). Если шагов рекурсии очень много ( больше 50ти ), как правило это приводит к runtime exception stackoverflow.

Хвостовая рекурсия решает эту проблему. Вы можете попросить компилятор принудительно использовать хвостовую рекурсию в методе с помощью аннотации @tailrec. Хвостовые рекурсивные методы реализованны разработчиком таким образом что все вычисления выполняются перед рекурсивным вызовом, а последним оператором является рекурсивный вызов. Если пометить метод аннотацией @tailrec и написать код по другому ( не правильно ), то будет ошибка компеляции. Затем компиляторы могут воспользоваться этим свойством, чтобы избежать ошибок переполнения стека, поскольку хвостовые рекурсивные вызовы можно оптимизировать, не вставляя промежуточные шаги рекурсивного вычисления в memory стек.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

*****

In “normal” recursive methods, a method calls itself at some point. This technique is used in the naive implementation of the Fibonacci number, for instance. The problem with this approach is that at each recursive step, another chunk of information needs to be saved on the stack. In some cases, an huge number of recursive steps can occur, leading to stack overflow errors.

Tail recursion solves this problem. In tail recursive methods, all the computations are done before the recursive call, and the last statement is the recursive call. Compilers can then take advantage of this property to avoid stack overflow errors, since tail recursive calls can be optimized by not inserting info into the stack.

You can ask the compiler to enforce tail recursion in a method with @tailrec

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

heirarchy of classes in scala ? Q.6. What is the equivalent type for java.lang.Object here in Scala?

A

http://prntscr.com/oet0ey

https://prnt.sc/ogap3p​

Where there’s java.lang.Object in Java, we have AnyRef in Scala. This is in context of a Java Runtime Environment (JRE).

https://data-flair.training/blogs/scala-interview-questions-with-answers/

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q
  1. What is the difference between an object and a class?

what is a companion object ?

A

Объект является единичным (sigleton pattern ) экземпляром класса и его не надо инстанциировать ( создавать при помощи ключ слова new или метода apply).

Если объект имеет то же имя, что и класс, этот объект называется сопутствующим объектом ( companion object ). В таком объекте удобно создавать метод фабрику apply или хранить имлициды для трейта или класса ( но это не точно ??? погуглить http://https://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html )

Так же стоит заметить, что Сопутствующий объект ( companion object) имеет доступ к методам приватной видимости класса, а класс также имеет доступ к закрытым методам объекта. Проводя сравнение с Java, сопутствующие объекты содержат «статические методы» класса.

Обратите внимание, что объект-компаньон должен быть определен в том же исходном файле, что и класс.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

****

An object is a singleton instance of a class. It does not need to be instantiated by the developer.

If an object has the same name that a class, the object is called a companion object (check Q7 for more details).
If an object has the same name that a class, the object is called a companion object. A companion object has access to methods of private visibility of the class, and the class also has access to private methods of the object. Doing the comparison with Java, companion objects hold the “static methods” of a class.

Note that the companion object has to be defined in the same source file that the class.

17
Q
  1. What is the difference between unapply and apply, when would you use them?
A

unapply - это метод, который должен быть реализован объектом, чтобы у него появился экстрактор ( extractor ). Экстрактор используются в сопоставлении с образцом для доступа к параметрам объекта ( полям ). Другими словами Unapply метод с функционалом противоположный функционалу apply. А экстрактор это противоположность конструктору. Unapply метод удобен при декомпозиции например объектов кейс классов в match pattern и дальнейшей работе с полями этого объекта ( сравнение, фильтрация, мэппинг )

Метод apply - это специальный метод, который позволяет записывать someObject(params) вместо someObject.apply (params). Такое использование часто встречается в case классах, которые содержат компоньюн объект с методом apply, который позволяет с удобным синтаксисом создавать новый объект без ключевого слова new.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

****

unapply is a method that needs to be implemented by an object in order for it to be an extractor. Extractors are used in pattern matching to access an object constructor parameters. It’s the opposite of a constructor.

The apply method is a special method that allows you to write someObject(params) instead of someObject.apply(params). This usage is common in case classes, which contain a companion object with the apply method that allows the nice syntax to instantiate a new object without the new keyword.

18
Q

Q.22. We have seen that traits let us implement multiple inheritance. Can traits extend other traits, though? Can you Subtype using a trait?

A

Да, trait может наследоваться от нескольких trait - тов. Мы можем расширить trait, используя ключевое слово extends. И если мы заставим класс расширить его, мы можем использовать ключевое слово override для реализации его абстрактных членов.
Можете ли подтип, использовать trait ?
Абсолютно. Мы можем использовать подтип trait - та.

19
Q
  1. What is the difference between a Java future and a Scala future?
A

Реализация Scala фактически асинхронна, т.е. ход выполнение потока основной программы не блокируется при создание нового потока для выполнения вычислений во Future, в то время как в Java вы не можете получить значение из Future без блокировки потока основной программы.

Scala предоставляет API для управления Future в виде монады ( т.е. есть как и традиционные для монады функции ( map , flatMap и тд ), методы и свойства, так и медоты и фунции уникальные для Future) или ( дальше до точки потом распишу ) путем добавления callback для завершения. Если вы не решите использовать метод из Future API - Await, вы не заблокируете свою основную программу, используя Scala Futures.

******

the Scala implementation is in fact asynchronous without blocking, while in Java you can’t get the future value without blocking.

Scala provides an API to manipulate the future as a monad or by attaching callbacks for completion. Unless you decide to use the Await, you won’t block your program using Scala futures.

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

20
Q
  1. Option vs Try vs Either
A

1) Монада Option - это решение Scala для проблемы null pointer exception из Java. В то время как в Java ( до java 8 ) отсутствие значения моделируется через null значение, в Scala его использование не приветствуется, как альтернатива используется монад Option.

val person: Person = getPersonByIdOnDatabaseUnsafe (id = 4) // возвращает ноль, если нет человека для предоставленного идентификатора
println (s “Возраст этого человека - $ {person.age}”) // если ноль, то будет выдано исключение

val personOpt: Option [Person] = getPersonByIdOnDatabaseSafe (id = 4) // возвращает пустую опцию, если нет человека для предоставленного идентификатора

personOpt match {
 case Some (p) =\> println (s "Возраст этого человека - $ {p.age}")
 case None =\> println ("Нет человека с таким идентификатором")
}
-------------------

2) Try - это монадный подход к блоку Java try / catch. Он может оборачивать собой runtime исключения.

def personAge (id: Int): либо [String, Int] = {
val personOpt: Option [Person] = DB.getPersonById (id)

 personOpt match {
 case None =\> Left (s "Не удалось получить человека с идентификатором: $ id")
 case Some (person) =\> Right (person.age)
 }
}

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

*****

1) The Option monad is the Scala solution to the null problem from Java. While in Java the absence of a value is modeled through the null value, in Scala its usage is discouraged, in flavor of the Option.

val person: Person = getPersonByIdOnDatabaseUnsafe(id = 4) // returns null if no person for provided id
println(s”This person age is ${person.age}”) // if null it will throw an exception

val personOpt: Option[Person] = getPersonByIdOnDatabaseSafe(id = 4) // returns an empty Option if no person for provided id

personOpt match {
case Some(p) =\> println(s"This person age is ${p.age}")
case None =\> println("There is no person with that id")
}
-------------------

def personAge(id: Int): Either[String, Int] = {
val personOpt: Option[Person] = DB.getPersonById(id)

personOpt match {
case None =\> Left(s"Could not get person with id: $id")
case Some(person) =\> Right(person.age)
}
}
21
Q

Q.20. How is a function different from a procedure?

A

можно привести пример с лупом в java and scala and if in scala and java

*****

A function is a computation unit and has no side effects. A procedure is a computation unit too, but has side effects.
However, both help with computation; this is how they’re similar.

22
Q

Q.6. What are the advantages of Scala?

A

Среди различных других преимуществ языка, вот несколько:

Это очень масштабируемый
Это очень проверяемый
Это очень ремонтопригодно и продуктивно
Это облегчает параллельное программирование
Это и объектно-ориентированный и функциональный
У него нет стандартного кода
Одиночные объекты - более чистое решение, чем статические
В массивах Scala используются обычные генерики
Scala имеет собственные кортежи и лаконичный код
Подробнее о его преимуществах читайте в разделе Преимущества Scala.

***

Among various other benefits of the language, here are a few:

It is highly scalable
It is highly testable
It is highly maintainable and productive
It facilitates concurrent programming
It is both object-oriented and functional
It has no boilerplate code
Singleton objects are a cleaner solution than static
Scala arrays use regular generics
Scala has native tuples and concise code
For a detailed piece on its benefits, read up on Advantages of Scala.

23
Q
  1. What is the difference between a trait and an abstract class?
A

Первое отличие состоит в том, что класс ( в том числе и абстрактный ) может расширять только один другой класс ( в том числе и абстрактный ) , в отличие от тейтов где один трейт может наследоваться от неограниченного количество трейтов.

Хотя трейт поддерживают только type parametes {Type parameters are enclosed in square brackets, while value parameters are enclosed in parentheses} и методы, абстрактные классы могут иметь на ряду с этим еще и конструкторы.

Кроме того, абстрактные классы совместимы с Java, в то время как трейты совместимы только с Java, если они не содержат никакой имплементаций ( полей или методов ) .

https://www.geeksforgeeks.org/difference-between-traits-and-abstract-classes-in-scala/

https://pedrorijo.com/blog/scala-interview-questions/#1-what-is-the-difference-between-a-var-a-val-and-def

*****

The first difference is that a class can only extend one other class, but an unlimited number of traits.

While traits only support type parameters, abstract classes can have constructor parameters.

Also, abstract classes are interoperable with Java, while traits are only interoperable with Java if they do not contain any implementation.