In F# what does top-level mean?
Asked Answered
S

1

7

When people talk about F# they sometimes mention the term top-level;

what does top-level mean?

For example in previous SO Q&A

Error FS0037 sometimes, very confusing
Defining Modules VS.NET vs F# Interactive
What the difference between a namespace and a module in F#?
AutoOpen attribute in F#
F# and MEF: Exporting Functions How to execute this F# function

The term also appears regularly in comments but for those Q&A I did not reference them.

The Wikipedia article on scope touches on this, but has no specifics for F#.

The F# 3.x spec only states:

11.2.1.1 Arity Conformance for Functions and Values

The parentheses indicate a top-level function, which might be a first-class computed expression that computes to a function value, rather than a compile-time function value.

13.1 Custom Attributes

For example, the STAThread attribute should be placed immediately before a top-level “do” statement.

14.1.8 Name Resolution for Type Variables

It is initially empty for any member or any other top-level construct that contains expressions and types.

I suspect the term has different meanings in different contexts: Scope, F# interactive, shadowing.

If you could also explain the origins from F# predecessor languages, (ML, CAML, OCaml) it would be appreciated.

Lastly I don't plan to mark an answer as accepted for a few days to avoid hasty answers.

Sesame answered 8/4, 2016 at 16:20 Comment(2)
Of interest related to OCaml: The toplevel systemSesame
Of interest: module vs type behavior difference on using F# lambda as actual argument to formal parameter that expects System.FuncSesame
M
4

I think the term top-level has different meaning in different contexts.

Generally speaking, I'd use it whenever you have some structure that allows nesting to refer to the one position at the top that is not nested inside anything else.

For example, if you said "top-level parentheses" in an expression, it would refer to the outer-most pair of parentheses:

((1 + 2) * (3 * (8)))
^                   ^

When talking about functions and value bindings (and scope) in F#, it refers to the function that is not nested inside another function. So functions inside modules are top-level:

module Foo = 
  let topLevel n = 
    let nested a = a * 10
    10 + nested n

Here, nested is nested inside topLevel.

In F#, functions and values defined using let can appear inside modules or inside classes, which complicates things a bit - I'd say only those inside modules are top-level, but that's probably just because they are public by default.

The do keyword works similarly - you can nest it (although almost nobody does that) and so top-level do that allows STAThread attribute is the one that is not nested inside another do or let:

module Foo =
  [<STAThread>] 
  do
    printfn "Hello!"

Bud it is not allowed on any do nested inside another expression:

do
  [<STAThread>] 
  do 
    printfn "Hello!"
  printfn "This is odd notation, I know..."
Monecious answered 8/4, 2016 at 19:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.