If you want to change the street name alone for profile
1
letmprofile={profilewithaddress={profile.addresswithstreet="Nungambakkam High Road"}}
The result will be
12345
> profile.tos()
val it : string = "Sheik. 1 - Road, Chennai 600001"
> mprofile.tos()
val it : string = "Sheik. 1 - Nungambakkam High Road, Chennai 600001"
Gracefully propogate the result from a callee function to caller is a good practise than using exceptions or null values. Exception raising and handling are mostly not under control due to its side effect nature. Also they come up with some cost in platform like .NET and Java.
I ususally enforce my team to use Result as method return type in imperative/OO languages like C#. It has a property IsValid so that callar can ensure whether the invocation is successful. Based on this, caller will take either actual Value or Error properties appropriately. This is one of the practise in functional reactive programming.
Functional languages address this with in-build pattern like F#’s Option, and Scala’s Some/None/Option. The weakness of these approaches is not providing failure case details to the caller. Scala provides a data type called Either. You can set either an actual value as Right or error details as Left. Alvin Alexander has written an interesting article about this (http://alvinalexander.com/scala/scala-either-left-right-example-option-some-none-null).
Let us define Either equivalent in F# with the help of discriminated union. I take the Alvin’s divide X by Y example here.
123
typeEither<'L,'R>=|Leftof'L|Rightof'R
Let us use this Either in the divide function as
12345678
letdividexy=ify=0thenLeft("Divide by zero")elseRight(x/y)letprnEither(v:Either<string,int>)=matchvwith|Left(s)->printfn"Error: %s"s|Right(i)->printfn"Result: %d"i
The prnEither is just a helper function to print the outcome to console.
12
prnEither(divide100)// prints "Error: Divide by zero"prnEither(divide1010)// prints "Result: 1"
Syntactic sugar for TaskCompletionSource
TaskCompletionSource provides SetException to set appropriate excpetion details and SetResult to set result if success. The below example demonstrate the usage of this in ‘sync’ way.
123456789101112131415161718
exceptionAmountErrorofstringletdebit(a:Account,amount:decimal)=// .Net way of promising and feature// don't worry about Account type definition herelettcs=newTaskCompletionSource<Account>()ifa.balance<amountthentcs.SetException(AmountError"Insufficient balance in account")elsetcs.SetResult({awithbalance=a.balance-amount})// returns Tasktcs.Taskleta={no="AnAccountNumber";name="Sheik";balance=100M}letb=debit(a,1000M)b.IsFaulted// prints trueb.Exception// you may get FSI_0002+AmountError: Exception of type 'FSI_0002+AmountError' was thrown.
letdebit(a:Account,amount:decimal)=// .Net way of promising and featurelettri=newTry<Account>()ifa.balance<amountthenFailuretri(AmountError"Insufficient balance in account")elseSuccesstri({awithbalance={amount=a.balance.amount-amount}})
As part of my IoT related experiments, reading Exploring Ardunio book for some insight. In order to get the list of electronic parts for the projects, http://exploringarduino.com/parts list out all required items. Here the excercise to take the HTML of the catalog from the web site using Chrome and then used F# script to get the plain list.
In the HTML, you can see the item title in the format of “title={item name}”
I define a regex to parse that specific item on every line.