The pattern discriminator is not defined - f#

I'm new in F#, can you help me with this error: 'The pattern discriminator is not defined'
let findColorIndex colorArray, color =
let mutable index=0
for i in 0..colorArray.Length-1 do
if Color.FromName(colorArray.[i]).R.Equals(color.R) then
if Color.FromName(colorArray.[i]).G.Equals(color.G) then
if Color.FromName(colorArray.[i]).B.Equals(color.B)
then index<-i
index

The error message is difficult to read. It is the initial comma that the compiler does not like. You probably mean either
let findColorIndex colorArray color =
or
let findColorIndex (colorArray, color) =

Stylistically, your code looks like a straight translation of C# code. It works but it doesn't look very nice. I rewrote it as follows:
// A little helper function to get all color values at once
let getRGB (color : Color) = (color.R, color.G, color.B)
let findColorIndex colorArray color =
let rec findIdx i =
// If no matching color is found, return -1
// Could use options instead...
if i >= colorArray.Length then -1
elif getRGB (Color.FromName colorArray.[i]) = getRGB color then i
else findIdx (i + 1)
findIdx 0
Alternatively you could use Array.tryFindIndex:
let findColorIndex colorArray color =
// Returns None if no matching index is found,
// otherwise Some index
colorArray |> Array.tryFindIndex (fun c ->
getRGB (Color.FromName c) = getRGB color)

Related

Swift search value for the nearest similar value reagrdless of sequence

Hi guys I want to ask how do you search the items for the nearest possible similar value regarding of the sequence. Example as below when I search for ["Restaurant","Bull"], it should return me str2 is the possible nearest values. Because this function only able to work for order sequence, it cannot for non-sequence. I really hope you guys can help me out....
func search(`for` searchItems: Set<String>, `in` searchArea: [Set<String>]) -> Set<String>? {
return searchArea.max(by: { (a, b) -> Bool in
return searchItems.intersection(a).count < searchItems.intersection(b).count || searchItems.intersection(a).count > searchItems.intersection(b).count
})
}
let str2: Set<String> = ["Bull","Restaurant","Corner"]
let str3: Set<String> = ["Corner","Restaurant","Mole"]
let area = [str3, str2] as [Any]
print("search result",self.search(for: ["Restaurant","Bull"], in: area as! [Set<String>]))
Probably because your str2 and str3 is not Set at all, it's array coz you are using array declaration, thus change it to this then it works if you use ["Bull", "Restaurant"]:
let str2 = Set(["Bull","Restaurant","Corner"])
let str3 = Set(["Corner","Restaurant","Mole"])
Also, Set is non-ordered sequence, Array is ordered sequence
Just make a set out of your query array and use its isSubset(of:) method to check wether it's a subset of your data.
let set1 = Set([1,2,3])
let set2 = Set([2,3,4])
let query = [1,2]
let querySet = Set(query)
querySet.isSubset(of: set1) // true
querySet.isSubset(of: set2) // false
let query2 = [2,1]
let querySet2 = Set(query)
querySet2.isSubset(of: set1) // true
querySet2.isSubset(of: set2) // false

FSCL error on a simple example

I am trying to use openCL with FSCL on F# but I am obtaining some errors that I don't understand
open FSCL.Compiler
open FSCL.Language
open FSCL.Runtime
open Microsoft.FSharp.Linq.RuntimeHelpers
open System.Runtime.InteropServices
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point2 =
struct
val mutable x: float32
val mutable y: float32
new ( q ,w) = {x=q; y=w}
end
[<ReflectedDefinition>]
let PointSum(a:gpu_point2,b:gpu_point2) =
let sx =(a.x+b.x)
let sy =(a.y+b.y)
gpu_point2(sx,sy)
[<ReflectedDefinition;Kernel>]
let Modgpu(b:float32[], c:float32[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let arp = Array.zeroCreate<gpu_point2> b.Length
let newpoint = gpu_point2(b.[gid],c.[gid])
arp.[gid] <- newpoint
arp
[<ReflectedDefinition;Kernel>]
let ModSum(a:gpu_point2[],b:gpu_point2[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let cadd = Array.zeroCreate<gpu_point2> a.Length
let newsum = PointSum(a.[gid],b.[gid])
cadd.[gid] <- newsum
cadd
[<ReflectedDefinition;Kernel>]
let ModSum2(a:gpu_point2[],b:gpu_point2[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let cadd = Array.zeroCreate<gpu_point2> a.Length
let newsum = gpu_point2(a.[gid].x+b.[gid].x,a.[gid].y+b.[gid].y)
cadd.[gid] <- newsum
cadd
let ws = WorkSize(64L)
let arr_s1= <# Modgpu([|0.f..63.f|],[|63.f..(-1.f)..0.f|],ws)#>.Run()
let arr_s2 = <# Modgpu([|63.f..(-1.f)..0.f|],[|0.f..63.f|],ws)#>.Run()
With this code when I try to use ModSum as
let rsum = <# ModSum(arr_s1,arr_s2,ws)#>.Run()
doesn't work, but instead when I use ModSum2 works perfectly
let rsum = <# ModSum2(arr_s1,arr_s2,ws)#>.Run()
The error I obtain the first time I run it is
FSCL.Compiler.CompilerException: Unrecognized construct in kernel body NewObject (gpu_point2, sx, sy)
and if I re-run the fsi console says
System.NullReferenceException: Object reference not set to an instance of an object.
The only thing I know is that the error doesn't comes from the use of another function since I can define a dot product function that works.
[<ReflectedDefinition>]
let PointProd(a:gpu_point2,b:gpu_point2) =
let f = (a.x*b.x)
let s = (a.y*b.y)
f+s
Thus, I guess the problem comes from the return type of PointSum, but is there a way to create such a function to sum two points and return the point type? And Why is not working?
Edit/Update:
Also with a record happens the same if I define the type as :
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point_2 = {x:float32; y:float32}
If I try to create a function that directly sums two gpu_point_2 on a function works, but if I call a second function it raises the same error as using a struct.
Try to add [<ReflectedDefinition>] on the constructor of gpu_point2:
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point2 =
struct
val mutable x: float32
val mutable y: float32
[<ReflectedDefinition>] new (q, w) = {x=q; y=w}
end
Normally each code that is called from the device need this attribute, constructors included.

Indexes as Ints in Swift

I have the following code which I've commented:
func hash (s:String) -> Int {
var z = 19
let key = "abcdefghijk"
for var i = 0; i < s.characters.count; i++ {
let index = s.startIndex.advancedBy(i)
let char = s[index]
if let f = key.characters.indexOf(char) {
print(f) //This outputs the number I want to use in the next line, but as String.CharacterView.Index, not an Int
z = (z * f) //obviously this won't work
}
// So instead we try this:
z = z * s.startIndex.distanceTo(key.characters.indexOf(char)!))
// It works for the first few characters then I get "fatal error: can not increment endIndex" and a EXC_BAD_INSTRUCTION
}
return z
}
I'm struggling to use Swift String to find the index I want to use as an Int in some kind of a hash function. In case it isn't clear:
User inputs a string, the function iterates through each character, finding that character in the key and then takes the index of that character in key and multiplies it to the existing z counter.
I get the results I want but only in the wrong type which doesn't let me convert to Int. Anyone know how?
Thanks
f = key.characters.indexOf(char) is an index into the characters
of key, therefore you have to compute the distance to the start index of key, not s:
z = z * key.startIndex.distanceTo(key.characters.indexOf(char)!))
which you can move back to your if-let block:
if let f = key.characters.indexOf(char) {
z = z * key.startIndex.distanceTo(f)
}
You also might want to use the overflow operator &*
if let f = key.characters.indexOf(char) {
z = z &* key.startIndex.distanceTo(f)
}
otherwise the application will crash if the result of the
multiplication does not fit into an Int.
Generally, the indexes of a Swift String can only be used
with the same string (regardless of string length), as the following
example demonstrates:
let s1 = "abc"
let i1 = s1.characters.indexOf("b")!
print(i1) // 1
let s2 = "🇩🇪a🇩🇪b🇩🇪c"
print(s2.characters.count) // 6
let d2 = s2.startIndex.distanceTo(i1) // fatal error: can not increment endIndex
If you make your key into an array of Characters, then indexOf will return the Int you need:
func hash (s:String) -> Int {
var z = 19
let key = Array("abcdefghijk".characters)
for char in s.characters {
if let f = key.indexOf(char) {
print(f)
z = (z &* (f + 1))
}
}
return z
}
Also, if your character is the first index in the key you will get a value of 0 which will make your hash value 0, so I've added 1 to f. I also incorporated &* as suggested by #MartinR to prevent Int overflow.
First, don't use forced unwrap as you can end up easily crashing your app (as it seems it already happened).
Second, you already test for the validity of key.characters.indexOf(char), you can place the z computation within the if-let:
z = z * s.startIndex.distanceTo(f)
What happens with your code is that the hash() function crashes as soon as it encounters a character beyond k, so you should also add all possible characters to key.

Assigning a value post while-loop results in error

I'm struggling to figure out why I receive the following error:
Block following this 'let' is unfinished. Expect an expression.
let hashset = System.Collections.Generic.HashSet<int>()
let mutable continueLooping = true
while (continueLooping) do
let value = System.Random().Next(0, 12)
let success = hashset.Add(value)
continueLooping <- hashset.Count <> 12
let z = hashet
The error is based on the following line:
let z = hashset
Why am I receiving this error?
NOTE:
I am new to F#. As a result, please forgive my ignorance.
as far as I can tell it's just because you mixed tabs and spaces in there - and in deed this works if I evaluate it in FSharpInteractive:
let hashset = System.Collections.Generic.HashSet<int>()
let mutable continueLooping = true
while (continueLooping) do
let value = System.Random().Next(0, 12)
let success = hashset.Add(value)
continueLooping <- hashset.Count <> 12
let z = hashset
evaluates to
val hashset : System.Collections.Generic.HashSet<int>
val mutable continueLooping : bool = false
val z : System.Collections.Generic.HashSet<int>
then z |> Seq.toArray evaluates to
val it : int [] = [|2; 8; 9; 3; 4; 10; 5; 11; 0; 6; 1; 7|]
which seems fine
btw: as you have a slight typo in there: ... z = hashet instead of hashsetI think you did not copy&paste the code that caused your error anyways.

f# parsing string to color

type circle = { X : int; Y : int; Diameter : int; Color : Color}
let mutable clickedCircle = { X = 0; Y = 0; Diameter = 0; Color = Color.White}
let txtBoxVal4 = System.Enum.Parse(typeof<Color>,txtBox2.Text)
clickedCircle <- {X = txtBoxVal2; Y = txtBoxVal3; Diameter = txtBoxVal1; Color = txtBoxVal4}
I am trying to parse a textbox.text into a color. From this code i get the error:
Error 1 This expression was expected to have type
Color
but here has type
obj
Quite new to F# and not to sure about the syntax. The error comes at
"Color = txtBoxVal4"
System.Enum.Parse returns an obj type that you need to cast to the enum type. You can do that using :?> or downcast. In your case the type is known so you can use downcast.
See the Casting and Conversions docs for more.
clickedCircle <- {X = txtBoxVal2; Y = txtBoxVal3; Diameter = txtBoxVal1; Color = downcast txtBoxVal4}
A wrapper function for Enum.Parse could make good use of the enum constraint and eliminate the need for unboxing at the call site.
module Enum =
let parse<'T, 'U when 'T : enum<'U>> value = Enum.Parse(typeof<'T>, value) :?> 'T
let color = Enum.parse "Black"

Resources