Использование C Unions с Scala - PullRequest
       1

Использование C Unions с Scala

2 голосов
/ 30 октября 2010

Можно ли эмулировать структуру объединения C, используя Scala?В этом случае переменные перезаписывают друг друга.

Ниже приведен список характеристик, которые могут быть возможны:

  1. С одной и той же переменной можно использовать разные типы.
  2. Переменные используют одну и ту же ячейку памяти.
  3. Любой способ узнать, какие типы хранятся.

Я думаю, что вторая характеристика наиболее трудна для подражания.

Спасибо

Ответы [ 4 ]

6 голосов
/ 30 октября 2010

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

В случае экскурсии по классу вы можете увидеть, что Var, Fun a App могут храниться в чем-то, способном удерживать термин. Затем сопоставление с образцом можно использовать для извлечения того, что было сохранено, и действовать в зависимости от *1000* определенного типа (Var, Fun, App и т. Д.), С которым сопоставляются. Весь этот процесс аналогичен использованию дополнительного флага «type» и конструкции / else-конструкции, часто используемой только с объединениями C, опять же, с типобезопасностью (и гораздо более удобной в большинстве случаев: -)

(На самом деле, смотреть на эти ссылки довольно обидно, так как на самом деле это не царапает поверхность: - /)

Практический пример / объяснение с использованием Scala: Что такое алгебраический тип данных? Он также хорошо показывает, как он связан / обрабатывается на «меньших» языках.

3 голосов
/ 31 октября 2010

Я думаю, что ваша лучшая ставка - Either:

var x: Either[Int, Double] = _
x = Left(5)
x = Right(1.5)
x match {
    case Left(i) => println("Int "+i)
    case Right(d) => println("Double "+d)
}

То, что это делает не , позволяет вам "читать" один тип, как если бы он был другим. Он использует одну ссылку больше, чем размер одних типов, но не добавляет размер, взятый обоими типами вместе. И это позволяет вам знать, какой тип хранится.

1 голос
/ 09 сентября 2011

Как насчет написания параметрического класса типа Union с неявными преобразователями из A => B и B => A

class Union [A, B] {
  getA = ...
  getB = ...
}

, который работал бы, если бы каждый B мог быть сохранен в A, например. Иначе, промежуточный, 3-й тип может быть использован для хранения и восстановления значений типов A и B, назовем его C.

class Union [A, B, C] (c: C) (implicit 
  a2c: (A => C), 
  b2c: (B => C),  
  c2a: (C => A), 
  c2b: (C => B)) {
  def getA : A = c2a (c) 
  def getB : B = c2b (c)
}

As и B сохраняются как Cs, и есть метод, для A и один для B, чтобы снова получить значение из C.

Чтобы использовать его, мы используем несколько демо-методов:

def l2i (l: List[Char]): Int = 
  (0 /: l.reverse.take (4).reverse) ((a, b) => (a * 255 + b))
def i2l (i: Int): List[Char] = 
  if (i < 255) List (i.toChar) else (i % 255).toChar :: toChars (i / 255)
def l2s (l: List[Char]): String = 
  l.mkString ("")
def s2l (s: String): List[Char] = 
  s.toCharArray.toList

и затем мы создаем настоящий союз (String / Int / List):

class UnionSIL (l: List[Char]) 
  extends Union [String, Int, List[Char]] 
    (l: List[Char]) (s2l, i2l, l2s, l2i) {
  def this (i: Int) = this (i2l (i))
  def this (s: String) = this (s2l (s))
}

и протестируйте его:

val ui = new UnionSIL (44) 
val us = new UnionSIL ("foobar") 
List(ui, us).foreach (u => println (u.getA + ": " + u.getB)) 

,: 44
foobar: 1846929924
1 голос
/ 30 октября 2010

Одним из наиболее распространенных применений объединения является то, что вы можете видеть (например) длинную строку и 3 дюйма, представленные массивом байтов, обычно для файлового или сетевого ввода-вывода.

Чтобы сделать эквивалент в Java и, следовательно, в Scala, вам следует обратиться к библиотеке NIO: http://en.wikipedia.org/wiki/New_I/O Это обеспечивает все функции, необходимые для чтения / записи расширенных значений в сокеты, файлы и т. Д.

Вместо этого вы можете использовать более старый подход Reader / Writer / Stream (http://tutorials.jenkov.com/java-io/index.html), если вы чувствуете себя более комфортно с этим API, и вам больше повезет, если вы найдете там онлайн-уроки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...