3

I need a type that will be translated into a plain JS object so that F# field access will be translated into simple JS field access (this is necessary, since the object will be sent through postMessage, so it'll lose all its methods).

Again, I need

let x = a.b

to be translated into

var x = a.b;

without any method calls.

Here is a slightly modified example from the F# Reference:

namespace T

open IntelliFactory.WebSharper

[<JavaScript>]
module A =
    type MyClass =
        val a : int
        val b : int
        new(a0, b0) = { a = a0; b = b0; }

    let myClassObj = new MyClass(35, 22)
    let x = myClassObj.b

This won't translate with

x: error : Failed to translate property access: b.'

Ok, let's make those vals mutable:

namespace T

open IntelliFactory.WebSharper

[<JavaScript>]
module A =
    type MyClass =
        val mutable a : int
        val mutable b : int
        new(a0, b0) = { a = a0; b = b0; }

    let myClassObj = new MyClass(35, 22)
    let x = myClassObj.b

This will be successfully translated, but… MyClass.New returns an empty object. The question now starts looking much like a bugreport, right? So, back to the question.

Are there any other ways to achieve what I want?

kirelagin
  • 13,248
  • 2
  • 42
  • 57

2 Answers2

1

There are additional issues with record-style constructors "{x = y}". I will have to look into this again on F# 3.0, the older F# did not produce sensible quotations for those and we did some partial workarounds in WebSharper. Right now your example breaks. So here is the working code with a static method instead of a constructor:

type MyClass private () =

    [<DefaultValue>]
    val mutable a : int

    [<DefaultValue>]
    val mutable b : int

    static member Create(a0, b0) =
        let c = MyClass()
        c.a <- a0
        c.b <- b0
        c

let test () =
    let myClassObj = MyClass.Create(35, 22)
    let x = myClassObj.a
    let y = myClassObj.b
    JavaScript.Log(x, y)

Trivially, a record would also work.

In some cases where you want to go really low-level you can annotate members with the Inline attribute. When this is too much overhead you can use untyped API:

let x = obj ()
x?a <- 1
let y = x?a
JavaScript.Log(x, y)
t0yv0
  • 4,714
  • 19
  • 36
  • “static method instead of a constructor” that's exactly what I did for now… And what's that untyped thing? I can find it neither in F# nor in WebSharper docs. – kirelagin Apr 17 '13 at 16:14
0

try this:

type MyClass (a, b) =
    member val A = a with get
    member val B = b with get

let myClassObj = new MyClass(35, 22)
let x = myClassObj.B
cja03
  • 1