2011-02-05 14 views
8

Necesito usar un tipo (cualquier tipo) como marcador en un parámetro implícito como tipo, para distinguirlo de otro implícito. Es extraño, pero esta puede ser otra pregunta.¿Cuál es el tipo más barato de Scala?

Desde que puedo usar cualquier tipo, yo estaba pensando en utilizar el más barato, en términos de huella de la memoria y el tiempoinicialización. Puede que no afecte demasiado el rendimiento en este caso, pero la pregunta es interesante: ¿cuál es el tipo más barato de Scala?

En Java, la respuesta es obviamente java.lang.Object. Pero Scala tiene algunos tipos "interesantes": tipos Any, AnyVal y tipos de fondo con posibles optimizaciones a su alrededor. No se puede crear una instancia del tipo Nothing, por lo que se excluye de esta comparación.

+3

Interesante, hubiera dicho que el tipo más barato en Java era un int simple. – Yahel

+0

No estoy seguro de qué tan "barato" es esto, pero Nada podría ser útil: 'def x (_: Nothing) =(); x (null.asInstanceOf [Nothing]) 'Just * do not * try * use that Nothing :-) –

+0

También sería interesante ver una pregunta sobre el problema" raíz ". –

Respuesta

3

Si elige Any o AnyVal, entonces cualquier primitivo que pase estará en caja, por lo que probablemente esté fuera.

AnyRef es una buena opción de hecho.

Si no hay ninguna parametrización de tipos en curso, las "primitivas" también son buenas opciones - Boolean o Int, por ejemplo.

Y también está Null, que es una opción muy interesante porque no asigna nada en absoluto, y es literal, por lo que seguramente será rápido. Sin saber qué es exactamente lo que estás haciendo con él, no puedo decir si esa es una opción válida.

Otra opción interesante es java.lang.Integer (usando el método estático valueOf), ya que garantiza la igualdad de referencia para valores pequeños (debe verificar los documentos para ver cuál es el rango preciso), lo que significa que no hay asignación.

+0

'java.lang.Integer' no garantiza la igualdad de referencia para valores pequeños. La expresión 'new Integer (5)' siempre crea una nueva instancia separada. Usted puede estar pensando en el autoboxing. 'Integer i = 5' siempre asignará el mismo objeto a' i'. –

+0

No estaba pensando en 'nuevo'. Lo he aclarado ahora, gracias. –

1

Como Scala se ejecuta sobre Java, supongo que la misma respuesta funcionaría también en el mundo de Scala. un objeto Scala de tipo Any es solo un objeto Java de algún tipo.

En Java, creo que un tipo primitivo como int, short o byte sería más barato que Object, pero esos tipos podrían estar empaquetados/enmarcados en Scala. (No es 100% seguro de que aunque.)

actualización

Si por alguna razón tiene que ser un objeto y no un tipo primitivo, cuerdas podría ser la mejor, ya que las cadenas están internados en la máquina virtual . Por lo tanto, generalmente solo habrá una instancia del objeto en toda la aplicación.

+0

"El compilador de Scala utiliza matrices de Java, tipos primitivos y aritmética nativa donde sea posible en el código compilado" (del libro "Programación en Scala") - parece que no están ajustados (al menos durante el tiempo de ejecución). – Maxym

+0

no se analiza el código para evitar el ajuste será simplemente perezoso, codificación diferida; 'intern' de cadenas es propenso a fugas y no mejora el rendimiento – bestsss

4

no estoy seguro de que consiga lo que quiere decir con "tipo más barato" ... En Java tipo numérico más barata en términos de memoria puede ser byte, pero a partir de rendimiento POV Java está optimizado para trabajar con int. De hecho, muchos (o la mayoría) de los idiomas están optimizados para funcionar con int (incluso los motores DB). Scala es el lenguaje JVM, así que diría que es mejor usar int.

ACTUALIZACIÓN: si la pregunta es sobre el tipo de datos "marcado/no marcado" adecuado, yo usaría la primitiva booleana.

si escribe booleano en un programa de Scala , del tipo que realmente va a obtener es scala.Boolean. O si escribe flotador , obtendrá scala.Float. Cuando compila su código Scala a bytecodes de Java , sin embargo, Scala compilará estos tipos en los tipos primitivos de Java donde sea posible para obtener los beneficios de rendimiento de los tipos primitivos de Java.

Nada es un hubiere, que es una especie de objeto en Java, y cualquier objeto necesita más memoria que cualquier tipo primitivo

Y por cierto, utilizando booleano como marcador es natural, se mejora la legibilidad del código (y de ahí el apoyo, la comprensión de los demás). Incluso si hay algo más, más optimizado no haría una optimización prematura y elegiría booleano.

+0

byte no toma" un "byte en la memoria, pero debe estar alineado, por lo que 4/8. La excepción es byte [] – bestsss

+0

@bestsss: de acuerdo, me equivoqué al hablar de tamaño de 1byte (esto es de acuerdo con javadoc que habla de 8 bits); por otro lado, cuánto realmente toma depende de la implementación de JVM (como sé que hay una sobrecarga, también referencia a http://stackoverflow.com/questions/229886/size-of-a-byte-in-memory-java) Algunas JVM pueden "tratar" el tipo de byte como un número de 32 bits ... Cambié mi respuesta de acuerdo con su observación. gracias – Maxym

13

Depende de su problema exacto, pero la construcción más barata en Scala, o en cualquier idioma, tiene que ser una que no exista en absoluto ...(al menos, no en tiempo de ejecución)

Permítanme introducir Phantom Types, lo que permite al compilador hacer lo correcto de forma estática, pero borrado a la nada antes de que lleguen a la JVM.

De forma similar, puede distinguir fácilmente dos objetos de tipos diferentes sin necesidad de campos de marcadores. Este es un buen candidato para case object s, y funciona muy bien junto con la coincidencia de patrones.

0

Scala ajusta los tipos primitivos, cuando ejecuta las llamadas al método del contenedor, que el tipo primitivo no implementa. Entonces, es decir. 1024 * 512 no está envuelto pero en 1024.toInt * 512 el 1024 se está envolviendo.

Cuestiones relacionadas