c# - tipos - Idiomas que permiten tuplas con nombre
tipos de metodos que existen en c# (12)
¿Qué hay de malo con el uso de estructuras o clases en C #?
public class SpeedDistance{
public double Speed;
public int Distance;
}
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.
P.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())
Podría concebir cómo una dinámica podría soportar tal característica. Los lenguajes estáticos en los que suelo nadar (como c #) pueden hacer un Diccionario, pero eso 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 puedes escribir una pequeña clase personalizada, pero esa es la situación que me gustaría evitar.
Podría imaginar que un lenguaje de procesamiento de macros podría escribir algo así para usted en un lenguaje estático, pero no conozco ese lenguaje.
Esto sale de mi respuesta de esta pregunta sobre los tipos de devolución .
¿Quieres decir, algo así como las collections.namedtuple de Python. Bueno, Python (las versiones actuales, 2.6 y 3.1) los admite ;-). Pero, en serio, no conozco un lenguaje estáticamente tipificado que los tenga incorporados.
Eiffel permite tuplas con nombre.
En C #, tienes 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 consumirlos como llamador , a menos que use "cast by example" (frágil), reflejo 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 usar una clase regular, pero este enfoque tiene algunos usos prácticos; por ejemplo, observe cómo se usan en ASP.NET MVC para pasar la información de configuración de manera simple y conveniente (que de lo contrario requeriría un diccionario). Un poco como cómo jQuery le permite pasar opciones como propiedades en un objeto.
Esto ahora es compatible a partir de C # 7
(double speed, int distance) CalculateStuff(int arg1, int arg2)
var result = CalculateStuff(1,2);
Console.WriteLine("Speed is: " + result.speed.ToString())
Console.WriteLine("Distance is: " + result.distance.ToString())
Consulte: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/
Existen varios idiomas de este tipo. La palabra para tal tupla nombrada es "grabar". La familia lingüística ML tiene tales registros, junto con los tipos correspondientes. Los lenguajes concretos incluyen: SML, OCaml y, lo que es más importante, F #. Este enlace explica sobre los registros en F #: http://en.wikibooks.org/wiki/F_Sharp_Programming/Tuples_and_Records#Defining_Records
Gracias . Así es como usé tu consejo.
Cargador dinámico de imágenes para 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 para el C #
public List<Sketches> Sketches
{
get
{
List<Sketches> hrefs = new List<Sketches>();
/ * el nombre de la imagen coincide con un ejemplo de ubicación de carpeta: 1234101005_001.Gif sería igual a "c: / images / 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; } }
}
No estoy seguro de para qué necesitaría 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 estoy al tanto de ningún lenguaje estático que pueda admitir esto, pero C # ciertamente no lo hace.
No estoy seguro de si esto es exactamente lo que estás buscando, pero en Haskell, puedes tener un registro con 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}
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 tuplas, pero no se pueden nombrar por lo que sé.
Esto realmente no está lejos de ser una simple estructura en cualquier lenguaje derivado de C, tampoco. Tal vez me perdí algo en la pregunta.
Pregunta antigua, pero en la necesidad de una mejor solución, creo.
Puede obtener parámetros con nombre aprovechando el tipo Tuple, pero envolviéndolo en un tipo con nombre personalizado que contenga .Item1, .Item2, etc. en nombres de propiedades significativos.
También odio el hecho de que las tuplas tienen parámetros sin nombre que hacen que el código sea ilegible, pero no puedo ignorar el tiempo que ahorra tener que implementar IComparable, IStructuralEquatable, etc. por su cuenta para que pueda usar sus estructuras como una clave de diccionario, 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);
Tienes la oportunidad de 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 aún se beneficia de todas las maravillosas características de la tupla que le permiten usarla como una clave compleja en diccionarios, etc.
El único inconveniente es que si solo planeó usar esta tupla dentro del alcance de un solo 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.
Swift permite tuplas con nombre. Puedes escribir algo como:
let interval = (start: 0, end: 10)
let start = interval.start
Son en efecto estructuras anónimas.
Yo se de;
- Python (escritura dinámica, fuerte)
- Eiffel (estática, tipificación de cuerdas)
Ambos pueden ser utilizados en .net
Y probablemente Lisp, puedes hacer cualquier cosa con Lisp.