1

If you were to run across code like this in your travels would the short names bother you?

let setPropertyAssignment = 
    parser {
        let! a = setIdentifierName
        let! b = propertyName
        let! c = openParenthesis 
        let! d = propertySetParameterList
        let! e = closeParenthesis 
        let! f = openCurlyBracket 
        let! g = functionBody
        let! h = closeCurlyBracket
        return Node(NodeType.PropertyAssignment, [a;b;c;d;e;f;g;h])
    }

Here is the largest parser in the project:

let iterationStatement = 
    parser {
        let! a = doKeyWord
        let! b = statement
        let! c = whileKeyWord
        let! d = openParenthesis
        let! e = expression
        let! f = closeParenthesis
        let! g = statementTerminator
        let symbols = [a; b; c; d; e; f; g]
        return Node(NodeType.IterationStatement, symbols)
    } +++ parser {
        let! a = whileKeyWord
        let! b = openParenthesis
        let! c = expression
        let! d = closeParenthesis
        let! e = statement
        let symbols = [a; b; c; d; e]
        return Node(NodeType.IterationStatement, symbols)
    } +++ parser {
        let! a = forKeyWord
        let! b = openParenthesis
        let! c = maybeOne expressionNoIn
        let! d = semiColon
        let! e = maybeOne expression
        let! f = semiColon
        let! g = maybeOne expression
        let! h = closeParenthesis
        let! i = statement
        let symbols = [a;b] @ c @ [d] @ e @ [f] @ g @ [h;i]              
        return Node(NodeType.IterationStatement, symbols)
    } +++ parser {
        let! a = forKeyWord
        let! b = openParenthesis
        let! c = varKeyWord
        let! d = variableDeclarationListNoIn
        let! e = semiColon
        let! f = maybeOne expression
        let! g = semiColon
        let! h = maybeOne expression
        let! i = closeParenthesis
        let! j = statement
        let symbols = [a;b;c;d;e] @ f @ [g] @ h @ [i;j]
        return Node(NodeType.IterationStatement, symbols)
    } +++ parser {
        let! a = forKeyWord
        let! b = openParenthesis
        let! c = leftHandSideExpression
        let! d = inKeyWord
        let! e = expression
        let! f = closeParenthesis
        let! g = statement
        let symbols = [a;b;c;d;e;f;g]               
        return Node(NodeType.IterationStatement, symbols)
    }  +++ parser {
        let! a = forKeyWord
        let! b = openParenthesis
        let! a = varKeyWord
        let! c = variableDeclarationNoIn
        let! a = inKeyWord
        let! c = expression
        let! d = closeParenthesis
        let! e = statement
        let symbols = [a; b; c; d; e]
        return Node(NodeType.IterationStatement, symbols)
    }
ChaosPandion
  • 6,305
  • 2
  • 33
  • 33
  • F# has a pretty interesting syntax there... – TheLQ Sep 15 '10 at 21:26
  • @TheLQ - The "..." make me unsure if you mean that in a good way or bad. If bad, why do you say that? – ChaosPandion Sep 15 '10 at 22:33
  • possible duplicate of [How would you know if you've written readable and easily maintainable code?](http://programmers.stackexchange.com/questions/141005/how-would-you-know-if-youve-written-readable-and-easily-maintainable-code) – Bart van Ingen Schenau Jul 27 '15 at 10:48

3 Answers3

2

Depends on the complexity. With something this size, it's pretty obvious what you're doing and why. Make it much bigger--a page or so--and it'll get very confusing very quickly.

Mason Wheeler
  • 82,151
  • 24
  • 234
  • 309
2

The singe char variable names keeps the important parts readable. To my eye that is much more valuable that naming the throwaway variables.

I know little about F#, but if something like the example below is possible I would find that slightly more straightforward since there are not extra assignments involved:

let setPropertyAssignment = 
  parser {
    return Node(NodeType.PropertyAssignment,
                  [
                   Lazy.force setIdentifierName;
                   Lazy.force propertyName;
                   Lazy.force openParenthesis;
                   Lazy.force propertySetParameterList;
                   Lazy.force closeParenthesis;
                   Lazy.force openCurlyBracket;
                   Lazy.force functionBody;
                   Lazy.force closeCurlyBracket
                  ]
               )
  }
Bill
  • 8,330
  • 24
  • 52
  • I think the line *"The singe char variable names keeps the important parts readable."* really is the key here. As long as my parsers have proper names this should be a non issue. – ChaosPandion Sep 16 '10 at 18:47
  • Out of my own curiosity is it possible to inline the forcing instead of all the let!s or is my lack of F# experience showing? – Bill Sep 16 '10 at 21:25
  • It is showing... :) although with a bit of work I could get something similar working. – ChaosPandion Sep 17 '10 at 05:31
  • At least in the other .net languages there is often a performance penalty in assigning intermediate variables, so it might be worth trying. F# and I are still at the "you give me a headache" stage so I don't claim to be able to come up with valid syntax... – Bill Sep 17 '10 at 12:44
1

You'd benefit from a wrapper function that takes a list of parsers of 'a (your a to i above) and returns a single parser of 'a list. That way you wouldn't need to assign names to these intermediate parsers; you could drop them directly into a list.

Tim Robinson
  • 266
  • 1
  • 4
  • You know that is very tempting but I am not sure how I will integrate error handing into the parsers yet. I will keep this in mind though. *(This is my first parser combinator project so I wanted to reinvent the wheel as they say so I can understand how everything works.)* – ChaosPandion Sep 15 '10 at 22:35
  • Understood. The Parsec/FParsec approach is to not return `'a` directly, but to return a union of either `Ok of 'a` or `Error of string`. – Tim Robinson Sep 16 '10 at 08:12