How can I write a no-op statement in F#?
Specifically, how can I improve the second clause of the following match statement:
match list with
| [] -> printfn "Empty!"
| _ -> ignore 0
Use unit for empty side effect:
match list with
| [] -> printfn "Empty!"
| _ -> ()
The answer from Stringer is, of course, correct. I thought it may be useful to clarify how this works, because "()" insn't really an empty statement or empty side effect...
In F#, every valid piece of code is an expression. Constructs like let and match consist of some keywords, patterns and several sub-expressions. The F# grammar for let and match looks like this:
<expr> ::= let <pattern> = <expr>
<expr>
::= match <expr> with
| <pat> -> <expr>
This means that the body of let or the body of clause of match must be some expression. It can be some function call such as ignore 0 or it can be some value - in your case it must be some expression of type unit, because printfn ".." is also of type unit.
The unit type is a type that has only one value, which is written as () (and it also means empty tuple with no elements). This is, indeed, somewhat similar to void in C# with the exception that void doesn't have any values.
BTW: The following code may look like a sequence of statements, but it is also an expression:
printf "Hello "
printf "world"
The F# compiler implicitly adds ; between the two lines and ; is a sequencing operator, which has the following structure: <expr>; <expr>. It requires that the first expression returns unit and returns the result of the second expression.
This is a bit surprising when you're coming from C# background, but it makes the langauge surprisingly elegant and consise. It doesn't limit you in any way - you can for example write:
if (a < 10 && (printfn "demo"; true)) then // ...
(This example isn't really useful - just a demonstration of the flexibility)
Related
let (->>>) lst exp = for i in lst do exp
let result = [0..5] ->>> ([1..5] ->>> printf "hi")
let result2 = for i in [0..5] do for x in [1..5] do printf "hi"
I was expecting result and result2 to do the same thing. But result prints hi just once. result2, however, prints it 30 times. What is missing here?
In your operator definition, exp is not necessarily a function. The way you defined the operator, exp is any value whatsoever. For example, you could do this:
[0..1] ->>> 42
This would compile and even run, because there is nothing in the definition of your operator that requires the exp parameter to be a function. Or anything else for that matter.
If you want to make exp evaluate over and over within the body of the loop, you need to make it a function and make sure that the body of the loop calls it. Since you don't have any requirements for it, the simplest one would be unit -> 'a. You don't really have to declare its type though, you can have the compiler infer it from its use:
let (->>>) lst exp = for i in lst do exp()
Notice the parentheses after exp - they signify a value of type unit, thus making expression exp() a function application (i.e. function exp applied to value ()).
Of course, with this definition, you won't be able to write [1..5] ->>> printf "hi", because printf "hi" is not a function. So instead you'll have to write:
[1..5] ->>> (fun() -> printf "hi")
Now you'll have five "hi"s printed out.
This is because the for .. do syntax is really a special part of the language, not "just another function" defined in the standard library. You can't really create same effect with clever function or operator definitions.
If you want a way to construct more complicated syntax than functions and operators, check out computation expressions.
It turns out that it is really hard to google the word comment.
Is is possible to represent "comment" expressions in quotations abstract syntax tree?
<# //this gets ignored by the compiler and don't inject the quotation
#>
If not, can you suggest a workaround to represent the comments?
As Ganesh points out, the Expr type has no way of representing comments - the F# quotations really represent just the AST of the expression, rather than full information about the source code (although you can get a file name & a location of a quoted expression).
To somehow embed comments in quotations, you'd need to come up with a way of embedding comments as valid F# code that means something - so you could e.g. define a dummy function comment and do something like this:
let comment (s:string) = ()
let sample =
<# comment "this is not ignored"
1 + ( comment "this is also not ignored"
4 ) #>
Then you could write an active pattern that looks for an expression of the form comment "..."; <expr> and extract the string and the following <expr>:
open Microsoft.FSharp.Quotations
let (|Comment|_|) = function
| Patterns.Sequential(DerivedPatterns.SpecificCall <## comment ##> (None, [], [Patterns.Value(comment, _)]), body) ->
Some(unbox<string> comment, body)
| _ -> None
Using the pattern, we can now write an (incomplete) pattern matching that succeeds when the top-level expression is some commented body expression:
match sample with
| Comment(comment, body) ->
printfn "// %s\n%A" comment body
This is not a very nice way of doing it, but I guess it is as good as it can get if you want to embed some annotations in a hand-written quotation code.
The Expr type that quotations return doesn't contain any way to represent a comment, so this is very unlikely to be possible.
I am looking at the following F# line
for i = 0 to i=10 do
Console.WriteLine("Hello")
An I am wondering that isn't the above line a statement as opposed to an expression?
Shouldn't everything be an expression in F#?
As already said, every syntactical construct in F# is an expression. F# does not distinguish between statements and expressions (and so I'd say that the WikiPedia quote posted by Robert is a bit misleading - F# does not have statements).
Actually, the above is not fully true, because some constructs in F# computation expressions such as let! are not expressions, but we can ignore that.
What does that mean? In C#, the syntax of for and method calls is defined something like this:
statement := foreach(var v in <expression>) <statement>
| { <statement> ... <statement> }
| <expression>;
| (...)
expression := <expression>.<ident>(<expression>, ..., <expression>)
| <literal>
| <expression> + <expression>
| (...)
This is very simplified, but it should give you the idea - a statement is something that does not evaluate to a value. It can be foreach loop (other loops), a statement block (with multiple statements) or an expression with semicolon (where the result of the expression is void or is ignored). An expression is, for example, method call, primitive literal (string, int) or a binary operator.
This means that you cannot write certain things in C# - for example, the argument of method call cannot be a statement (because statements do not evaluate to a value!)
On the other hand, in F#, everything is an expression. This means there is just a single syntactic category:
expression := for v in <expression> do <expression>
| <expression>; <expression>
| <expression>.<ident>(<expression>, ..., <expression>)
| <literal>
| <expression> + <expression>
| (...)
This means that in F# all syntactic constructs are expressions, including for and other loops. The body of for is also an expression, but it would not make sense if the expression evaluated to some value (i.e. 42), so the types require that the result of the body is unit (which does not carry any information). Similarly, the first expression in sequencing (<expr>; <expr>) should return unit - the result of sequencing is the result of the second expression.
This makes the language simpler and more uniform, but you can write some odd things:
let x = (for i in 0 .. 10 do printfn "%d" i); 42
This will print numbers from 0 to 10 and then define a value x to be 42. The assignment is a sequencing of expressions (<expr>; <expr>) where the first one is for loop (that has a type unit, because it does not evaluate to anything) and the second one is 42, which evaluates to 42.
Every statement in F#, including if statements and loops, is a
composable expression with a definite return type.
Functions and expressions that do not return any value have a return
type of unit.
http://en.wikipedia.org/wiki/F_Sharp_(programming_language)
In languages like F# statements are just expressions that return the value () of type unit. As the unit type has only one value it conveys no information so returning the value of type unit is saying "if I'm doing anything then it is by way of a side effect" like printing to the console or writing to disk.
Note that not everything is an expression in F#. Type definitions are not expressions. Patterns are not expressions. And so on...
I found it's very hard to search for the simple indentation guide in F#.
Basically, I am wondering what's the rule for multiple-line statement indentation.
In C#, there is no problem because whitespace doesn't count.
Although I can write F# code according to my intuition and it works, I really want to know what's the rule for breaking one statement into multiple lines.
I write as
printfn "%d"
1
It works as expected
And if I write them in the same column, something goes wrong.
>
printfn "%A%A"
1
[];;
> //nothing is returned... and no error in this case
I want to confirm the basic rule for doing this. It's a little annoying when you can't be sure what you are doing.
Thanks in advance
I just tried another case
List.iter
(printfn "%d")
[1..10];;
And it prints out 1 to 10.
Why it's not
List.iter
((printfn "%d")
[1..10]);;
As Yin points out, the rule is that arguments of a function should be indented further than the call to the function. To add more details, your first snippet is interpreted like this:
printfn "%A%A";
1;
[];
Each of these is a valid expression that returns something (function, number, empty list) and then ignores the result and continues. Because they are written in the top-level scope, F# Interactive doesn't emit a warning that you're ignoring some values. If they were in a do block or let declaration:
do
printfn "%A%A"
1
[]
The F# compiler would emit a warning when sequencing expressions (using ;) that do not return unit:
stdin(5,3): warning FS0193: This expression is a function value, i.e. is missing arguments. Its type is 'a -> 'b -> unit.
stdin(6,3): warning FS0020: This expression should have type 'unit', but has typ
e 'int'. Use 'ignore' to discard the result of the expression, or 'let' to bind
the result to a name.
stdin(5,3): warning FS0020: This expression should have type 'unit', but has typ
e ''a list'. Use 'ignore' to discard the result of the expression, or 'let' to b
ind the result to a name.
In your second example, you should indent:
>
printfn "%A%A"
1
[];;
Otherwise the three expressions are three sequential expressions, not a single expression.
You can refer F# Language Specification for firm rules, e.g. Chapter 15 in the specification.
I've got a simple grammar. Actually, the grammar I'm using is more complex, but this is the smallest subset that illustrates my question.
Expr ::= Value Suffix
| "(" Expr ")" Suffix
Suffix ::= "->" Expr
| "<-" Expr
| Expr
| epsilon
Value matches identifiers, strings, numbers, et cetera. The Suffix rule is there to eliminate left-recursion. This matches expressions such as:
a -> b (c -> (d) (e))
That is, a graph where a goes to both b and the result of (c -> (d) (e)), and c goes to d and e. I'm trying to produce an abstract syntax tree for these expressions, but I'm running into difficulty because all of the operators can accept any number of operands on each side. I'd rather keep the logic for producing the AST within the recursive descent parsing methods, since it avoids having to duplicate the logic of extracting an expression. My current strategy is as follows:
If a Value appears, push it to the output.
If a From or To appears:
Output a separator.
Get the next Expr.
Create a Link node.
Pop the first set of operands from output into the Link until a separator appears.
Erase the separator discovered.
Pop the second set of operands into the Link until a separator.
Push the Link to the output.
If I run this through without obeying steps 2.3–2.7, I get a list of values and separators. For the expression quoted above, a -> b (c -> (d) (e)), the output should be:
A sep_1 B sep_2 C sep_3 D E
Applying the To rule would then yield:
A sep_1 B sep_2 (link from C to {D, E})
And subsequently:
(link from A to {B, (link from C to {D, E})})
The important thing to note is that sep_2, crucial to delimit the left-hand operands of the second ->, does not appear, so the parser believes that the expression was actually written:
a -> (b c -> (d) (e))
In order to solve this with my current strategy, I would need a way to produce a separator between adjacent expressions, but only if the current expression is a From or To expression enclosed in parentheses. If that's possible, then I'm just not seeing it and the answer ought to be simple. If there's a better way to go about this, however, then please let me know!
I haven't tried to analyze it in detail, but: "From or To expression enclosed in parentheses" starts to sound a lot like "context dependent", which recursive descent can't handle directly. To avoid context dependence you'll probably need a separate production for a From or To in parentheses vs. a From or To without the parens.
Edit: Though it may be too late to do any good, if my understanding of what you want to match is correct, I think I'd write it more like this:
Graph :=
| List Sep Graph
;
Sep := "->"
| "<-"
;
List :=
| Value List
;
Value := Number
| Identifier
| String
| '(' Graph ')'
;
It's hard to be certain, but I think this should at least be close to matching (only) the inputs you want, and should make it reasonably easy to generate an AST that reflects the input correctly.