Code and proofs for Verse-ML, an equation-style sub-ml language. Part of an undergraduate senior thesis with Norman Ramsey, Milod Kazerounian, and Roger Burtonpatel.
I wanted to make actors and actions very clear. So, I changed the paper to have 'real' actors in it. Please let me know what you think.
The problem with Pat and Obe as actors is that the action of writing the code isn't important. What's important are the properties of the codes themselves. (The actors are also unimportant, but transparently so, so that might be OK.) They should probably get the hook.
Technical writing presents at least two classic problems that Williams does not provide much help with:
Definitions. In this case, we know what to do: each definition is made clear through examples.
Properties.
Section 2 cares about both. The definitions you can keep informal here, but I do think being a bit more explicit will help. The key aspect of the section is the properties, and here I think you'll be helped by laying out a claim: code written using pattern matching and its extensions has superior properties. Then be explicit about the superior properties. I'm not sure exactly what properties you care about, but they might include the following:
It's easier to avoid duplicating code.
It's easier to follow the decision-making.
Pattern matching militates toward naming important intermediate values.
A compiler may be able to tell if the code omits an important case.
WEAK: The code is shorter and easier to follow.
ANTIPATTERN: The code is more elegant.
Line 27: Observers aren't just for functional programmers, and they were proposed outside a functional context. So just "tool a functional programmer..."
Line 42: "structure" here, "form" earlier.
Line 43: "But many functional programmers favor..."
Line 46: "with against"
Line 46: Still struggling with verb "dominate." How do you feel about actor/action "programmers prefer"?
Line 52: "favors" vs "likes", which is it?
Line 68: subject should be Obe's code, not Obe.
Line 68: Strike "obviously." (It's a mathematical insult word, as in, if it's not obvious to my reader, I've just insulted them.)
Line 68, 2nd sentence, subjects should be case analysis and deconstruction, yes?
Line 68, paragraph: worth referring to line numbers in the figure? (for tl, ...)
Line 75: actor action, "code resembles"
Line 76: Needs intro with old information, e.g., "To see the resemblance, you..."
Line 78: Action of "paying syntactic cost" comes from left field and is too metaphorical for my taste.
Line 80: Pull the footnote up into the main text.
Lines 68 to 92: You need to decide how you want to refer to the examples. Pat/Obe or 1a and 1b? Personally I think Pat and Obe have served their purpose, but whatever you decide, it needs to be consistent.
Lines 83 to 87: Only 1b shows pattern matching. Nobody's preference is at issue. "Figure 1b provides an opportunity to introduce a few terms..."
Line 88: In several places you should switch plural to singular, but especially here, "A case expression tests a scrutinee."
Line 88: Combine notes 1 and 2 into a single footnote.
Line 93: Abrupt change of subject.
Lines 93 to 118: Are clausal definitions relevant to the proposal in your paper? Possibly as a disadvantage for the Verse style, which presumably doesn't support them? If they are relevant at all, you might consider delaying this introduction to the point where you compare pattern matching with Verse.
Lines 125 to 146: This intro isn't working so well for me. What problem is being solved by extensions? "Expressiveness falls short" is so vague as to be meaningless: new features are added because the original isn't expressive enough.
One idea, which will work for side conditions if nothing else, is to address the problem of code duplication. To proceed in that direction, you would need some examples of code people want to write where bare pattern matching requires code duplication. Perhaps some examples from your UFT?
Another possibility, perhaps less convincing, is difficulty in reading the code: if every alternative has its own choice in the case expression, perhaps the alternatives are easy to identify. But if some choices have multiple alternatives distinguished with if, maybe we believe the code is harder to read?
Line 137: "frequently" is way too strong here. How about "Language designers have introduced three extensions: side conditions, pattern guards, and or-patterns"?
Line 154: Can you come up with a better function to illustrate this issue? If not, at least give this function a better name.
Line 154: As you introduce each unfamiliar function (like nameOf), give its type.
Line 165: Please flag the OCaml examples as such, and please indicate which examples have and have not been typechecked.
Line 175: At this point I want to see the observer-based code for comparison.
Line 192, main verb "is": "And side conditions can exploit bindings..."
Like 197, main verb "address": "A side condition can incorporate ..."
Line 198: too general, needs an example first.
Line 206: The real "woof" here is the increasingly badly named nameOf. You need a real example. Perfectly OK to quote one from the literature.
Line 223: Since you're in OCaml for heaven's sake use &&.
Lines 223 to 226: Is this a straw man? (Also, I'm not confident about the outer Option.get on line 226. Have you typechecked this code?) We've already established the weakness of observers. So at least show how this issue might be handled using pattern matching:
let nameOf rho e = match e with
Name n
when binds rho n andalso
(case lookup n rho of Some (x :: xs) -> isSome (lookup x rho)
_ -> false)
-> (case lookup n rho of Some (x :: xs) ->
(case lookup x rho of Some y -> y
_ -> raise Impossible)
_ -> raise Impossible)
| _ -> None
Line 232: I see only two redundant calls to lookup?
Line 241: I missed that figure 5 was supposedly from Obe. What is match doing there? Eliminate it! And let's not make Obe out to be an idiot. A sane programmer would use exceptions and perhaps some let binding, e.g.,
let nameOf rho e =
let n = asName e in
let xs = Option.get (lookup n rho) in
let x = List.hd xs in
Option.get (lookup x rho)
handle _ -> None
Line 241: I can't find the four duplicate right-hand sides.
Lines 253 to 255: isn't this match expression equivalent to r2?
Line 267: "this problem" --- what problem?
Lines 266 to 267: "$PROBLEM can be addressed by pattern guards, a form ..."
(and use singular "an intermediate pattern binds to an expression").
Lines 267 to 271, coherent subjects: "Pattern guards can make nameOf ..., as shown in Figure 7---which, since pattern guards aren't found in OCaml, is written in Haskell."
Line 272: "Clear." Don't insult the reader who find the example unclear. Explain the syntax.
What things are separated by commas? Guards. What is a guard? Either a Boolean expression or? What is the dynamic semantics of a guard? It may succeed, binding zero or more variables, or it may fail.
Line 292: key sentence.
Figure 9 isn't convincing because the right-hand sides aren't complicated enough. And the real workarounds here aren't to convert the match to a sequence of if-then-else tests. There are two possibilities:
Abstract the duplicated code into a nested function, as in
let fortnite () = ... complicated ... in
let bloodborne () = ... complicated' ... in
let eldendring () = ... complicated'' ... in
match token with
| BattlePass -> fortnite ()
... and so on ...
Invent a bespoke algebraic datatype, as in
data game = Fortnite | Bloodborned | Eldenring
let parent_game_of_token token =
let game = match token with
| BattlePass -> Fortnite
... and so on ... in
match game with
| Fortnite -> ... complicated ...
| Bloodborne -> ... complicated' ...
| Eldendring -> ... complicated'' ...
Line 393: Not a smart claim. Some half-baked ideas for a transition might include the following:
I (rab) find the extension story vaguely unsatisfying. (And if you like, how do we know more extensions aren't coming. Cough view patterns cough. Although I think they actually don't fit here.)
I spotted an intriguing alternative: Verse.
Like clausal definitions (oops), Verse allows to write equations that resemble algebraic laws. But crucially, Verse's equations aren't oriented. What does that mean? Choices in a pattern match are oriented: a pattern always appears on the left, and an expression always appears on the right. And only a pattern can bind a variable. But in Verse, either side of an equation can bind a variable. And binding, instead of being assumed based on the position of a variable, is expressed by means of an explicit binding construct.
You write,
The problem with Pat and Obe as actors is that the action of writing the code isn't important. What's important are the properties of the codes themselves. (The actors are also unimportant, but transparently so, so that might be OK.) They should probably get the hook.
Technical writing presents at least two classic problems that Williams does not provide much help with:
Definitions. In this case, we know what to do: each definition is made clear through examples.
Properties.
Section 2 cares about both. The definitions you can keep informal here, but I do think being a bit more explicit will help. The key aspect of the section is the properties, and here I think you'll be helped by laying out a claim: code written using pattern matching and its extensions has superior properties. Then be explicit about the superior properties. I'm not sure exactly what properties you care about, but they might include the following:
It's easier to avoid duplicating code.
It's easier to follow the decision-making.
Pattern matching militates toward naming important intermediate values.
A compiler may be able to tell if the code omits an important case.
WEAK: The code is shorter and easier to follow.
ANTIPATTERN: The code is more elegant.
Line 27: Observers aren't just for functional programmers, and they were proposed outside a functional context. So just "tool a
functionalprogrammer..."Line 42: "structure" here, "form" earlier.
Line 43: "But many functional programmers favor..."
Line 46: "with against"
Line 46: Still struggling with verb "dominate." How do you feel about actor/action "programmers prefer"?
Line 52: "favors" vs "likes", which is it?
Line 68: subject should be Obe's code, not Obe.
Line 68: Strike "obviously." (It's a mathematical insult word, as in, if it's not obvious to my reader, I've just insulted them.)
Line 68, 2nd sentence, subjects should be case analysis and deconstruction, yes?
Line 68, paragraph: worth referring to line numbers in the figure? (for tl, ...)
Line 75: actor action, "code resembles"
Line 76: Needs intro with old information, e.g., "To see the resemblance, you..."
Line 78: Action of "paying syntactic cost" comes from left field and is too metaphorical for my taste.
Line 80: Pull the footnote up into the main text.
Lines 68 to 92: You need to decide how you want to refer to the examples. Pat/Obe or 1a and 1b? Personally I think Pat and Obe have served their purpose, but whatever you decide, it needs to be consistent.
Lines 83 to 87: Only 1b shows pattern matching. Nobody's preference is at issue. "Figure 1b provides an opportunity to introduce a few terms..."
Line 88: In several places you should switch plural to singular, but especially here, "A case expression tests a scrutinee."
Line 88: Combine notes 1 and 2 into a single footnote.
Line 93: Abrupt change of subject.
Lines 93 to 118: Are clausal definitions relevant to the proposal in your paper? Possibly as a disadvantage for the Verse style, which presumably doesn't support them? If they are relevant at all, you might consider delaying this introduction to the point where you compare pattern matching with Verse.
Lines 125 to 146: This intro isn't working so well for me. What problem is being solved by extensions? "Expressiveness falls short" is so vague as to be meaningless: new features are added because the original isn't expressive enough.
One idea, which will work for side conditions if nothing else, is to address the problem of code duplication. To proceed in that direction, you would need some examples of code people want to write where bare pattern matching requires code duplication. Perhaps some examples from your UFT?
Another possibility, perhaps less convincing, is difficulty in reading the code: if every alternative has its own choice in the case expression, perhaps the alternatives are easy to identify. But if some choices have multiple alternatives distinguished with
if
, maybe we believe the code is harder to read?Line 137: "frequently" is way too strong here. How about "Language designers have introduced three extensions: side conditions, pattern guards, and or-patterns"?
Line 154: Can you come up with a better function to illustrate this issue? If not, at least give this function a better name.
Line 154: As you introduce each unfamiliar function (like
nameOf
), give its type.Line 165: Please flag the OCaml examples as such, and please indicate which examples have and have not been typechecked.
Line 175: At this point I want to see the observer-based code for comparison.
Line 192, main verb "is": "And side conditions can exploit bindings..."
Like 197, main verb "address": "A side condition can incorporate ..."
Line 198: too general, needs an example first.
Line 206: The real "woof" here is the increasingly badly named
nameOf
. You need a real example. Perfectly OK to quote one from the literature.Line 223: Since you're in OCaml for heaven's sake use
&&
.Lines 223 to 226: Is this a straw man? (Also, I'm not confident about the outer
Option.get
on line 226. Have you typechecked this code?) We've already established the weakness of observers. So at least show how this issue might be handled using pattern matching:Line 232: I see only two redundant calls to
lookup
?Line 241: I missed that figure 5 was supposedly from Obe. What is
match
doing there? Eliminate it! And let's not make Obe out to be an idiot. A sane programmer would use exceptions and perhaps somelet
binding, e.g.,Line 241: I can't find the four duplicate right-hand sides.
Lines 253 to 255: isn't this
match
expression equivalent tor2
?Line 267: "this problem" --- what problem?
Lines 266 to 267: "$PROBLEM can be addressed by pattern guards, a form ..." (and use singular "an intermediate pattern binds to an expression").
Lines 267 to 271, coherent subjects: "Pattern guards can make
nameOf
..., as shown in Figure 7---which, since pattern guards aren't found in OCaml, is written in Haskell."Line 272: "Clear." Don't insult the reader who find the example unclear. Explain the syntax. What things are separated by commas? Guards. What is a guard? Either a Boolean expression or? What is the dynamic semantics of a guard? It may succeed, binding zero or more variables, or it may fail.
Line 292: key sentence.
Figure 9 isn't convincing because the right-hand sides aren't complicated enough. And the real workarounds here aren't to convert the match to a sequence of if-then-else tests. There are two possibilities:
Abstract the duplicated code into a nested function, as in
Invent a bespoke algebraic datatype, as in
Line 393: Not a smart claim. Some half-baked ideas for a transition might include the following:
I (rab) find the extension story vaguely unsatisfying. (And if you like, how do we know more extensions aren't coming. Cough view patterns cough. Although I think they actually don't fit here.)
I spotted an intriguing alternative: Verse.
Like clausal definitions (oops), Verse allows to write equations that resemble algebraic laws. But crucially, Verse's equations aren't oriented. What does that mean? Choices in a pattern match are oriented: a pattern always appears on the left, and an expression always appears on the right. And only a pattern can bind a variable. But in Verse, either side of an equation can bind a variable. And binding, instead of being assumed based on the position of a variable, is expressed by means of an explicit binding construct.