Когда @uncheckedVariance требуется в Scala и почему он используется в GenericTraversableTemplate?

Я нашел обсуждение в ответе tobias.pal очень интересным: https://stackoverflow.com/a/32689974/1184842

for (( FD=3 ; FD < 100 ; FD++ )) ; do exec {FD}> file.$FD ; echo $FD >&${FD}; done

Это не сработает, так как exec {FD}> file.${FD} будет одним и тем же дескриптором над всеми значениями $ FD, верно? (Denio Mariz)

Я решил это, используя массив, как указано Дрю Чапином:

#!/bin/bash
# global variables for temp file handling
declare -a TEMPORARY_FILES_WRITE;
declare -a TEMPORARY_FILES_READ;

function createTempFile() {
    local usecase="$1"
    local id="$2"
    local tmpfile=$(mktemp)  # Create a temporal file in the default temporal folder of the system

    # Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
    exec {TEMPORARY_FILES_WRITE[$id]}>"$tmpfile"
    exec {TEMPORARY_FILES_READ[$id]}<"$tmpfile"
    rm "$tmpfile"  # Delete the file, but file descriptors keep available for this script
}    

for (( FD=3 ; FD < 100 ; FD++ )) ; do 
    TEMP_FILE_COUNTER=$((TEMP_FILE_COUNTER + 1))
    createTempFile "Iteration $FD" $FD ;
    echo $FD >&${TEMPORARY_FILES_WRITE[$FD] ;
done

example=$(cat <&${TEMPORARY_FILES_READ[50]})
echo $example

Это приведет к выводу 50.

38
задан retronym 16 March 2010 в 22:14
поделиться

3 ответа

Проблема в том, что GenericTraversableTemplate используется дважды: один раз для изменяемых коллекций (где его параметр типа должен быть инвариантным), и один раз для неизменяемых коллекций (где ковариация неизменна).

Проверка типов GenericTraversableTemplate предполагает либо ковариантность, либо инвариантность для параметра типа A. Однако, когда мы наследуем его в мутабельном признаке, мы должны выбрать инвариантность. И наоборот, мы хотели бы получить ковариацию в неизменяемом подклассе.

Поскольку мы не можем абстрагироваться от аннотации variance (пока ;-)) в GenericTraversableTemplate, чтобы мы могли инстанцировать его на любой из вариантов в зависимости от подкласса, нам приходится прибегать к кастингу (@uncheckVariance - это, по сути, kind-cast). Для дальнейшего чтения рекомендую мою диссертацию (извините ;-)) или наш недавний bitrot paper

28
ответ дан 27 November 2019 в 03:52
поделиться

В своей диссертации я описываю исчисление Scalina, которое имеет аннотации границ и дисперсии как часть языка вида (ранняя версия также доступна в виде доклада на семинаре). Актуальность этого обсуждения заключается в следующем шаге, который я хочу сделать в развитии этого исчисления: построить еще один слой поверх этого, чтобы можно было абстрагироваться от аннотаций границ (легко) и дисперсии (заставляет меня ломать голову). На самом деле, вы не просто добавите один дополнительный слой, а скорее обобщите ваши конструкции полиморфизма, чтобы они работали на всех уровнях, и превратите ваши "атрибуты" (границы, аннотации дисперсии, необходимые неявные аргументы, ...) в обычные типы со специальными видами, которые все подлежат абстракции.

Идея "атрибуты - это типы" хорошо объясняется Эдско де Врисом в контексте типов уникальности.

Uniqueness Typing Simplified, Edsko de Vries, Rinus Plasmeijer, and David Abrahamson. In Olaf Chitil, Zoltán Horváth and Viktória Zsók (Eds.): IFL 2007, LNCS 5083, pp. 201-218, 2008.

Аннотация: Мы представляем систему уникальности типа которая является более простой, чем система уникальности Clean и системы, предложенной нами ранее. Новая новая система типов проста для реализовать и добавить в существующие компиляторы, и может быть легко расширена продвинутыми функциями, такими как типы более высокого ранговые типы и импредикативность. Мы описываем нашу реализацию в Morrow, экспериментальном функциональном языке с обеими этими возможностями. Наконец, мы докажем состоятельность основной системы типов системы типов ядра по отношению к лямбда-исчисления по вызову.

8
ответ дан 27 November 2019 в 03:52
поделиться

Я нашел другой случай, когда используется @uncheckedVariance - синтетический метод, который возвращает значение по умолчанию для параметра абстрактного типа:

M:\>scala -Xprint:typer -e "class C { def p[T >: Null](t: T = null) = t }"
[[syntax trees at end of typer]]// Scala source: (virtual file)
package <empty> {
  final object Main extends java.lang.Object with ScalaObject {
    def this(): object Main = {
      Main.super.this();
      ()
    };
    def main(argv: Array[String]): Unit = {
      val args: Array[String] = argv;
      {
        final class $anon extends scala.AnyRef {
          def this(): anonymous class $anon = {
            $anon.super.this();
            ()
          };
          class C extends java.lang.Object with ScalaObject {
            <synthetic> def p$default$1[T >: Null <: Any]: Null @scala.annotation.unchecked.uncheckedVariance = null;
            def this(): this.C = {
              C.super.this();
              ()
            };
            def p[T >: Null <: Any](t: T = null): T = t
          }
        };
        {
          new $anon();
          ()
        }
      }
    }
  }
5
ответ дан 27 November 2019 в 03:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: