Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for byref-like parameters for local functions #805

Open
Horusiath opened this issue Nov 8, 2019 · 2 comments
Open

Add support for byref-like parameters for local functions #805

Horusiath opened this issue Nov 8, 2019 · 2 comments

Comments

@Horusiath
Copy link

@Horusiath Horusiath commented Nov 8, 2019

Add support for recursive loops / loop breaks for ref structs

One of the common scenarios in programming languages is situation when we want to iterate over the elements of the collection up to a given point, when our expectation has been satisfied and we don't need to iterate any longer. In many languages (like C#) this can be easily done with foreach loop combined with break/early return.

However in F# this is not the case. To achieve that the common patter is to use recursive loop, eg.:

let tryFind item array =
    let rec loop item array i =
        if i >= Array.length array then -1
        elif array.[i] = item then i
        else loop item array (i+1)
    loop item array 0

Which will be unrolled by F# compiler into equivalent implementation with early return included. Problem is that this approach doesn't work when we want to pass ref struct (eg. ReadOnlySpan).

While I managed to work around this issue with variable flags, I don't thing it's expected way to work with things:

let tryFind item (span: ReadOnlySpan<_>) =
    let mutable i = 0
    let mutable found = -1
    while found = -1 && i < span.Length do
        if span.[i] = item then 
            found <- i
        i <- i + 1
    found

There are two possible ways to work with it:

  1. Enable recursive loops to work with ref structs as an input (which I admit is preferred one, as it keeps a language feature set consistent over supported types and has broader applicability).
  2. Introduce early returns (like break and return statements) to the language.

Extra information

Related issues:

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement...
  • ... and/or test this
@TIHan

This comment has been minimized.

Copy link

@TIHan TIHan commented Nov 8, 2019

You should probably change the title to:
Add support for byref-like parameters for local functions

The problem you are hitting is due to the lack of support for local functions having byref-like parameter types. You can do recursion just fine with byref-like types, you just need to make them top-level functions:

module Test

let rec loop item (array: ReadOnlySpan<_>) i =
    if i >= array.Length then -1
    elif array.[i] = item then i
    else loop item array (i+1)

This already works today.

But this example:

let topLevel () =
    let local (p: byref<int>) = p
    let mutable x = 1
    local &x

Does not work and this is what is preventing from you from having this code:

let tryFind item array =
    let rec loop item (array: ReadOnlySpan<_>) i =
        if i >= array.Length then -1
        elif array.[i] = item then i
        else loop item array (i+1)
    loop item array 0
@Horusiath Horusiath changed the title Add support for recursive loops / loop breaks for ref structs Add support for byref-like parameters for local functions Nov 8, 2019
@cartermp

This comment has been minimized.

Copy link
Member

@cartermp cartermp commented Nov 8, 2019

@TIHan what are your thoughts on enabling this kind of pattern?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.