2009-09-29 10 views
16

Me preguntaba si hay algún idioma que permita tuplas con nombre. Es decir: un objeto con múltiples variables de diferente tipo y nombre configurable.Idiomas que permiten tuplas con nombre

ej .:

public NamedTuple<double:Speed, int:Distance> CalculateStuff(int arg1, int arg2) 

var result = CalculateStuffTuple(1,2); 

Console.WriteLine("Speed is: " + result.Speed.ToString()) 
Console.WriteLine("Distance is: " + result.Distance.ToString()) 

que podía concebir cómo una dinámica podría apoyar esta característica. Los lenguajes estáticos en los que normalmente me meto (como C#) pueden hacer un diccionario, pero no es seguro a menos que todos los elementos sean del mismo tipo. O puede usar un tipo Tuple, pero eso significa que tiene nombres fijos de los miembros (Var1, Var2, etc.).

También podría escribir una pequeña clase personalizada, pero esa es la situación que me gustaría evitar.

Me imagino que un lenguaje de procesamiento de macro podría escribir algo así para usted en un lenguaje estático, pero no conozco ese lenguaje.

Esto viene de mi respuesta en this question about return types.

+0

La razón por la que me gustaría evitar una costumbre clase/estructura es que no me gusta escribir! Nada más que eso. – ligos

+0

Esta línea no debería incluir Tuple. var result = CalculateStuffTuple (1,2); –

Respuesta

18

En C#, tiene tipos anónimos; Estos son similares pero tienen sus propias limitaciones:

var result = new { Speed = 12.4, Distance = 8, Caption = "car 1" }; 

Sin embargo, es difícil de consumir estos como una persona que llama, a menos que utilice "proyectada por ejemplo" (frágil), reflexión, o dynamic. De los tres, el último es el más apetitoso.

dynamic result = GetSomething(); 
Console.WriteLine(result.Speed); 
Console.WriteLine(result.Distance); 

En la mayoría de los casos, sería una mejor idea sólo para usar una clase regular - pero este método tiene algunos usos prácticos; por ejemplo, mira cómo se utilizan en ASP.NET MVC para pasar información de configuración de manera simple y conveniente (que de otro modo requeriría un diccionario). Un poco como jQuery le permite pasar opciones como propiedades en un objeto.

+0

Esto parece ser el más cercano a lo que estaba pidiendo (al menos en C#). – ligos

-1

No estoy seguro de lo que necesitaría para esto: una tupla es simplemente una estructura que contiene diferentes tipos de datos. Si realmente desea propiedades con nombre, tendrá que crear un tipo personalizado o crear un tipo anónimo sobre la marcha.

No conozco ningún lenguaje estáticamente tipeado que pueda soportar esto tampoco C# ciertamente no lo hace.

3

¿Quieres decir algo así como Python's collections.namedtuple? Bueno, Python (las versiones actuales, 2.6 y 3.1) los admite ;-). Pero en serio, no sé de un lenguaje estáticamente estátizado que los tenga incorporados.

2

¿Qué pasa con el uso de estructuras o clases en C#?

public class SpeedDistance{ 
    public double Speed; 
    public int Distance; 
} 
+2

Bueno, el campo público es una mala idea, por supuesto ... pero 'doble velocidad pública {get; set;}' haría ;-p –

+1

Me gusta que mis tuplas sean inmutables. Y eso requiere, en su lugar, variables de solo lectura y un constructor, que comienza a alargarse demasiado. – ligos

+1

campos públicos están bien, si y solo si eso es todo lo que contiene la clase. Pero las tuplas también pueden tener muchas otras propiedades agradables, que ayudan al pasar a otras bibliotecas. Si se escriben desde cero cada vez, entonces no interoperan. –

3

no estoy seguro si esto es exactamente lo que está buscando, pero en Haskell, puede tener un registro con los nombres y tipos específicos:

data Movement = Movement { speed :: Double, distance :: Int } deriving (Show) 

main = do 
    print $ Movement 3.14 100 
    print Movement {distance = 5, speed = 2.1} 
    print Movement {speed = 9, distance = -4} 

de salida:

 
Movement {speed = 3.14, distance = 100} 
Movement {speed = 2.1, distance = 5} 
Movement {speed = 9.0, distance = -4} 

Pero técnicamente no es una tupla . Haskell tiene tienen tuplas, pero hasta el momento no tienen nombre.

Esto realmente no está lejos de una simple estructura en cualquier lenguaje derivado de C, tampoco. Tal vez me perdí algo en la pregunta.

6

Eiffel permite tuplas con nombre.

5

Sé de;

  • Python (dinámico, mecanografía fuerte)
  • Eiffel (, mecanografía cadena estática)

dos se pueden usar en .net

Y, probablemente, Lisp, se puede hacer cualquier cosa con Lisp .

39

Una vieja pregunta, pero necesito una mejor solución, creo.

Puede obtener parámetros con nombre aprovechando el tipo de Tuplo, pero envolviéndolo en un tipo con nombre personalizado que ajuste .Item1, .Item2, etc. en nombres de propiedades significativas.

Yo también odio el hecho de que Tuples tenga parámetros sin nombre que hacen que el código sea ilegible, pero no puede ignorar el tiempo que le ahorra tener que implementar IComparable, IStructuralEquatable, etc. para que pueda usar sus estructuras como un diccionario clave, por ejemplo.

Creo que este es un compromiso muy agradable:

public class Velocity : Tuple<double, double, string> 
{ 
    public Velocity(double Speed, double Direction, string Units) : base(Speed, Direction, Units) { } 
    public double Speed { get { return this.Item1; } } 
    public double Direction { get { return this.Item2; } } 
    public string Units { get { return this.Item3; } } 
} 

Ahora, en lugar de esta basura:

Tuple<double, double, string> myVelocity = new Tuple<double, double, string>(10, 2.34, "cm/s"); 
System.Diagnostics.Debug.Print("Speed: " + myVelocity.Item1); 
System.Diagnostics.Debug.Print("Direction: " + myVelocity.Item2); 
System.Diagnostics.Debug.Print("Units: " + myVelocity.Item3); 

se llega a hacer esto:

Velocity myVelocity2 = new Velocity(10, 2.34, "cm/s"); 
System.Diagnostics.Debug.Print("Speed: " + myVelocity2.Speed); 
System.Diagnostics.Debug.Print("Direction: " + myVelocity2.Direction); 
System.Diagnostics.Debug.Print("Units: " + myVelocity2.Units); 

Y todavía beneficio de todas las maravillosas características de tupla que le permiten usarlo como una clave compleja en diccionarios, etc.

El único inconveniente es que si solo planificó usar esta tupla dentro del alcance de un único método, debe declarar un tipo dentro del alcance de la clase que contiene ese método. Para la mayoría de las aplicaciones, no creo que sea un problema.

+0

Eso no es tan malo. Excepto que tengo que tener un montón de pequeñas clases envolviendo 'Tuple <>'. Pero es mejor que tener que volver a implementar IEquatable, IComparable, etc. – ligos

+1

No puedo creer que nunca haya pensado en esto. Súper útil. –

+0

Simplemente la solución que estaba buscando. Excelente :) –

0

Gracias Alain. Así es como usé tu consejo.

cargador Imagen dinámica de un carrusel

<div id="owl" class="owl-carousel owl-theme"> 
    @foreach (var image in Model.Sketches) 
    { 
     <div class="item" > 
      <a href="@image.SketchHref" id="[email protected]" target="_blank" > 
       <img id="[email protected]" class="lazyOwl" style="border:1px solid #d1c7c7;outline : 0;max-height:350px;max-width:400px;" 
        title="click for full size" alt="@image.SketchName" data-src="@image.SketchHref" /></a> 
        <div style="text-align:left;height:auto;vertical-align:bottom;padding:2px;font-size:1em;color:#DF3A01;">Sketch @image.SketchNumber of @Model.Sketches.Count()</div> 
     </div> 
    } 
    </div> 

Y por el nombre de la imagen C#

public List<Sketches> Sketches 
    { 
     get 
     { 
      List<Sketches> hrefs = new List<Sketches>(); 

/* coincide con una carpeta de la ubicación ejemplo: 1234101005_001.Gif sería igual a "C: \ imágenes \ 1234 \ 10 \ 1005_BLD \" */

  var sketchFolder = Regex.Replace(some_image, @"(\d{4})(\d{2})(\d{4})", @"c:\Sketches\$1\$2\$3\_BLD"); 
      var sketchHref = Regex.Replace(some_image, @"(\d{4})(\d{2})(\d{4})", @"/sketches/$1/$2/$3/_BLD"); 
      Int16 i = 0; 

      if (System.IO.Directory.Exists(sketchFolder)) 
      { 
       List<string> gifs = GetGifs(sketchFolder); 

       gifs.ForEach(delegate(String gif) 
       { 
        string s = sketchHref + "/" + gif; 
        string f = sketchFolder + "/" + gif; 

        if (System.IO.File.Exists(f)) 
        { 
         Sketches sketch = new Sketches(s, (++i).ToString(), gif); 
         hrefs.Add(sketch); 
        } 
        else // gif does not exist 
        { 
         Sketches sketch = new Sketches("placeholder.png", (++i).ToString(), gif); 
         hrefs.Add(sketch); 
        } 
       }); 
      } 
      else // folder does not exist 
      { 
       Sketches sketch = new Sketches("placeholder.png", (++i).ToString(), ""); 
       hrefs.Add(sketch); 
      } 
      return hrefs; 
     } 
    } 

public class Sketches : Tuple<string, string, string> 
{ 
    public Sketches(string SketchHref, string SketchNumber, string SketchName) : base(SketchHref, SketchNumber, SketchName) { } 
    public string SketchHref { get { return this.Item1; } } 
    public string SketchNumber { get { return this.Item2; } } 
    public string SketchName { get { return this.Item3; } } 
} 
1

Swift permite tuplas con nombre. Puede escribir algo como:

let interval = (start: 0, end: 10) 
let start = interval.start 

Son en efecto estructuras anónimas.

Cuestiones relacionadas