I have an array of string UUIDs that I want to change to UUID. Example of the data:
["69359037-9599-48e7-b8f2-48393c019135" "1d8a7307-b5f8-4686-b9dc-b752430abbd8"]
How can I change or parse it? I tried using uuid.fromString() method:
if len(a) == 2 {
user1 := a[0]
a[0], _ = uuid.FromString(a[0])
}
However, this gives me an error
FromString returns UUID parsed from string input. Input is expected in
a form accepted by UnmarshalText.
With github.com/gofrs/uuid/v5, use uuid.FromString.
FromString returns UUID parsed from string input. Input is expected in a form accepted by UnmarshalText.
This method returns UUID or an error in case the parsing failed. You have two options to avoid explicit error handling:
FromStringOrNil, which returns only a UUID, but possibly nil in case of error
Must, which panics when the error of FromString is not nil. You use like:
uuid.Must(uuid.FromString("69359037-9599-48e7-b8f2-48393c019135"))
WARNING: satori/go.uuid, the older popular UUID package, nowadays is unmaintained and has unfixed issues. The package gofrs/uuid mentioned above is a maintained fork. From the package documentation:
We recommend using v2.0.0+ of this package, as versions prior to 2.0.0 were created before our fork of the original package and have some known deficiencies.
With github.com/google/uuid, use uuid.Parse. The rest of the pattern is the same as satori/uuid.
In your specific case, it looks like there's no problem in parsing the UUIDs, however the code you posted doesn't seem to produce the error you mention. Instead there is another problem:
a[0], _ = uuid.FromString(a[0])
you are attempting to reassign the value of uuid.FromString, which is a UUID to a[0] which is, presumably, a string.
The following code works fine (see it on Go Play):
var a = []string{"69359037-9599-48e7-b8f2-48393c019135", "1d8a7307-b5f8-4686-b9dc-b752430abbd8"}
func main() {
if len(a) == 2 {
user1 := a[0]
s, _ := uuid.FromString(a[0])
fmt.Println(user1) // prints 69359037-9599-48e7-b8f2-48393c019135
fmt.Println(s) // prints 69359037-9599-48e7-b8f2-48393c019135
}
}
Lets say, that I have this function in Javascript which can generate string based on proper configuration:
function func(config) {
// ...
}
also, let's assume, that the config variable has structure as below (all of these can be not given to function call):
{
"color": string, // can be: "blue", "red", "green"
"number": int, // can be: any number
"other": string, // can be: "x", "y"
}
How to create proper binding for this? I'm stuck with:
[#bs.deriving abstract]
type options = {
[#bs.optional]
color: [#bs.string] [ | `blue | `red | `green ]
[#bs.optional]
number: int,
[#bs.optional]
other: [#bs.string] [ | `x | `y ]
}
[#bs.module]
external func: options => string = "func";
But it does not work when trying to use like this:
let config = MyModule.config(
~color=`blue,
~number=123,
~other=`x
);
let value = MyModule.func(config);
The color and other values are integers, not strings.
This is a case of a JavaScript idiom for named parameters (objects with optional fields), needing to be adapted to the OCaml/ReasonML idiom (functions with actual labelled parameters). You would do this in three steps. Step 1, as Glenn showed, define an external for the config:
type config;
[#bs.obj] external config: (
~color:[#bs.string] [`blue | `red | `green]=?,
~number:int=?,
~other:[#bs.string] [`x | `y]=?,
unit,
) => config = "";
Step 2, bind to the JavaScript function using the JavaScript style of the config object:
[#bs.val] external func: config => string = "";
Step 3, wrap the JavaScript function binding in an OCaml-idiomatic function with labelled parameters:
let func(~color=?, ~number=?, ~other=?, ()) = ()
|> config(~color?, ~number?, ~other?)
|> func;
You can use it like this:
let result = func(~color=`blue, ());
The #bs attributes are often poorly thought out hacks that you shouldn't expect to work well with other attributes, or really with anything other than exactly what the documentation explains or shows examples of. However, if an attribute is used where it is not intended you'll usually at least get a warning about the attribute being unused, which your code does.
#bs.string in particular only works on types at the outermost level of externals, i.e. on types whose values will be passed directly to the external function. There is also a way to create JavaScript objects using external functions which also happens to use less magic and give you much more control over the API. As far as I'm aware, the only downside compared to #bs.deriving is that you can't override field names using something like #bs.as. They have to be valid OCaml identifiers.
Here's your example implemented using an external function annotated with #bs.obj:
type options;
[#bs.obj] external options : (
~color:[#bs.string] [`blue | `red | `green]=?,
~number:int=?,
~other:[#bs.string] [`x | `y]=?,
unit
) => options = "";
To use it you call it exactly as with #bs.deriving:
let config = options(~color=`blue,~number=123, ~other=`x, ());
But even with this I've encountered edge cases where integer values are passed in instead of strings. For this reason I tend to avoid the polymorphic variant attributes altogether and instead use ordinary variants along with conversion functions. This has the added benefit of being more idiomatic, blending in better and being more interoperable with non-BuckleScript code.
Here's what your example might look like using this approach:
type color = Blue | Red | Green;
let colorToString = fun
| Blue => "blue"
| Red => "red"
| Green => "green";
type other = X | Y;
let otherToString = fun
| X => "x"
| Y => "y";
[#bs.obj] external options : (
~color:string=?,
~number:int=?,
~other:string=?,
unit
) => options = "";
[#bs.module] external func: options => string = "func";
let func = (~color=?, ~number=?, ~other=?, ()) =>
func(options(
~color = ?Belt.Option.map(color, colorToString),
~number?,
~other = ?Belt.Option.map(other, otherToString),
()));
let config = func(~color=Blue,~number=123, ~other=X, ());
This is because in reality, those values are variants, instead of trying to make it exactly like JavaScript, I would rather try something more idiomatic to Reason:
type color = Blue | Green | Red;
type coords = X | Y;
type config = {
color,
coords,
number: int
};
let func = (config: config) => "something"
And then inside your function actually return strings (if that is what you really need) by pattern matching on the correct values provided to config.
See the working code here.
Hope it helps!
I have a small piece of F# code that is generating a cryptic error I can't figure out....
namespace epic.View
open System
open FSharp.Desktop.UI
[<AbstractClass>]
type public FieldModelBase<'ValueType>() =
inherit Model()
let mutable fieldCaption: string = null
let mutable fieldValue: 'ValueType = null
[<DerivedProperty>]
member this.Caption with public get() = sprintf "%s" fieldCaption and set value = fieldCaption <- sprintf "%s" value; this.NotifyPropertyChanged "Caption"
[<DerivedProperty>]
member inline this.Value with public get() = fieldValue and set value = fieldValue <- value; this.NotifyPropertyChanged "Value"
which generates the following error:
The signature and implementation are not compatible because the
declaration of the type parameter 'ValueType' requires a constraint of
the form 'ValueType : null
What does this mean and how do I resolve it? It looks like I should be adding a type constraint on the 'ValueType type-parameter to require it is... mutable? is that right?
In Scala 2.11.2, the following minimal example compiles only when using type ascription on the Array[String]:
object Foo {
def fromList(list: List[String]): Foo = new Foo(list.toArray : Array[String])
}
class Foo(source: IndexedSeq[String])
If I remove the type ascription in fromList, it will fail to compile with the following error:
Error:(48, 56) polymorphic expression cannot be instantiated to expected type;
found : [B >: String]Array[B]
required: IndexedSeq[String]
def fromList(list: List[String]): Foo = new Foo(list.toArray)
^
Why can't the compiler infer the Array[String] here? Or does this issue have to do something with the implicit conversion from Array's to IndexedSeq's?
The issue is that the .toArray method returns an Array of some type B which is a superclass of the T in List[T]. This allows you to use a list.toArray on List[Bar] where an Array[Foo] is required if Bar extends Foo.
Yes, the real reason this doesn't work out of the box is that the compiler is trying to figure out which B to use and also how to get to an IndexedSeq. It seems like it's trying to resolve the IndexedSeq[String] requirement but B is only guaranteed to be a String or a superclass of String; hence the error.
This is my preferred work around:
def fromList(list: List[String]): Foo = new Foo(list.toArray[String])
I'm trying to make a very simple application in F#. I want just to make a tiny button with the click event, which will call the MessageBox.Show() method.
open System
open System.Windows.Forms
module FSI =
[<System.Runtime.InteropServices.DllImport("user32.dll")>]
extern bool ShowWindow(nativeint hWnd, int flags)
let HideConsole() =
let proc = System.Diagnostics.Process.GetCurrentProcess()
ShowWindow(proc.MainWindowHandle, 0)
FSI.HideConsole()
let form1 = new Form()
form1.Text <- "App"
let Test() = ( MessageBox.Show("Clicked.") )
let button1 = new Button( Text = "Click Me" )
button1.Click.AddHandler(fun _ _ -> Test())
form1.Controls.Add(button1)
[<STAThread>]
do
Application.Run(form1)
The errors occurred for the:
FSI.HideConsole() // warning
button1.Click.AddHandler(fun _ _ -> Test()) // compiler error
And they are similar.
For the 1-st:
Warning This expression should have type 'unit', but has type 'bool'. Use 'ignore' to discard the result of the expression, or 'let' to bind the result to a name.
For the 2-nd:
This expression was expected to have type unit but here has type DialogResult
F# functions implicitly return the result of their last expression, so currently your function Test() returns the result of MessageBox.Show(string). To create a function that returns void/unit, you can use the ignore operator.
let Test() = ignore (MessageBox.Show("Clicked."))
It's a bit cumbersome to have to do the extra parenthesis wrapping, so typically one uses the pipeforward (|>) operator, which doesn't require that:-
let Test() = MessageBox.Show("Clicked.") |> ignore
This can also be applied to your call of HideConsole. The compiler uses the warning to inform you that the return value of HideConsole is not used.