Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this an F# quotations bug?

[<ReflectedDefinition>]
let rec x = (fun() -> x + "abc") ()

The sample code with the recursive value above produces the following F# compiler error:

error FS0432: [<ReflectedDefinition>] terms cannot contain uses of the prefix splice operator '%'

I can't see any slicing operator usage in the code above, looks like a bug... :)

Looks like this is the problem with the quotation via ReflectedDefinitionAttribute only, normal quotation works well:

let quotation =
    <@ let rec x = (fun() -> x + "abc") () in x @>

produces expected result with the hidden Lazy.create and Lazy.force usages:

val quotation : Quotations.Expr<string> =
   LetRecursive
   ([(x, Lambda (unitVar,
        Application
        (Lambda (unitVar0,
            Call (None,
            String op_Addition[String,String,String](String, String),
            [Call (None,
                String Force[String](Lazy`1[System.String]), // `
                [x]), Value ("abc")])),
        Value (<null>)))),
   (x, Call (None, Lazy`1[String] Create[String](FSharpFunc`2[Unit,String]), [x])),
   (x, Call (None, String Force[String](Lazy`1[String]), [x]))], x) // `

So the question is: is this an F# compiler bug or not?

like image 330
controlflow Avatar asked May 30 '10 12:05

controlflow


People also ask

What do the f-stop numbers mean?

An f-stop is expressed as a fraction, with “f” as the numerator and the f-stop number as the denominator. The aperture size reads inversely to its corresponding f-number: The smaller the f-number, the larger the aperture. The larger the f-number, the smaller the aperture.

What is the f on a camera?

Aperture controls the brightness of the image that passes through the lens and falls on the image sensor. It is expressed as an f-number (written as “f/” followed by a number), such as f/1.4, f/2, f/2.8, /f4, f/5.6, f/8, f/11, f/16, f/22, or f/32.

What is the lowest f-stop?

The lowest f-stop available is f/0.7. It belongs to Zeiss Planar 50mm, a lens used by NASA to film the moon, and Stanley Kubrick to make a film at candlelight. However, most photo lenses go as low as f/2, fewer go to f/1.2, and only a few reach f/0.95. The largest f-stop available is f/45.

What does f 2.8 mean in photography?

Here's the aperture scale. Each step down lets in half as much light: f/1.4 (very large opening of your aperture blades, lets in a lot of light) f/2.0 (lets in half as much light as f/1.4) f/2.8 (lets in half as much light as f/2.0)


1 Answers

I'd think that this may be caused by the treatment of recursive values in F#. As a workaround, you can turn the recursive reference into a parameter:

[<ReflectedDefinition>] 
let foo x = (fun() -> x + "abc") ()

// To construct the recursive value, you'd write:
let rec x = foo x

The last line is of course invalid (just like your original code), because you're creating an immediate recursive reference, but it should give you the idea - in reality, you'd probably enclose x in a lambda function.


EDIT Originally, I thought that the problem may be as below, but I'm not sure now (see comments).

It looks more like a (probably known) limitation to me than an unexpected bug. There is an important difference between the two versions of the code you wrote - in the first case, you're binding a public value (visible to .NET) named x while in the second case, x is just a symbol used only in the quotation.

The quotation that would have to be stored in the meta-data of the assembly would look like this:

let rec x = <@ (fun() -> %x + "abc") () @>

The body is quoted, but x is not a quoted symbol, so it needs to be spliced into the quotation (that is, it will be evaluated and the result will be used in its place). Note that this code will fail, because you're declaring a recursive value with immediate reference - x needs to be evaluated as part of its definition, so this won't work.

However, I think that % cannot appear in ReflectedDefinition quotations (that is, you cannot store the above in meta-data), because it involves some runtime aspects - you'd need to evaluate x when loading the meta-data.

like image 166
Tomas Petricek Avatar answered Sep 21 '22 21:09

Tomas Petricek