I'm writing a toy compiler, which is in a very early stage of development. The lexer contains the following block of code:

    let consumeChar (state: LexerState) = 
        match state.CurrentChar() with
        | End -> state
        | _   -> { state with Offset = state.Offset + 1u }

    let tryConsume (ch: char) (state: LexerState) = 
        if state.CurrentChar() = Regular ch
        then Success <| consumeChar state
        else Failure state

    // ...

    let onForwardSlash() =
        let onUnterminatedMLComment = ...

        state |> consumeChar
              // Line comment
              |> tryConsume '/'
              |> andThenSuccess (consumeToEndOfLine >> lexToken)
              // Multiline comment
              |> orElse (tryConsume '*'
                         >> andThen (consumeTo "*/" 
                                     >> andThenSuccess lexToken
                                     >> orElseSuccess onUnterminatedMLComment))
              // Just a forward slash
              |> orElseSuccess (LexingResult.T (Punctuator Slash) start)

Where andThen, orElse and friends are defined like this:

type TryResult<'fail, 'res> = 
    | Failure of 'fail
    | Success of 'res

let orElse next tryResult =
    match tryResult with
    | Success res  -> Success res
    | Failure cont -> next cont

let andThen next tryResult =
    match tryResult with
    | Success cont -> next cont
    | Failure fail -> Failure fail 

let orElseSuccess f tryResult =
    match tryResult with
    | Success res  -> Success res
    | Failure cont -> Success <| f cont

let andThenSuccess f tryResult = ...

I arrived at this code "naturally" while trying to reduce duplication in the previous version. And the current version is shorter and seems less noisy indeed.

A little later, I stumbled across a blog post which discourages point-free style of programming.
And my code seems to be in a style quite similar to point-free. So it got me thinking. Briefly looking through the sources of FAKE, Paket, Suave, and FSharp compiler itself, they seem to keep function composition usage to a minimum.

Hence the question: Is the onForwardSlash function's code abusing function composition/point-free style?

(I know about FsLexxYacc and FParsec. This question is about code style, not implementing a lexer)

  • \$\begingroup\$ @200_success Added a link to the github repo with the full code. And added a summary of what the code is supposed to do in the question's text. The code pieces currently present in the question hopefully are the most relevant to it. Could you give a specific example of what is missing that prevents from understanding context? ... \$\endgroup\$
    – Myk
    Commented Sep 21, 2018 at 17:04
  • \$\begingroup\$ @200_success Also I'd be grateful if you could suggest a better title. I used questions like codereview.stackexchange.com/q/991/177486 and codereview.stackexchange.com/q/13759/177486 as a guideline when asking. They seem to be considered on-topic for the site. But at the end of the day, this question really is about the practice of point-free programming which I think the code is aligned with. So, if it's really off-topic, and cannot be improved, we should close it. \$\endgroup\$
    – Myk
    Commented Sep 21, 2018 at 17:10
  • 1
    \$\begingroup\$ I've edited it (Rev 5). I think it should be OK, since the GitHub link is there for context, and the code now has a stated purpose in the title. \$\endgroup\$ Commented Sep 21, 2018 at 18:03
  • \$\begingroup\$ @200_success Thank you for a great edit. Really improves the question. \$\endgroup\$
    – Myk
    Commented Sep 21, 2018 at 19:09


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.