Здравствуйте, Аноним, Вы писали:
А>И не совсем понимаю что показано на сайте scala-lang.org в этом примере. А>Можете объяснить?
Если у функции есть implicit аргумент, то при вызове функции его можно опустить и вместо него будет подставлен implicit объект подходящего типа из текущего scope.
Читать Scala Language Specification, Chapter 7 'Implicit Parameters and Views'.
Re[3]: Implicit Parameters
От:
Аноним
Дата:
02.10.09 17:12
Оценка:
N>Во-первых, отсутствует модификатор implicit у объекта LongMonoid.
А если не объявлять LongMonoid как implicit?
Я же потом его явно использую.
trait Similar {
def isSimilar(x: Any): Boolean
}
case class MyInt(x: Int) extends Similar {
def isSimilar(m: Any): Boolean =
m.isInstanceOf[MyInt] &&
m.asInstanceOf[MyInt].x == x
}
object UpperBoundTest extends Application {
def findSimilar[T <: Similar](e: T, xs: List[T]): Boolean =
if (xs.isEmpty) false
else if (e.isSimilar(xs.head)) true
else findSimilar[T](e, xs.tail)
}
val test = UpperBoundTest
val list: List[MyInt] = List(MyInt(1), MyInt(2), MyInt(3))
println(test.findSimilar[MyInt](MyInt(4), list))
println(test.findSimilar[MyInt](MyInt(2), list))
Re: Implicit Parameters
От:
Аноним
Дата:
04.10.09 11:01
Оценка:
Никогда не сталкивался по серьезному с дженериками.
Поэтому вот этот пример вызывает некоторые затруднения — http://www.scala-lang.org/node/129
Сам пример понятно как работает.
Но что значит вот этот текст?
The annotation +T declares type T to be used only in covariant positions. Similarly, -T would declare T to be used only in contravariant positions. For covariant type parameters we get a covariant subtype relationship regarding this type parameter. For our example this means Stack[T] is a subtype of Stack[S] if T is a subtype of S. The opposite holds for type parameters that are tagged with a -.
Здравствуйте, Аноним, Вы писали:
N>>Во-первых, отсутствует модификатор implicit у объекта LongMonoid.
А>А если не объявлять LongMonoid как implicit? А>Я же потом его явно использую.
Ну если явно, то можно не писать implicit.
Исходный пример-то был именно на демонстрацию использования implicit.
Здравствуйте, Аноним, Вы писали:
А>Но что значит вот этот текст? А>
А>The annotation +T declares type T to be used only in covariant positions. Similarly, -T would declare T to be used only in contravariant positions. For covariant type parameters we get a covariant subtype relationship regarding this type parameter. For our example this means Stack[T] is a subtype of Stack[S] if T is a subtype of S. The opposite holds for type parameters that are tagged with a -.
А>Может кто-то объяснить по-русски и с примерами?
Ковариантный — значит "меняющийся в ту же сторону". Контравариантный — "меняющийся в обратную сторону".
Классические дженерики C# (версии ниже 4.0) и Java не поддерживают ко-/контравариантности. Это значит, что, например, не будет неявного преобразования от типа List<String> к List<Object> несмотря на то, что String является подтипом типа Object. Ясно, что в общем случае ковариантность не типобезопасна: иначе мы могли бы привести List<String> к List<Object> и затем положить туда Integer, после чего могли бы попытаться извлечь этот элемент из исходной переменной типа List<String>, которая ссылается на тот же объект — ясно, что это закончилось бы тем, что в худшем случае в переменной типа String оказался бы Integer, а в лучшем мы получили бы ClassCastException в неожиданном месте (там, где нет явного приведения типов). Поэтому самое простое решение — запретить коваринатность вообще. Scala принимает более изящное решение: разделять позиции в коде, на которых может встречаться тип-параметр (например: декларация параметра метода, декларация возвращаемого значения, декларация локальной переменной и т.д.) на ковариантные, контравариантные и инвариантные в зависимости от того, окажется ли это типобезопасным при разрешенных приведениях типов.
И если некоторый тип-параметр встречается только в ковариантных позициях, то он может быть объявлен ковариантным (+T). Другими словами: если он объявлен ковариантным, то он обязан встречаться только в ковариантных позициях. Аналогичная ситуация в C# 4.0, за исключением, что ко-/контравариантные типы-параметры быть только у интерфейсов и делегатов, но не у любых классов.
Соответственно, если параметр T у класса C — коавариантный, то тип C[B] будет считаться подтипом типа C[A] (и будет неявно приводим к типу С[A]), если тип В является подтипом типа A.
И наоборот, если параметр T у класса C — контравариантный, то тип C[A] будет считаться подтипом типа C[B] (и будет неявно приводим к типу С[B]), если тип В является подтипом типа A.
Последняя ситуация имеет смысл, например, для такого класса (умеющего сравнивать объекты типа T):
class Comparer[-T] {
def Compare(x : T, x : T) : Boolean = { /* ... */ }
}
Объект типа Comparer[Object] умеет сравнивать любые объекты, значит он умеет сравнивать и строки. Ясно, что его можно безопасно неявно привести к типу Comparer[String]. Для компилятора здесь существенно то, что тип T появляется только в качестве типа параметров метода — эти позиции контравариантны.
Для инвариантных типов-параметров, между C[A] и C[B] нет неявных преобразований ни в какую сторону (если типы A и B различны).
Здравствуйте, Аноним, Вы писали:
А>А как понять — где он сохраняется в scala-коде?
А не нужно думать, где он сохраняется.
Это то же самое замыкание.
elem — это параметр всего объекта, задаваемый при его создании, и он просто in scope во всех его методах.
Здравствуйте, Аноним, Вы писали:
А>Из-под интерпретатора. А>А почему такая разница?
Так задумано. В интерпретаторе все декларации или выражения выполняются в порядке ввода.
Компилятор требует, чтобы top-level декларации были декларациями классов, трейтов или объектов (не должно быть top-level выражений или деклараций методов или значений), их порядок не важен, а выполнение начинается с метода Main или объекта, наследующегося от Application.
Re[4]: Implicit Parameters
От:
Аноним
Дата:
10.10.09 08:49
Оценка:
N>А не нужно думать, где он сохраняется. N>Это то же самое замыкание. N>elem — это параметр всего объекта, задаваемый при его создании, и он просто in scope во всех его методах.
И все равно я не понимаю — как выстраивается цепочка объектов в стеке.
Не могу понять — как работает pop.
Здравствуйте, Аноним, Вы писали:
А>И все равно я не понимаю — как выстраивается цепочка объектов в стеке. А>Не могу понять — как работает pop.
А замыкания лежат в куче, а не на стеке.
Если нужно понять именно внутренний механизм, то надо смотреть jad-ом в class-файлах. Там будет создаваться специальное поле.
Re[6]: Implicit Parameters
От:
Аноним
Дата:
11.10.09 10:12
Оценка:
Хорошо, а если я не хочу чтобы объект, которыя я передаю в метод push жил так долго?
Пусть это будет Stack, который хранит длины строк а не сами строки.
В метод push передается строка, а сохраняется и выводится методом pop — длина строки.
Как быть?
Re[7]: Implicit Parameters
От:
Аноним
Дата:
12.10.09 14:01
Оценка:
Я не совсем понимаю почему вот такой код
class Foo(str: String) {
val len = str.length
def getLen = len
}
компилится в
public class Foo
implements ScalaObject
{
private final int len;
public Foo(String str)
{
len = str.length();
}
public int getLen()
{
return len();
}
public int len()
{
return len;
}
public int $tag()
throws RemoteException
{
return scala.ScalaObject.class.$tag(this);
}
}
А вот такой код
class Foo(str: String) {
val len = str.length
def getLen = len
def getStr = str}
компилится в
public class Foo
implements ScalaObject
{
private final int len;
private final String str;
public Foo(String str)
{
this.str = str;
super();
len = str.length();
}
public String getStr()
{
return str;
}
public int getLen()
{
return len();
}
public int len()
{
return len;
}
public int $tag()
throws RemoteException
{
return scala.ScalaObject.class.$tag(this);
}
}
Это оптимизация компилятора, что в первом случае нет такой вот строчки?