Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#Seq.sort是否返回输入序列的副本?_F#_Functional Programming_C# To F# - Fatal编程技术网

F#Seq.sort是否返回输入序列的副本?

F#Seq.sort是否返回输入序列的副本?,f#,functional-programming,c#-to-f#,F#,Functional Programming,C# To F#,这里有一些(我)在F#中意想不到的行为。我有一个简单的类对序列进行排序: type MyQueue<'a when 'a : comparison> ( values : 'a[] ) = let vals = Seq.sort values member this.First = Seq.nth 0 vals override this.ToString() = Seq.fold ( fun s a -> s

这里有一些(我)在F#中意想不到的行为。我有一个简单的类对序列进行排序:

type MyQueue<'a when 'a : comparison> ( values : 'a[] )  = 

    let vals =
        Seq.sort values

    member this.First = Seq.nth 0 vals

    override this.ToString() =
        Seq.fold ( fun s a -> s + a.ToString() + ";" ) "" vals
键入MyQueue(值:'a[])=
让瓦尔斯=
排序值
成员this.First=Seq.nth 0 VAL
重写此.ToString()=
Seq.fold(趣味s a->s+a.ToString()+“;”)VAL
我编写了一个稍微做作的单元测试(用C#)来测试这一点:

private class TestObject : IComparable
    {
        public TestObject( double Value )
        {
            this.Value = Value;
        }

        public void Update(double NewValue)
        {
            this.Value = NewValue;
        }

        public double Value { get ; private set; }

        public int CompareTo(object Comparable)
        {
            return this.Value.CompareTo( (Comparable as TestObject).Value );
        }

        public override string ToString ()
        {
            return Value.ToString();
        }
    }

    [Test]
    public void TestUpdate_OK()
    {

        var nums = new double[]{7,4,3,12,11,3,8};

        var values = nums.Select( n => new TestObject(n) ).ToArray();

        var q = new MyQueue<TestObject>( values );

        Console.WriteLine ( q.ToString() );

        // update one of the values in the collection - should not re-sort the collection
        values[3].Update( 2.0 );

        Console.WriteLine ( q.ToString() );

        Assert.AreEqual( q.First.Value, 3.0 );
    }
私有类TestObject:IComparable
{
公共测试对象(双值)
{
这个。值=值;
}
公共无效更新(双新值)
{
this.Value=NewValue;
}
公共双值{get;private set;}
公共整数比较(对象可比较)
{
返回此.Value.CompareTo((与TestObject.Value相当);
}
公共重写字符串ToString()
{
返回值.ToString();
}
}
[测试]
public void TestUpdate_OK()
{
var nums=新的双[]{7,4,3,12,11,3,8};
var values=nums.Select(n=>newtestobject(n)).ToArray();
var q=新的MyQueue(值);
Console.WriteLine(q.ToString());
//更新集合中的一个值-不应对集合重新排序
值[3]。更新(2.0);
Console.WriteLine(q.ToString());
断言.AreEqual(q.First.Value,3.0);
}
Seq.sort会对序列进行排序,并且第一个输出是正确的:

三,;3.4.7.8.11;12;

但是,更新测试(引用类型)对象会导致序列重新排序:

二,;3.3.4.7.8.11;

我希望MyQueue对象中的VAL现在将被取消排序,因为引用对象中的值已更改,但Seq.sort似乎已再次执行。我不明白,我以为函数式编程的目的是为了避免副作用。为什么我会有这种行为

F#Seq.sort是否返回输入序列的副本

对。它还能做什么呢?更改需要复制的一组值类型的顺序(在所有.NET语言中都是如此)

(这包括C#和VB中的LINQ操作符:惰性方面是仅在需要第一个复制的元素时才进行复制,此时将创建一个完整的新集合。)

F#Seq.sort是否返回输入序列的副本

对。它还能做什么呢?更改需要复制的一组值类型的顺序(在所有.NET语言中都是如此)


(这包括C#和VB中的LINQ运算符:惰性方面是仅在需要第一个复制的元素时才进行复制,此时将创建一个完整的新集合。)

您实际上可以直接在f#的源代码中检查这一点,但简言之,它的作用是调用Seq.toArray,在适当的位置对数组进行排序并将该数组作为序列返回。

实际上,您可以直接在f的源代码中对此进行检查,但简而言之,它所做的是调用Seq.toArray,对数组进行适当排序,并将该数组作为序列返回。

原因是语句
let vals=Seq.sort values
在某些代码使用VAL变量(即Seq.fold在toString方法中所做的操作)之前,实际上不会对值进行排序,它使用VAL序列,此时进行排序,无论值数组中当时有什么值,都会对这些值进行排序,因此基本上排序是在调用toString方法时进行的

另外,我不会将其称为FP:),因为您基本上是通过使用私有状态创建类型来执行OOPs,并且该状态由类型成员访问


您的问题与序列的工作方式有关,通常不适用于FP。

原因是语句
let vals=Seq.sort values
在某些代码使用VAL变量(即Seq.fold在toString方法中的作用)之前,实际上并没有对值进行排序,它使用VAL序列,此时进行排序,无论值数组中当时有什么值,都会对这些值进行排序,因此基本上排序是在调用toString方法时进行的

另外,我不会将其称为FP:),因为您基本上是通过使用私有状态创建类型来执行OOPs,并且该状态由类型成员访问


您的问题与序列的工作方式有关,通常不适用于FP。

我认为这是我不理解的核心问题。我的单元测试中有2个ToString()。我原以为第一天会发生这种事。因此,第一个ToString()按预期顺序排列。然而,第二个输出也被重新排序,我不知道这是从哪里来的。我同意这不是FP,但我不认为F#是纯粹的函数。但是,我确实希望语句let vals=Seq.sort values在功能上起作用。当您调用ToString时,排序正在进行,因此每次调用ToString时,都会对基础数组进行排序,并返回此排序数组的字符串表示形式。如果u make
let vals=Array.sort values
,则排序仅在创建对象时发生,并且toString将始终返回相同的结果,而与对原始数组对象的修改无关,因为Array.sort将创建一个新的已排序数组Seq只是IEnumerable的F#表示。如果您知道LINQ到对象,那么同样的概念也适用于Seq。将seq视为未来的值,当您对seq执行某些操作时,结果是一个seq,这意味着您只是在设置一个管道,但该管道尚未执行,当您开始使用foreach或toList etcAha从中提取值时,它将被执行,我想我看到了我的困惑。我认为在创建类型时,let vals=Seq.sort values行只调用了一次,但每次调用ToString时都会调用它。佩妮的头发掉了