mboost-dp1
Kotlin
- Forside
- ⟨
- Forum
- ⟨
- Tagwall
Jeg fatter ikke deres hensigt med at gøre Java mere sikkert ved checke for null pointer dereference..
De skriver:
Vi kan vælge at oprette en String som er nullable eller en som ikke er.. Så handler det endnu mere om at holde tungen lige i munden når man kigger andres kode igennem.
Som jeg læser det, giver de, ikke-nullable variabler, ikke længere en NullPointerException, men fejler bare i stilhed.. Dvs at det nu bliver sværere for udviklere at finde fejl!
Eller er det bare mig, der ikke har lært at læse?
EDIT: quote-fejl på newz.dk, ftw..!
De skriver:
http://confluence.jetbrains.net/display/Kotlin/Null-safety skrev:In Kotlin the type system distinguishes between references that can hold null (nullable references) and those that can not (non-null references). For example, a regular variable of type String can not hold null:var a : String = "abc"
a = null // compilation error
To allow nulls, one declares a variable as nullable string, written String?:var b : String? = "abc"
b = null // ok
Now, if you call a method on a, it's guaranteed not to cause an NPE, so you can safely sayval l = a.length()
But if you want to call the same method on b, that would not be safe, and the compiler reports an error:val l = b.length() // error: variable 'b' can be null
Vi kan vælge at oprette en String som er nullable eller en som ikke er.. Så handler det endnu mere om at holde tungen lige i munden når man kigger andres kode igennem.
Som jeg læser det, giver de, ikke-nullable variabler, ikke længere en NullPointerException, men fejler bare i stilhed.. Dvs at det nu bliver sværere for udviklere at finde fejl!
Eller er det bare mig, der ikke har lært at læse?
EDIT: quote-fejl på newz.dk, ftw..!
Jeg kan se at nogle udhvilede øjne læser bedre.. Jeg tog fejl.. Den vil ikke fejle i stilhed da alle non-nullable variabler altid vil have en værdi.
De fejler kun hvis man prøver at sætte dem til null.. Og det er ikke i stilhed.. Nå.. Men hvad er formålet..?
De skriver selv at det er til industrielt brug.. Men hvad er grunden til at arne_v har smidt linket op.. Hvad er det du gerne vil diskutere?
De fejler kun hvis man prøver at sætte dem til null.. Og det er ikke i stilhed.. Nå.. Men hvad er formålet..?
De skriver selv at det er til industrielt brug.. Men hvad er grunden til at arne_v har smidt linket op.. Hvad er det du gerne vil diskutere?
#5
Man må antage at de gerne vil lave et mere sikkert sprog.
Eksistensen af NULL/null/nil er ret omdiskuteret (i akademiske kreds).
http://en.wikipedia.org/wiki/Null_pointer#Null_poi...
Jeg postede det ikke fordi at jeg tror at kotlin bliver en succes - det tror jeg nemlig ikke.
Jeg postede det fordi fordi det er sundt at tænke lidt out of the box. Bare fordi at stprt set alle mainstream sprog idag har en NULL, så kunne det jo godt være at det slet ikke var så god en id.
Man må antage at de gerne vil lave et mere sikkert sprog.
Eksistensen af NULL/null/nil er ret omdiskuteret (i akademiske kreds).
http://en.wikipedia.org/wiki/Null_pointer#Null_poi...
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
Jeg postede det ikke fordi at jeg tror at kotlin bliver en succes - det tror jeg nemlig ikke.
Jeg postede det fordi fordi det er sundt at tænke lidt out of the box. Bare fordi at stprt set alle mainstream sprog idag har en NULL, så kunne det jo godt være at det slet ikke var så god en id.
Jeg vil hermed drage en sammenligning til matematikken: Ved at fjerne tallet 0 fra vores talsystem ville vi kunne undgå situationer hvor division med 0 opstod, hvilket lapper hullet med hvad der sker når man dividerer med 0 (Det må man ikke i matematikken).
Hvis man fjerner null som mulig værdi, så vil udviklerne blot sætte værdierne til at pege på en anden konstant, som så får samme funktion som værdien null.
Når value typer feks ikke kan initialiseres til null, så sætter man dem ofte i stedet til en default værdi, som feks ved tal typer ofte er tallet 0. Det betyder at værdien 0 nu kan betyde to ting: At variablen er uinitialiseret eller at variablen rent faktisk har værdien 0.
Jeg foretrækker nullable data typer så jeg utvetydigt kan definere værdien som værende uinitialiseret, fremfor at skulle checke for tvetydigheden hver gang jeg bruger variablen. Det gør koden simplere at forstå og lettere at læse, hvilket gerne skulle betyde færre fejl.
At mindre erfarne udviklere så har det med at glemme at initialisere variablerne og man dermed får en fejl når værdien null opstår, det må kunne løses på bedre måder end at fjerne muligheden for at sætte værdien null.
Hvis man fjerner null som mulig værdi, så vil udviklerne blot sætte værdierne til at pege på en anden konstant, som så får samme funktion som værdien null.
Når value typer feks ikke kan initialiseres til null, så sætter man dem ofte i stedet til en default værdi, som feks ved tal typer ofte er tallet 0. Det betyder at værdien 0 nu kan betyde to ting: At variablen er uinitialiseret eller at variablen rent faktisk har værdien 0.
Jeg foretrækker nullable data typer så jeg utvetydigt kan definere værdien som værende uinitialiseret, fremfor at skulle checke for tvetydigheden hver gang jeg bruger variablen. Det gør koden simplere at forstå og lettere at læse, hvilket gerne skulle betyde færre fejl.
At mindre erfarne udviklere så har det med at glemme at initialisere variablerne og man dermed får en fejl når værdien null opstår, det må kunne løses på bedre måder end at fjerne muligheden for at sætte værdien null.
Mort (7) skrev:Hvis man fjerner null som mulig værdi, så vil udviklerne blot sætte værdierne til at pege på en anden konstant, som så får samme funktion som værdien null.
Sikker?
C++ har haft references i mange år jeg mener ikke at null simulerings references er almindelige.
Mort (7) skrev:Jeg foretrækker nullable data typer så jeg utvetydigt kan definere værdien som værende uinitialiseret,
Hele pointen er vel at man vil fjerne mulighedem for unitialiserede variable.
Mort (7) skrev:At mindre erfarne udviklere så har det med at glemme at initialisere variablerne og man dermed får en fejl når værdien null opstår, det må kunne løses på bedre måder end at fjerne muligheden for at sætte værdien null.
Såsom?
Wikipedia skrev:In safe languages a possibly-null pointer can be replaced with a tagged union which enforces explicit handling of the exceptional case; in fact, a possibly-null pointer can be seen as a tagged pointer with a computed tag.
Det er sådan jeg ville foretrække det. Så siger man eksplicit i typen at returværdien muligvis ikke er veldefineret, og ting kan checkes statisk.
arne_v (8) skrev:Sikker?
Ja
Jeg ser det ofte brugt med data typer som ikke kan have værdien null.
arne_v (8) skrev:Hele pointen er vel at man vil fjerne mulighedem for unitialiserede variable.
Konkret eksempel: Lav en linked list uden brug af en uinitialiserings indikator som feks null eller predefineret værdi. Du kan godt gøre det, men det kræver at du bruger en anden værdi til at indikere at et element i listen er det sidste element - Dvs du flytter blot problematikken fra at bruge null til at checke en anden variabel i stedet.
arne_v (8) skrev:Såsom?
Du kan feks kræve at alle variable eksplicit får erklæret en værdi, når de defineres.
type 'a list = Cons of 'a * 'a list | Empty_list
Og så kan man skrive
let f x = match x with
Cons a * _ -> a + 1
| Empty_list -> 0
modulo "pseudokode"
Alternativet, som f.eks. F# har, er at bruge Options.arne_v (6) skrev:Eksistensen af NULL/null/nil er ret omdiskuteret (i akademiske kreds).
Sakset fra et af mine F# projekter:
type RelayCommand (execute : obj -> unit, canExecute : Option<obj -> bool>) =
member this.CanExecute(parameter) =
if canExecute.IsNone then
true
else
canExecute.Value(parameter)
Altså her er canExecute et optional parameter, og i stedet for at skulle pass null (enten direkte, eller fra et overload), så kan vi bruge en Option.
Der hvor Options er rigtige smarte, er nok mest når man laver pattern matching. Overstående kode kunne f.eks. skrives som
type RelayCommand (execute : obj -> unit, canExecute : Option<obj -> bool>) =
member this.CanExecute(parameter) =
match canExecute with
| IsNone -> true
| IsSome -> canExecute.Value(parameter)
Hvor man så er sikret at man *altid* håndtere muligheden for at der ikke er angivet et parameter.
Hvilket F# elegant har løst med Options.Mort (7) skrev:Hvis man fjerner null som mulig værdi, så vil udviklerne blot sætte værdierne til at pege på en anden konstant, som så får samme funktion som værdien null.
Når value typer feks ikke kan initialiseres til null, så sætter man dem ofte i stedet til en default værdi, som feks ved tal typer ofte er tallet 0. Det betyder at værdien 0 nu kan betyde to ting: At variablen er uinitialiseret eller at variablen rent faktisk har værdien 0.
Problemet er så at null ikke nødvendigvis er det samme som uinitialiseret. Det kan også være du har sat værdien til null for at indikere at den tidligere værdi skulle fjernes.Mort (7) skrev:Jeg foretrækker nullable data typer så jeg utvetydigt kan definere værdien som værende uinitialiseret, fremfor at skulle checke for tvetydigheden hver gang jeg bruger variablen.
Igen, i F# ville du bruge en Option, og sætte værdien til "None". Men til modsætning fra Null, så er None et slags flag, og ikke en værdi.
Windcape (14) skrev:Problemet er så at null ikke nødvendigvis er det samme som uinitialiseret. Det kan også være du har sat værdien til null for at indikere at den tidligere værdi skulle fjernes.
Er det ikke lige meget? Jeg ser bare null som en ikke-defineret værdi. Hvis man skal begynde at tolke en variabels null-værdi i koden, er man da galt på den.
Og ja, det gør man. Men se her:Mort (10) skrev:Dvs du flytter blot problematikken fra at bruge null til at checke en anden variabel i stedet.
type LinkedList<'T>() =
let mutable head = Option<Node<'T>>.None
member this.Insert(value) =
let node = new Node<'T>(value);
match head with
| None -> head <- Some node
| Some(value) ->
value.Next <- Some node
head <- Some node
Du kan slet ikke komme til at skrive
head.Next <- node
Hvilket betyder at du er sikret imod at head kan være null, og dermed skabe fejl, fordi du har *glemt* at initialisere head til en ikke-null værdi.
Komplet eksemple, til de interasserede:
Gist: https://gist.github.com/1103488
100% frit for null !
Gist: https://gist.github.com/1103488
open System
type Node<'T>(nodeValue : 'T, next : Node<'T> option) =
member this.NodeValue
with get() =
nodeValue
member this.Next
with get() =
next
type LinkedList<'T>() =
let mutable head = Option<Node<'T>>.None
let rec printList (node : Node<'T> option) =
match node with
| None -> None
| Some(value) ->
printfn "%A" value.NodeValue
match value.Next with
| None -> None
| Some(nextNode) -> printList(Some nextNode)
member this.Insert(value) =
let nextNode = new Node<'T>(value, head)
head <- Some nextNode
member this.PrintList() =
printList(head)
let list = new LinkedList<string>()
list.Insert("foo")
list.Insert("bar")
list.Insert("bas")
list.PrintList() |> ignore
Console.Read() |> ignore
100% frit for null !
Problemet er jo, når at du f.eks. henter data fra en 3rd parts service. Eksemple:tazimn (2) skrev:Som jeg læser det, giver de, ikke-nullable variabler, ikke længere en NullPointerException, men fejler bare i stilhed.. Dvs at det nu bliver sværere for udviklere at finde fejl!
var xml = GetXmlFromRemoteService();
var document = XElement.Parse(xml)
var rootElement = document.Element("foo")
var barElements = rootElement.Elements("bar")
Så forestiller vi os lige at vores 3rd parts service fejler, og der pludselig ikke er noget "foo" element. Altså er "rootElement" variablen null, og vi får en NPE. Træls! Fordi nu crasher din app, og det vil tage dig mindst 2 dage at deploy et fix.
Alternativet:
let xml = GetXmlFromRemoteService();
let document = XElement.Parse(xml)
let rootElement = document.Element("foo")
match rootElement with
| None ->
MessageBox.Show("An error occoured retriving the data. Please try again later");
| Some(value) ->
let barElements = value.Elements("bar")
Meget mere sikker kode! Og til modsætning fra det første eksempel, kan du ikke "glemme" at håndtere None/Some, til modsætning fra null.
Derudover så kan man jo med statisk analyse, f.eks. med Code Contracts til Visual Studio, sikre sig om referenceværdier kan være null på et tidspunkt hvor der forsøges at tilgå/kalde medlemmer på et objekt.
Windcape (19) skrev:Problemet er jo, når at du f.eks. henter data fra en 3rd parts service. Eksemple:
var xml = GetXmlFromRemoteService();
var document = XElement.Parse(xml)
var rootElement = document.Element("foo")
var barElements = rootElement.Elements("bar")
Så forestiller vi os lige at vores 3rd parts service fejler, og der pludselig ikke er noget "foo" element. Altså er "rootElement" variablen null, og vi får en NPE. Træls! Fordi nu crasher din app, og det vil tage dig mindst 2 dage at deploy et fix.
var xml = GetXmlFromRemoteService();
var document = XElement.Parse(xml)
var rootElement = "";
if (document.Element("foo")){
rootElement = document.Element("foo")
}
var barElements = rootElement.Elements("bar")
Problem solved..
Jeg bestemte mig for at det var noget javascript! ;-)
Hvis det endelig er kan der også checkes for exceptions i javascript..
#21
Fordelen i Windcape's eksempel er at det står i funktionstypen at den måske returnerer None, og derved kan det checkes statisk for om man håndterer det tilfælde. Altså kan din compiler hjælpe dig med at sikre at der ikke er sådan en fejl.
@Windcape
Hvorfor er der så mange paranteser i dit F# kode?
Edit: also hvorfor har du ingen projekter? :(
Fordelen i Windcape's eksempel er at det står i funktionstypen at den måske returnerer None, og derved kan det checkes statisk for om man håndterer det tilfælde. Altså kan din compiler hjælpe dig med at sikre at der ikke er sådan en fejl.
@Windcape
Hvorfor er der så mange paranteser i dit F# kode?
Edit: also hvorfor har du ingen projekter? :(
Windcape (16) skrev:Ikke nødvendigvis. I det ene tilfælde er dit reference objekt null (som default værdi), i det andet bruger du specifikt null som en faktisk værdi.
Hvilket er forkert! Her er en option bedre.
At bruge null som en faktisk værdi kan da kun være ukorrekt og misbrug af dens egentlige funktion.
Hvis #21 havde checket eksplicit mod null (ala foo===null), ville det da være det samme som None.
Jeg synes nu der er et minimum. Jeg er ikke sikker på at der kunne være mindre, da det f.eks. er påkrævet for at definere types. Måske for den rekursive print metode.onetreehell (23) skrev:Hvorfor er der så mange paranteser i dit F# kode?
huh? Hvis du mener github, så er det fordi at jeg foretrækker Mercurial, og dermed har alt mine projekter på bitbucketonetreehell (23) skrev:Edit: also hvorfor har du ingen projekter? :(
Men forskellen er bare stadigvæk at du ikke kan lave:Daniel-Dane (24) skrev:Hvis #21 havde checket eksplicit mod null (ala foo===null), ville det da være det samme som None.
<null>.DoStuff() med options.
<option>.DoStuff() vil ikke compile.
Uhm. Jeg kan da ikke forestille mig, at de fleste IDE'er ikke informerer om, at et objekt ikke er initialiseret.
Jeg kan da sværge på, at Delphi altid ville smide en advarsel (dvs. den ville stadig compile), hvis man forsøgte
Jeg kan da sværge på, at Delphi altid ville smide en advarsel (dvs. den ville stadig compile), hvis man forsøgte
var
obj: TObj // dynamisk objekt
begin
//obj := TObj.Create;
obj.DoStuff();
end
#27
Ja, hvis det er så åbenlyst. Problemet er når du instansisere ud fra en metode som retunere en værdi, eller null.
Eksemplet jeg gav med XElement tidligere var et rigtigt eksempel, fra en fejl i en af mine mobile apps. (Hvor der netop er 2 dages deployment tid, hvilket gør NPEs super irreterende)
Ja, hvis det er så åbenlyst. Problemet er når du instansisere ud fra en metode som retunere en værdi, eller null.
Eksemplet jeg gav med XElement tidligere var et rigtigt eksempel, fra en fejl i en af mine mobile apps. (Hvor der netop er 2 dages deployment tid, hvilket gør NPEs super irreterende)
Windcape (28) skrev:(Hvor der netop er 2 dages deployment tid, hvilket gør NPEs super irreterende)
Som Microsoft mand med 2 dage deployment tid, må du vel bare lade være med at lave sådanne tåblige fejl.
Du kan vel ikke give IDE'et eller compileren skylden. Du må da bare have styr på dine variable.
En NPE er vel ikke mere irrerterende end andre fejl.
Her er nogle eksempler hvor jeg er rimelig sikker på at paranteser kan undlades.
Er al din F# kode så mutable?
match value.Next with
| None -> None
| Some nextNode -> printList (Some nextNode)
member this.Insert value =
let nextNode = new Node<'T>(value, head)
head <- Some nextNode
list.Insert "foo"
list.Insert "bar"
list.Insert "bas"
Er al din F# kode så mutable?
Windcape (28) skrev:Eksemplet jeg gav med XElement tidligere var et rigtigt eksempel, fra en fejl i en af mine mobile apps.
Jeg kan ikke læse F# (*), men det ser meget pænt ud (bortset fra at man skal gentage meget kode). Jeg synes stadig (i din kode), at du checker mod None hele tiden (som lige så godt kunne være null).
Nå, drop det, Windcape. Jeg checker altid mod null (i hvert fald objekter og funktioner, jeg ikke kender), så jeg får ikke de problemer alligevel (**).
*)
Jeg stødte på en fuld datalog en nat, som fortalte, at man som datalog ikke lærer programmeringssprog men programmering. Resten var bare semantik eller sådan noget. Ja, den er god med ham. F# er fandeme hieroglyffer.
**)
En anden årsag til, at jeg ikke får de problemer er, at jeg ikke programmerer. Det løser en del problemer (jeg hader exceptions).
Windcape (34) skrev:hah :D Godt jeg ikke valgte haskell som eksempel sprog så!
Det sprog vil jeg nu lære blot for at irritere dig. Eller så bliver det bare mig, der bliver irriteret.
#32
Jeg har vist blandet din kode lidt sammen. I #17 er dine nodes også mutable.
Hvad gør du så med funktioner med to eller flere argumenter? f. eks.
Pointen med at bruge option-typer er at man _kun_ skal "checke for null", altså None, når returtypen er en optiontype. Ved mange funktioner er der slet ikke behov for en optiontype da det altid giver et meningsfuldt resultat. Derfor ville det også være fjollet at tjekke for null i f. eks. java hvis man ved det altid giver et meningsfyldt svar. Men det kan compileren ikke vide med null.
=D
Jeg har vist blandet din kode lidt sammen. I #17 er dine nodes også mutable.
Hvad gør du så med funktioner med to eller flere argumenter? f. eks.
let add3 x y z = x + y + z
Daniel-Dane (33) skrev:Jeg kan ikke læse F# (*), men det ser meget pænt ud (bortset fra at man skal gentage meget kode). Jeg synes stadig (i din kode), at du checker mod None hele tiden (som lige så godt kunne være null).
Nå, drop det, Windcape. Jeg checker altid mod null (i hvert fald objekter og funktioner, jeg ikke kender), så jeg får ikke de problemer alligevel (**).
Pointen med at bruge option-typer er at man _kun_ skal "checke for null", altså None, når returtypen er en optiontype. Ved mange funktioner er der slet ikke behov for en optiontype da det altid giver et meningsfuldt resultat. Derfor ville det også være fjollet at tjekke for null i f. eks. java hvis man ved det altid giver et meningsfyldt svar. Men det kan compileren ikke vide med null.
Daniel-Dane (33) skrev:Jeg stødte på en fuld datalog en nat, som fortalte, at man som datalog ikke lærer programmeringssprog men programmering. Resten var bare semantik eller sådan noget.
=D
Mort (10) skrev:Konkret eksempel: Lav en linked list uden brug af en uinitialiserings indikator som feks null eller predefineret værdi. Du kan godt gøre det, men det kræver at du bruger en anden værdi til at indikere at et element i listen er det sidste element - Dvs du flytter blot problematikken fra at bruge null til at checke en anden variabel i stedet.
Der er naturligvis ikke nogen speciel pointe i at teste på en anden variabel af type boolean fremfor at teste for om pointeren er null.
Men det kan godt gøres uden. Hvis du har forskellige konkrete sub klasser alt efter om node er head, middle eller tail, så kan lidt almindelig polymorfisme klare det.
Mort (10) skrev:Du kan feks kræve at alle variable eksplicit får erklæret en værdi, når de defineres.
??
Hvis værdien ikke må være null, så er det kotlin løsningen.
Hvis værdien gerne må være null, så er problemet ikke løst.
Windcape (13) skrev:Alternativet, som f.eks. F# har, er at bruge Options.
Windcape (14) skrev:Igen, i F# ville du bruge en Option, og sætte værdien til "None". Men til modsætning fra Null, så er None et slags flag, og ikke en værdi.
Windcape (18) skrev:100% frit for null !
Windcape (19) skrev:Meget mere sikker kode! Og til modsætning fra det første eksempel, kan du ikke "glemme" at håndtere None/Some, til modsætning fra null.
Windcape (26) skrev:Men forskellen er bare stadigvæk at du ikke kan lave:
<null>.DoStuff() med options.
<option>.DoStuff() vil ikke compile.
Hm.
Jeg synes at det er et mærkeligt billede du tegner af options.
F# options er det som gør at du kan få NPE i F#.
F# har valgt at have typer som ikke kan være null.
Og så har man indført option for at kunne gøre det alligevel.
Så med option skal man huske at teste for none og glemmer man det og forsøger at gøre noget forkert, så får man en NPE.
Min F# kundskaber er ikke godt nok til de meget avancerede eksempler, men følgende giver en NPE:
#light
let s2 : string option = None;;
printfn "%s" (s2.ToString());;
#39
Umiddelbart tror jeg ikke du kan det der og vil få en compile fejl.
I OCaml ville det tilsvarende nok være
eller
Begge vil give en compilefejl da s ikke er af typen string, men (string) option.
Umiddelbart tror jeg ikke du kan det der og vil få en compile fejl.
I OCaml ville det tilsvarende nok være
let s : string option = None
print_string s
eller
let s = Some "Hello, World!"
print_string s
Begge vil give en compilefejl da s ikke er af typen string, men (string) option.
Det er en F# optimization. En null option er bogstaveligtalt null.arne_v (45) skrev:Jeg gætter på at det er en form for side effect af at F# skal passe ind i .NET konteksten.
Men det er meningen at man altid skal bruge options med match.
dvs.
match s2 with
| None -> None
| Some s2 -> printf "%s" s2
Så det handler altså ikke om null vs. None, men at det kun er visse typer, som kan være None/null.
match s2 with
| null -> noop
| Some s2 -> printf "%s" s
#47
Sådan har det jo altid været, da value-types som bekendt ikke kan være null.
Men pointen med options var at vise at det ikke var nødvendigt at instantisere variable til null som default. F# kræver altid explicit instantisering. F.eks. kan du ikke lave følgende C#
I F# vil du ALTID skulle tildele det en værdi, hvilket man så gør med options. Og hvis options altid håndteres med match (hvilket er meningen) så giver det mere solid kode, end tilsvarende C#.
Sådan har det jo altid været, da value-types som bekendt ikke kan være null.
Men pointen med options var at vise at det ikke var nødvendigt at instantisere variable til null som default. F# kræver altid explicit instantisering. F.eks. kan du ikke lave følgende C#
class N
{
private string name; // equiv to setting the value to = null.
}
I F# vil du ALTID skulle tildele det en værdi, hvilket man så gør med options. Og hvis options altid håndteres med match (hvilket er meningen) så giver det mere solid kode, end tilsvarende C#.
Windcape (46) skrev:Det er en F# optimization. En null option er bogstaveligtalt null.
Men det er meningen at man altid skal bruge options med match.
dvs.
match s2 with
| None -> None
| Some s2 -> printf "%s" s2
Det er da en ringe "optimering". Pludselig har man genindført null pointer exceptions i et ellers sikkert sprog (mht. null pointer fejl).
Jeg har ikke set andre sprog med option typer der tillader sådan noget.
Opret dig som bruger i dag
Det er gratis, og du binder dig ikke til noget.
Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.