Я нашел обсуждение в ответе 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.
Проблема в том, что GenericTraversableTemplate используется дважды: один раз для изменяемых коллекций (где его параметр типа должен быть инвариантным), и один раз для неизменяемых коллекций (где ковариация неизменна).
Проверка типов GenericTraversableTemplate предполагает либо ковариантность, либо инвариантность для параметра типа A. Однако, когда мы наследуем его в мутабельном признаке, мы должны выбрать инвариантность. И наоборот, мы хотели бы получить ковариацию в неизменяемом подклассе.
Поскольку мы не можем абстрагироваться от аннотации variance (пока ;-)) в GenericTraversableTemplate, чтобы мы могли инстанцировать его на любой из вариантов в зависимости от подкласса, нам приходится прибегать к кастингу (@uncheckVariance - это, по сути, kind-cast). Для дальнейшего чтения рекомендую мою диссертацию (извините ;-)) или наш недавний bitrot paper
В своей диссертации я описываю исчисление 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, экспериментальном функциональном языке с обеими этими возможностями. Наконец, мы докажем состоятельность основной системы типов системы типов ядра по отношению к лямбда-исчисления по вызову.
Я нашел другой случай, когда используется @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();
()
}
}
}
}