Implicit Parameters
От: Аноним  
Дата: 02.10.09 16:43
Оценка:
Почитал немного про "Implicit Parameters" в Scala.
И не совсем понимаю что показано на сайте scala-lang.org в этом примере.
Можете объяснить?
scala
Re: Implicit Parameters
От: Аноним  
Дата: 02.10.09 16:59
Оценка:
Не могу понять — почему не работает такой код

abstract class SemiGroup[A] {
      def add(x: A, y: A): A
}

abstract class Monoid[A] extends SemiGroup[A] {
      def unit: A
}
object ImplicitTest 
{

    implicit object StringMonoid extends Monoid[String] {
            def add(x: String, y: String): String = x concat y
            def unit: String = "HELLO"
    }

    implicit object IntMonoid extends Monoid[int] {
            def add(x: Int, y: Int): Int = x + y
            def unit: Int = 0
    }

    object LongMonoid extends Monoid[Long] {
            def add(x: Long, y: Long): Long = x + y
            def unit: Long = 0L
    }

    def sum[A](xs: List[A])(implicit m: Monoid[A]): A = {
        if (xs.isEmpty) m.unit
        else m.add(xs.head, sum(xs.tail))
    }

    println(sum(List(1, 2, 3)))
    println(sum(List("a", "b", "c")))
    println(sum(List(1L, 2L, 3L)(LongMonoid())))
}
Re[2]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.10.09 17:04
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Не могу понять — почему не работает такой код


А>
А>    implicit object IntMonoid extends Monoid[int] {
А>            def add(x: Int, y: Int): Int = x + y
А>            def unit: Int = 0
А>    }

А>    object LongMonoid extends Monoid[Long] {
А>            def add(x: Long, y: Long): Long = x + y
А>            def unit: Long = 0L
А>    }
А>


Во-первых, отсутствует модификатор implicit у объекта LongMonoid.

А>
А>    println(sum(List(1L, 2L, 3L)(LongMonoid())))
А>


Во-вторых, лишние скобки после имени объекта LongMonoid.
Re: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 02.10.09 17:09
Оценка:
Здравствуйте, Аноним, Вы писали:

А>И не совсем понимаю что показано на сайте 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?
Я же потом его явно использую.
Re: Implicit Parameters
От: Аноним  
Дата: 04.10.09 10:26
Оценка:
И еще вопрос — почему не все примеры со http://www.scala-lang.org работают без допиливания?
Например вот этот — http://www.scala-lang.org/node/136
нужно переделать вот так, чобы он заработал
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 -.


Может кто-то объяснить по-русски и с примерами?
Re[4]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 04.10.09 11:10
Оценка:
Здравствуйте, Аноним, Вы писали:

N>>Во-первых, отсутствует модификатор implicit у объекта LongMonoid.


А>А если не объявлять LongMonoid как implicit?

А>Я же потом его явно использую.

Ну если явно, то можно не писать implicit.
Исходный пример-то был именно на демонстрацию использования implicit.
Re[2]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 04.10.09 11:12
Оценка:
Здравствуйте, Аноним, Вы писали:

А>И еще вопрос — почему не все примеры со http://www.scala-lang.org работают без допиливания?

А>Например вот этот — http://www.scala-lang.org/node/136
А>нужно переделать вот так, чобы он заработал

Видимо, ты из под интерпретатора (scala) его запускаешь?
Для компилятора (scalac) исходный текст должен подойти.
Re[2]: Implicit Parameters
От: Аноним  
Дата: 04.10.09 11:33
Оценка:
А>Сам пример понятно как работает.

Поспешил
Непонятно где и как сохраняется elem.
Посмотрел декомпилированный код — в нем есть такое
private final Object elem$1;


А как понять — где он сохраняется в scala-коде?
Re[2]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 04.10.09 11:51
Оценка: 18 (3)
Здравствуйте, Аноним, Вы писали:

А>Но что значит вот этот текст?

А>

А>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 различны).
Re[3]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 04.10.09 11:57
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А как понять — где он сохраняется в scala-коде?


А не нужно думать, где он сохраняется.
Это то же самое замыкание.
elem — это параметр всего объекта, задаваемый при его создании, и он просто in scope во всех его методах.
Re[3]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 04.10.09 12:29
Оценка:
Ещё надо добавить, что типы-параметры у методов не могут объявлять вариантность:
trait A {
  def Foo[+T] : T // Error
}


Однако, типы-параметров у типов-параметров высшего порядка у методов — могут:
trait A {
  def Foo[T[+X]] : T[String]
}
Re[3]: Implicit Parameters
От: Аноним  
Дата: 04.10.09 12:33
Оценка:
N>Видимо, ты из под интерпретатора (scala) его запускаешь?
N>Для компилятора (scalac) исходный текст должен подойти.

Из-под интерпретатора.
А почему такая разница?
Re[4]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 04.10.09 13:02
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Из-под интерпретатора.

А>А почему такая разница?

Так задумано. В интерпретаторе все декларации или выражения выполняются в порядке ввода.
Компилятор требует, чтобы top-level декларации были декларациями классов, трейтов или объектов (не должно быть top-level выражений или деклараций методов или значений), их порядок не важен, а выполнение начинается с метода Main или объекта, наследующегося от Application.
Re[4]: Implicit Parameters
От: Аноним  
Дата: 10.10.09 08:49
Оценка:
N>А не нужно думать, где он сохраняется.
N>Это то же самое замыкание.
N>elem — это параметр всего объекта, задаваемый при его создании, и он просто in scope во всех его методах.

И все равно я не понимаю — как выстраивается цепочка объектов в стеке.
Не могу понять — как работает pop.
Re[5]: Implicit Parameters
От: nikov США http://www.linkedin.com/in/nikov
Дата: 10.10.09 10:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>И все равно я не понимаю — как выстраивается цепочка объектов в стеке.

А>Не могу понять — как работает 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);
    }
}


Это оптимизация компилятора, что в первом случае нет такой вот строчки?
private final String str;
Re[8]: Implicit Parameters
От: avpavlov  
Дата: 12.10.09 16:20
Оценка:
А>Это оптимизация компилятора, что в первом случае нет такой вот строчки?
А>
private final String str;


Ну а какие могут быть сомнения? Если в первом случае строка не нужна, а во втором нужна, то из этого разница и проистекает
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.