Getting the value of wildcard arm - wildcard

How would I get the value of the wildcard arm in a match statement?
For example:
let a = 1i;
let b = 2i;
match a.cmp(&b) {
Greater => println!("is greater"),
_ => println!("is {}", _) // error: unexpected token: `_`
}
I'm hoping for something cleaner than storing the enum being matched in a variable:
let a = 1i;
let b = 2i;
let ord = a.cmp(&b);
match ord {
Greater => println!("is greater"),
_ => println!("is {}", ord)
}

Is this what you're asking for?
let a = 1i;
let b = 2i;
match a.cmp(&b) {
Greater => println!("is greater"),
e => println!("is {}", e)
}

Related

How to send the result of a pipline into a switch statement?

I want to send the result of a pipeline into a switch statement
let onWithOptions = (~key: string, eventName, options: options, decoder) =>
onCB(eventName, key, event => {
...
event |> Tea_json.Decoder.decodeEvent(decoder) |>
switch x {
| Ok(a) => Some(a)
| Error(_) => None
}
})
I have tried to do it this way but it didn't work x is not recognizable in the switch statement
let onWithOptions = (~key: string, eventName, options: options, decoder) =>
onCB(eventName, key, event => {
...
let x = event |> Tea_json.Decoder.decodeEvent(decoder) |>
switch x {
| Ok(a) => Some(a)
| Error(_) => None
}
})
Any idea on how this could be done?
You could create an anonymous function to pass it into:
let x = event |> Tea_json.Decoder.decodeEvent(decoder) |> (x =>
switch x {
| Ok(a) => Some(a)
| Error(_) => None
})
This is the closest equivalent in Rescript to the function shot-hand in OCaml. But in this scenario is really just a convoluted way of giving the value a name:
let x = event |> Tea_json.Decoder.decodeEvent(decoder)
let x =
switch x {
| Ok(a) => Some(a)
| Error(_) => None
}

Get value of optional types when retrieving value of record fields in F#

I have a type defined as follows:
type Employee = {
Id: Guid
Name: string
Phone: string
Email: Option<string>
}
and an instance of this type:
let emp = {
Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
Name = "A"
Phone = "B"
Email = Some "E"
}
I want to extract the field names and values from this record type using reflection like the following:
let getFieldValueMappingOfARecordType (data: 'T) : seq<string * obj> =
let fieldValueMapping =
data.GetType()
|> FSharpType.GetRecordFields
|> Seq.map (
fun propertyInfo ->
(propertyInfo.Name, data |> propertyInfo.GetValue)
)
fieldValueMapping
Then invoking the above function with the instance of employee type
let mapping = getFieldValueMappingOfARecordType emp
|> Seq.toList
gives us:
val mapping : (string * obj) list =
[("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
("Email", Some "E")]
So far it's working well with non-optional type. But in case of optional types, it's returning the value of the field as either Some value or None. What I would like to do is to get the value when the field has Some value or make it null when it's None.
Essentially like the follwing:
val mapping : (string * obj) list =
[("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
("Email", "E")]
Or if the employee instance is like the following:
let emp = {
Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
Name = "A"
Phone = "B"
Email = None
}
Then,
val mapping : (string * obj) list =
[("Id", bc07e94c-b376-45a2-928b-508b888802c9); ("Name", "A"); ("Phone", "B");
("Email", null)]
This is what I have so far (non-working code):
open System
open Microsoft.FSharp.Reflection
open System.Reflection
type Employee = {
Id: Guid
Name: string
Phone: string
Email: Option<string>
}
let emp = {
Id = Guid "bc07e94c-b376-45a2-928b-508b888802c9"
Name = "A"
Phone = "B"
Email = Some "E"
}
let getSomeOrNull (t: Type) (o: obj) =
let opt = typedefof<option<_>>.MakeGenericType [| t |]
match (o :?> opt) with
| Some s ->
s
| None ->
null
let getValues (data: 'T) =
let values =
data.GetType()
|> FSharpType.GetRecordFields
|> Array.map (
fun propertyInfo ->
let value =
data |> propertyInfo.GetValue
let isOption =
propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() = typedefof<Option<_>>
match isOption with
| true ->
(propertyInfo.Name, (getSomeOrNull propertyInfo.PropertyType value))
| false ->
(propertyInfo.Name, value)
)
values
getValues emp
|> printfn "%A"
I think the only way to do this is with reflection:
let getSomeOrNull (t: Type) (o: obj) =
if isNull o then null
else t.GetProperty("Value").GetValue(o)
I think this should do the trick:
let getSomeOrNull (o: obj) =
match o with
| :? Option<string> as o -> a |> Option.toObj > box
| _ -> null

Flow $ObjMap on type parameter

Flow isn't producing the error I expect in the following. Is it a bug with Flow (probably) or do I misunderstand something about type parameters?
function test<A: Object>(
obj: A,
mapper: $ObjMap<A, <V>(V) => V => any>
) {
}
test(
{
foo: 1,
bar: '2',
},
{
foo: (x: number) => String(x),
bar: (x: number) => parseInt(x),
// ^^^^^^
// should error that this is the wrong argument type
}
)
It seems like a bug because the following produces an error, albeit in the wrong place:
const a = {foo: 1, bar: '2'}
type A = typeof a
type B = $ObjMap<A, <V>(V) => V => any>
const b: B = {
foo: x => String(x),
bar: (x: number) => parseInt(x),
}
Error:
3: type B = $ObjMap<A, <V>(V) => V => any>
^ Cannot instantiate `$ObjMap` because string [1] is incompatible with number [2] in the first argument.
References:
1: const a = {foo: 1, bar: '2'}
^ [1]
7: bar: (x: number) => parseInt(x),
^ [2]
Okay, I was able to get it to work with
declare function test<A: Object, M: $ReadOnly<$ObjMap<A, <I, O>(I) => I => O>>>(
obj: A,
mapper: M
): $ObjMap<M, <I, O>((I) => O) => O>
Not ideal because the output is only assignable to a $ReadOnly shape, but it covers all the type checking I need.

CCCrypt maximum time it returns nil. What is the problem in Encryption

I trying to write an encryption (AESCBC128) function based on CCCrypt and the CCCrypt is generating a random value.
for example, when I pass 016768821221 to function it'll return "0oTPFcKNWABTpBGgLlzsjw==" for the same iv and Key.
here's the iv: "khabbababab" and the key is : "khabbababab"
why it returns nil. The encryption is correct but some times it returns nil
extension String {
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = kCCKeySizeAES128
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = CCOptions(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
CCOptions(options),
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
print(String(data: data, encoding: .utf8) as Any)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
print("succccc")
return base64cryptString
}
else {
print("nill nill llllllllll")
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
Your aesEncrypt always passes a keylength of 16 to CCCrypt without checking that the key actually has at least 16 bytes of data.

How to link Java API classes using apiMappings?

How do you link to Java classes in sbt using apiMappings? This is my code below which works for various dependencies, but I'm unclear how to link to Java standard library classes?
apiMappings ++= {
def findManagedDependency(organization: String, name: String): Option[File] = {
(for {
entry <- (fullClasspath in Runtime).value ++ (fullClasspath in Test).value
module <- entry.get(moduleID.key) if module.organization == organization && module.name.startsWith(name)
} yield entry.data).headOption
}
val links = Seq(
findManagedDependency("org.scala-lang", "scala-library").map(d => d -> url(s"http://www.scala-lang.org/api/$scalaVsn/")),
findManagedDependency("com.typesafe.akka", "akka-actor").map(d => d -> url(s"http://doc.akka.io/api/akka/$akkaVersion/")),
findManagedDependency("com.typesafe", "config").map(d => d -> url("http://typesafehub.github.io/config/latest/api/")),
findManagedDependency("com.fasterxml.jackson.core", "jackson-core").map(d => d -> url("http://fasterxml.github.io/jackson-core/javadoc/2.3.1/")),
findManagedDependency("io.spray", "spray-http").map(d => d -> url("http://spray.io/documentation/1.1-SNAPSHOT/api/")),
findManagedDependency("io.spray", "spray-routing").map(d => d -> url("http://spray.io/documentation/1.1-SNAPSHOT/api/")),
findManagedDependency("org.slf4j", "slf4j-api").map(d => d -> url("http://www.slf4j.org/api/")),
findManagedDependency("com.typesafe.akka", "akka-testkit").map(d => d -> url(s"http://doc.akka.io/api/akka/$akkaVersion/")),
findManagedDependency("org.specs2", "specs2").map(d => d -> url(s"http://etorreborre.github.io/specs2/api/SPECS2-$specs2Version/"))
)
links.collect { case Some(d) => d }.toMap
}
Use the solution from How to link classes from JDK into scaladoc-generated doc?, i.e. add the following to apiMappings:
apiMappings += (
file("/Library/Java/JavaVirtualMachines/jdk1.8.0_11.jdk/Contents/Home/jre/lib/rt.jar") ->
url("http://docs.oracle.com/javase/8/docs/api")
)
and fixJavaLinksTask task will do the rest with the following in build.sbt:
import scala.util.matching.Regex.Match
autoAPIMappings := true
// builds -doc-external-doc
apiMappings += (
file("/Library/Java/JavaVirtualMachines/jdk1.8.0_11.jdk/Contents/Home/jre/lib/rt.jar") ->
url("http://docs.oracle.com/javase/8/docs/api")
)
lazy val fixJavaLinksTask = taskKey[Unit](
"Fix Java links - replace #java.io.File with ?java/io/File.html"
)
fixJavaLinksTask := {
println("Fixing Java links")
val t = (target in (Compile, doc)).value
(t ** "*.html").get.filter(hasJavadocApiLink).foreach { f =>
println("fixing " + f)
val newContent = javadocApiLink.replaceAllIn(IO.read(f), fixJavaLinks)
IO.write(f, newContent)
}
}
val fixJavaLinks: Match => String = m =>
m.group(1) + "?" + m.group(2).replace(".", "/") + ".html"
val javadocApiLink = """\"(http://docs\.oracle\.com/javase/8/docs/api/index\.html)#([^"]*)\"""".r
def hasJavadocApiLink(f: File): Boolean = (javadocApiLink findFirstIn IO.read(f)).nonEmpty
fixJavaLinksTask <<= fixJavaLinksTask triggeredBy (doc in Compile)
You may find my answer to this question what you are looking for.
This main difference between that answer and the other answer posted here is that the location of rt.jar is determined from the runtime, and not hard coded.

Resources