I thought I understood F# code execution but clearly I'm missing something. When I run the following
#!/usr/bin/env fsharpi
let a =
System.Console.WriteLine("Function A")
let b =
System.Console.WriteLine("Function B")
let c =
System.Console.WriteLine("Function C")
c
b
a
I get the output:
Function A
Function B
Function C
So for some reason it's executing the functions as it reads them in instead of the function calls which are in reverse order.
Why is this?
I think you're misunderstanding what this line means:
let a =
System.Console.WriteLine("Function A")
It assigns the result of System.Console.WriteLine("Function A") to a. If you run it you'll see a is typed as unit:
val a : unit = ()
And at that time "Function A" was already written to console.
What you probably want is a to be a function and not a value:
let a() =
System.Console.WriteLine("Function A")
It can be called using a(). If you put that all together:
let a() =
System.Console.WriteLine("Function A")
let b() =
System.Console.WriteLine("Function B")
let c() =
System.Console.WriteLine("Function C")
c()
b()
a()
you'll get what you expect:
Function C
Function B
Function A
Related
I have the following scenario in which the position of code shall not change. How to modify this code to fix the error without moving the function and table variable. I am a Lua newbie, just 4 days
function a()
print("function a");
end
ftable = {
["a"] = a,
["b"] = b
};
function b()
print("function b");
end
ftable["a"](); -- prints 'function a'
ftable["b"](); -- attempt to call field 'b' (a nil value)
Update : Using the following mechanism its possible to do this.
function a()
print("function a");
end
ftable = {
["a"] = a,
["b"] = "b"
};
function b()
print("function b");
end
ftable["a"](); -- prints 'function a'
_G[ftable["b"]]();
Lua's table declaration and function definition (and function calling syntax) is very flexible. You can use the field key as an identifier instead of the index syntax, provided that the key is a string and is also a valid identifier ({ a = a } and ftable.a()). This seems to be the case with your a and b keys. You can also make the field assignment with the function definition statement (function ftable.b…).
function a()
print("function a")
end
ftable = {
a = a
}
function ftable.b()
print("function b")
end
ftable.a() -- prints 'function a'
ftable.b() -- prints 'function b'
Of course, you could also move "function a" down and code it like "function b". that would leave ftable = { } at the top.
One difference from your code. The global variable b is no longer set to the function. In most cases, this would be considered an advantage.
I would also like to re-iterate what #lhf said,
There are no declarations in Lua, only definitions.
A function definition (in the general case) is an expression. When evaluated, it produces a function value. Various types of statements can assign the value to a variable or field, as does function ftable.b()….
You can't do that. There are no declarations in Lua, only definitions. You need to define variables before using them.
What you can do is to register the names of the functions in ftable and then fix the values before using them:
ftable = {
["a"] = true,
["b"] = true,
}
...
for k,v in pairs(ftable) do ftable[k]=_G[k] end
This code assumes that your functions are defined globally.
I have the following code snippet using the reactive extensions:
let value : 't = ...
Observable.Create<'t>(fun observer ->
let subject = new BehaviorSubject<'t>(value)
let d0 = subject.Subscribe(observer)
let d1 = observable.Subscribe(subject)
new CompositeDisposable(d0, d1) :> IDisposable
)
This works. However if I drop the upcast to IDisposable then the code fails
to compile, citing ambiguous overloads. However CompositeDisposable is an
IDisposable. Why is the type inference engine failing to resolve this? Note I use this pattern almost all the time in C# returning CompositeDisposable from Observable.Create without having to upcast.
As #kvb said, functions don't support variance so upcast is required for interfaces and subclasses.
Here is a small example demonstrating the behavior with subclasses:
type A() =
member x.A = "A"
type B() =
inherit A()
member x.B = "B"
let f (g: _ -> A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // fails
If function f is written by you, adding type constraints could help:
// This works for interface as well
let f (g: _ -> #A) = g()
let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // works
Otherwise, you have to do a litle upcast as your example described.
EDIT: Since F# 6.0, auto-upcasting of interfaces and subclasses is now supported by default.
I want to implement a F# function which may accept 1 or 2 arguments. I would like to use the function like this:
let foo = ...
foo "a"
foo "a" "b"
Both the arguments can be the same type. I read the pages about match pattern, active pattern, but cannot find one works for me.
I believe this is due to some of the underlying .Net features, but I think you have to use a class with overloaded methods - something like
type t() =
static member foo a = "one arg"
static member foo (a,b) = "two args"
On a type member, you can use optional params:
type Helper private () =
static member foo (input1, ?input2) =
let input2 = defaultArg input2 "b"
input1, input2
To call this method:
Helper.foo("a")
Helper.foo("a", "b")
Is this what you're after?
You can't use optional params on a function though, unfortunately.
In addition to the other answers, here are a few more "almost solutions". They are not strictly what you wanted, but are worth knowing anyway.
Using a list (or an array) and pattern matching:
let f = function
| [a, b] -> ...
| [a] -> ...
| [] -> failwith "too few arguments"
| _ -> failwith "too many arguments"
f ["a"]
f ["a" ; "b"]
Problems: parameters are not named, not clear from function signature how many parameters it takes.
Using a record to pass all optional parameters:
type FParams = { a : string; b : string }
let fdefault = { a = "a" ; b = "b" }
let f (pars: FParams) = ...
f { fdefault with b = "c" }
Problem: a is also optional, which is not what you wanted. Can be useful though.
In addition to the other answers, you might also be able to do what you want via partial application and currying. Like this:
let foo a b =
a + b
let foo2 a =
foo 1 a;;
Obviously you'd want to fix the first parameter in the call to foo within foo2 to whatever default you want.
This is probably something simple, but I have a .fs file with a simple sample function.
let printHello = printfn "%A" "Hello"
I have set the search path to the .fs file using
>#I "PathToMyFSFile"
I have loaded my file using
>#load "Test.fs"
Which worked fine. Now I want to call the function which actually prints the hello to screen, but thats turning out to be too difficult
> Test.printHello;;
val it : unit = ()
Tried Test.printHello();; as well but doesn't work. How do I actually make it print "Hello" to screen?
your current printHello isn't actually a function. To make it a function you need to do
let printHello() = printfn "%A" "Hello"
noice the (). Then everything should work.
EDIT:
When the compiler sees your definition
let printHello = printfn "%A" "Hello"
it passes it as a simple data term. For example, consider this program:
let printHello = printfn "%A" "Hello"
printfn "World"
printHello
This will print "Hello" then "World". printHello just has unit type, so does nothing. Compare it to
let printHello() = printfn "%A" "Hello"
printfn "World"
printHello()
Here printHello is a function. In this case, the function is only executed when it is explicitly called, so this prints "World" then "Hello".
As John already said, your printHello isn't a function - it is a value of type unit. When you give printfn all the required arguments (as you did), it does the imperative operation and return unit (which is a type with only a single value written as ()). You can see that writing that declaration does the printing immediately:
> let printHello = printfn "%A" "Hello";;
"Hello"
val printHello : unit = ()
When you use printHello later, it simply refers to this unit value (which does not carry any information).
If you want to make it a function (of type unit -> unit) that will do something each time it is executed, then you can use the sample that John posted.
The function printfn was not partially applied, because you gave it all the parameters it required (so it could just print immediately). If you wanted to use partial application, you could use something like:
> let printHello = printfn "%s %s" "Hello";; // Note - didn't give value for second %s
val printHello : string -> unit
Now printHello is a function that waits for the second parameter and then runs:
> printHello "World";;
Hello World
val it : unit = ()
> printHello "F#";;
Hello F#
val it : unit = ()
As has already been said in other answers, "printHello" set to () is unit, the return value of printfn is () , console print is side-effect.
use Lazy:
let printHello = Lazy (fun () ->printfn "%A" "Hello")
DEMO
> Test.printHello.Value;;
"Hello"
val it : unit = ()
> Test.printHello.Value;;
val it : unit = () //only once
use Seq:
let printHello = seq { printfn "%A" "Hello"; yield ()}
DEMO
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null]
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null] //many times
Why does this compile:
let (|T|F|) b =
let f (o:int) : obj = null
if b then T else F(f)
while this fails:
let (|T|F|) b =
let f (o:obj) : obj = null
if b then T else F(f)
The difference between the two examples is the argument 'o' is coerced to either an 'int' (compiles) or an 'obj' (fails to compile)
It's an unfortunate type inference corner case. This will work:
let (|T|F|) b : Choice<unit,obj -> obj> =
let f (o:obj) : obj = null
if b then T else F(f)
In your original code, despite your annotation (o:obj), F# infers that o could actually be of any type 'a, which leads to a generic active pattern of type bool -> Choice<unit,'a -> obj>. Because 'a is a free type variable, F# won't accept this active pattern definition. You can see a similar problem if you do something like:
let (|T|F|) b =
if b then T else F []
Again, the solution would be to monomorphize the definition:
let (|T|F|) b : Choice<unit,int list> =
if b then T else F []