F#: let veranderlijk vs. ref

Ten eerste erken ik de mogelijkheid dat deze vraag een duplicaat zou kunnen zijn; laat het me weten.

Ik ben benieuwd wat de algemene “best practice” is voor die situaties waarin veranderlijkheid gewenst is. F# lijkt hiervoor twee faciliteiten te bieden: de binding let mutable, die lijkt te werken als variabelen in de “meeste” talen, en de referentiecel (gemaakt met de functie ref) waarvoor expliciete dereferentie vereist is om te gebruiken.

Er zijn een aantal gevallen waarin de een in de een of de ander wordt “gedwongen”: .NET interop heeft de neiging om veranderlijk te gebruiken met <-, en bij workflow-berekeningen moet men refmet :=. Dus die gevallen zijn vrij duidelijk, maar ik ben benieuwd wat ik moet doen bij het maken van mijn eigen veranderlijke variabelen buiten die scenario’s. Welk voordeel heeft de ene stijl boven de andere? (Misschien zou meer inzicht in de implementatie helpen.)

Bedankt!


Antwoord 1, autoriteit 100%

Ik kan alleen maar ondersteunen wat gradbotzei – als ik mutatie nodig heb, geef ik de voorkeur aan let mutable.

Wat betreft de implementatie en de verschillen tussen de twee – refcellen worden in wezen geïmplementeerd door een heel eenvoudig record dat een veranderlijk recordveld bevat. Je zou ze gemakkelijk zelf kunnen schrijven:

type ref<'T> =  // '
  { mutable value : 'T } // '
// the ref function, ! and := operators look like this:
let (!) (a:ref<_>) = a.value
let (:=) (a:ref<_>) v = a.value <- v
let ref v = { value = v }

Een opmerkelijk verschil tussen de twee benaderingen is dat let mutablede veranderlijke waarde op de stapel opslaat (als een veranderlijke variabele in C#) terwijl refde veranderlijke waarde opslaat in een veld van een aan een heap toegewezen record. Dit kan enige invloed hebben op de prestaties, maar ik heb geen cijfers…

Hierdoor kunnen veranderlijke waarden die refgebruiken een alias zijn – wat betekent dat je twee waarden kunt maken die verwijzen naar dezelfde veranderlijke waarde:

let a = ref 5  // allocates a new record on the heap
let b = a      // b references the same record
b := 10        // modifies the value of 'a' as well!
let mutable a = 5 // mutable value on the stack
let mutable b = a // new mutable value initialized to current value of 'a'
b <- 10           // modifies the value of 'b' only!

Antwoord 2, autoriteit 14%

Verwante vraag:“U zei dat lokale veranderlijke waarden niet kunnen worden vastgelegd door een sluiting, dus u moet in plaats daarvan ref gebruiken. De reden hiervoor is dat veranderlijke waarden die zijn vastgelegd in de sluiting moeten worden toegewezen op de heap (omdat sluiting op de heap wordt toegewezen).” van F# ref-mutable vars vs object velden

Ik denk dat let mutablede voorkeur heeft boven referentiecellen. Persoonlijk gebruik ik referentiecellen alleen als ze nodig zijn.

De meeste code die ik schrijf, gebruikt geen veranderlijke variabelen dankzij recursie en staartaanroepen. Als ik een groep veranderlijke gegevens heb, gebruik ik een record. Voor objecten gebruik ik let mutableom persoonlijke veranderlijke variabelen te maken. Ik gebruik eigenlijk alleen referentiecellen voor afsluitingen, over het algemeen gebeurtenissen.


Antwoord 3, autoriteit 8%

Zoals beschreven in dit MSDN-blogartikelin sectie Vereenvoudigd gebruik van veranderlijke waarden, u hebt geen referentiecellen meer nodig voor lambda’s.
Dus over het algemeen heb je ze helemaal niet meer nodig.


Antwoord 4, autoriteit 4%

Dit artikelvan Brian biedt mogelijk een antwoord.

Mutables zijn gebruiksvriendelijk en efficiënt (geen verpakking), maar kunnen niet worden vastgelegd in lambda’s. Ref-cellen kunnenworden vastgelegd, maar zijn uitgebreid en minder efficiënt (? – weet ik niet zeker).


Antwoord 5, autoriteit 2%

Misschien wil je de sectie Veranderlijke gegevensin het wikibook bekijken .

Voor het gemak volgen hier enkele relevante citaten:

Het veranderlijke sleutelwoord wordt vaak gebruikt
met recordtypen om veranderlijk te maken
records

Veranderlijke variabelen zijn enigszins
beperkt: mutables zijn niet toegankelijk
buiten de scope van de functie
waar ze zijn gedefinieerd. specifiek,
dit betekent dat het niet mogelijk is om
verwijzen naar een veranderlijke in een subfunctie
van een andere functie.

Ref-cellen omzeilen enkele van de
beperkingen van veranderlijken. In feite, ref
cellen zijn een heel eenvoudig gegevenstype dat:
een veranderlijk veld in een record inpakken
typ.

Aangezien ref-cellen zijn toegewezen aan de
hoop, ze kunnen worden gedeeld over
meerdere functies

Other episodes