Подтвердить что ты не робот

Языки, которые позволяют названные кортежи

Мне было интересно, существуют ли какие-либо языки, которые допускают именованные кортежи. Т.е.: объект с несколькими переменными различного типа и настраиваемое имя.

Например:

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())

Я мог бы понять, как динамика может поддерживать такую ​​функцию. Статические языки, которые я обычно плаваю (например, С#), могут выполнять словарь, но это не безопасно, если все элементы одного типа. Или вы можете использовать тип Tuple, но это означает, что у вас есть фиксированные имена членов (Var1, Var2 и т.д.).

Вы также можете написать небольшой пользовательский класс, но эту ситуацию я бы хотел избежать.

Я мог представить, что язык макросов может script что-то вроде этого для вас на статическом языке, но я не знаю такого языка.

Это выходит из моего ответа из этого вопроса о типах возврата.

4b9b3361

Ответ 1

В С# у вас есть анонимные типы; они похожи, но имеют свои собственные ограничения:

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

Однако использовать их в качестве вызывающего абонента трудно, если только вы не используете "cast by example" (хрупкое), отражение или dynamic. Из трех последних наиболее аппетитно.

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

В большинстве случаев было бы лучше просто использовать обычный класс, но этот подход имеет практическое применение; например, посмотрите, как они используются в ASP.NET MVC для простой и удобной передачи информации о конфигурации (что в противном случае требовало бы словаря). Немного похоже на то, как jQuery позволяет передавать параметры как свойства объекта.

Ответ 2

Старый вопрос, но мне нужно лучшее решение, я думаю.

Вы можете получить именованные параметры, используя тип Tuple, но обернув его в пользовательский именованный тип, который обертывает .Item1,.Item2 и т.д. в значимых именах свойств.

Я слишком ненавижу тот факт, что Tuples имеют неназванные параметры, которые делают код нечитаемым, но не могут игнорировать время, которое он сохраняет, чтобы самостоятельно реализовать IComparable, IStructuralEquatable и т.д., чтобы вы могли безопасно использовать свои структуры в качестве словарного ключа, например.

Я думаю, что это очень приятный компромисс:

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; } }
}

Теперь вместо этого мусора:

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);

Вы можете сделать это:

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);

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

Единственным недостатком является то, что если вы планировали использовать этот кортеж только в рамках одного метода, вам нужно объявить тип в рамках этого метода, содержащего класс. Для большинства приложений я не думаю, что проблема.

Ответ 3

Eiffel позволяет названные кортежи.

Ответ 4

Я знаю

  • Python (динамический, сильный ввод текста)
  • Eiffel (статический ввод строки)

Оба могут использоваться в .net

И, вероятно, Lisp, вы можете сделать что угодно с Lisp.

Ответ 5

Теперь это поддерживается, начиная с С# 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())

Смотрите: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/

Ответ 6

Вы имеете в виду что-то вроде Python collections.namedtuple? Ну, Python (текущие версии, 2.6 и 3.1) поддерживает их;-). Но серьезно, я не знаю, какой статически типизированный язык имел их как встроенный.

Ответ 7

Я не уверен, что это именно то, что вы ищете, но в Haskell у вас может быть запись с указанными именами и типами:

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}

выход:

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

Но это технически не кортеж. Насколько я знаю, у Haskell есть кортежи, но они не имеют имени.

Это действительно недалеко от простой структуры на любом C-производном языке. Возможно, я пропустил что-то в этом вопросе.

Ответ 8

Что не так с использованием структур или классов в С#?

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

Ответ 9

Несколько таких языков существуют. Слово для такого названного кортежа - это "запись". Семейство языков ML имеет такие записи вместе с соответствующими типами. Конкретные языки включают: SML, OCaml и, что важно, F #. Эта ссылка объясняет записи в F #: http://en.wikibooks.org/wiki/F_Sharp_Programming/Tuples_and_Records#Defining_Records

Ответ 10

Swift позволяет использовать названные кортежи. Вы можете написать что-то вроде:

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

Они представляют собой анонимные структуры.

Ответ 11

Спасибо Alain. Вот как я использовал ваш совет.

Динамический загрузчик изображений для карусели

<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>

И для С#

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

/* имя изображения соответствует местоположению папки Пример: 1234101005_001.Gif будет равен "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; } }
}

Ответ 12

Я не уверен, для чего вам это нужно - кортеж - это просто структура, которая содержит разные типы данных. Если вам действительно нужны именованные свойства, вам нужно будет создать собственный тип или создать анонимный тип на лету.

Я не знаю ни одного статически типизированного языка, который бы поддерживал это, но С#, конечно же, не делает.