What is the purpose of the # operator, called the stringizer operator,
and how can it be used?
My book describes # in the following way, the bald part is what I do not understand.
The stringizer operator # must be followed by a parameter and they are replaced with a string literal contructed from the argument's tokens, which are not first replaced That is, the following input:
#define W 124
#define str(a) (#a)
str(W)
produces the output:
"W"
If we would like to have a string literal with the definition of a macro, we must use two function-like macros:
#define W 124
#define xstr(a) (#a)
#define str(b) (xstr(b))
which produces the output
"124"
The reason for this is that the argument of the parameter b is completely replaced before the parameter is replaced in the replacement-list of str, which means that the invocation of xstr will use 124 as the argument which is then stringized in xstr
So to understand this, think of how the preprocessor will treat these things. In the first example we can see that
#define W 124
#define str(a) (#a)
str(W)
would get processed as follows str(W) -> #W -> "W".
Now if we take the second example this
#define W 124
#define xstr(a) (#a)
#define str(b) (xstr(b))
str(W)
Would be processed as follows: str(W) -> xstr(124) -> #124 and finally "124"
#a forces the compiler to put the value of a, which in this case is a macro argument, in double quotes. This quoting of the string happens before substitution within the macro. Thus you get the "W".
You can see this by passing your source through the C preprocessor; you do not need to have a valid C program here. On Linux hosts, ignoring the "#" and blank line fluff produced by cpp, we get:
cpp macro-strings.c
("W")
Adding a level of indirectness allows the expansion the value of W. Since there is no "#" in the outer macro the substitutions occurs within that macro before the inner macro is expanded, which creates the string.
If you comment out the xstr definition it may become more visual:
#define W 124
/* #define xstr(a) (#a) */
#define str(b) (xstr(b))
cpp macro-strings.c
(xstr(124))
Removing the comment produces the proper (("124"))
And do remember, that adjacent double-quoted strings are combined by the compiler into a single string:
"Hello," " " "world!" is the same as "Hello, world!"
This can become quote important when one or more strings are generated within macros.
If time is not that much an issue, understanding often comes from a "do it yourself" approach. Here, if the question is "what is preprocessor doing?", why not write a simplified toy-preprocessor and study the results. I forgot the name, but there is a "law", saying "You only really understood if you can implement it".
Of course, writing a full fledged C/C++ preprocessor is not really attractive. So, the following code tries to get a sufficiently large, yet minimalist implementation of a simplified model, which is just so able to showcase what is basically going on. A compact language has been chosen to keep the line count low. No parser is needed if you resort to abstract syntax tree level instead of using a syntax.
type MacroExpr =
| MacroDef of string * string list * MacroExpr
| MacroCall of string * (string * MacroExpr) list
| String of string
| Stringize of MacroExpr
| ArgRef of string
let rec run (macros : MacroExpr list) (call : MacroExpr) : MacroExpr =
let value_of arg_name =
match call with
| MacroCall(n,args) -> snd (List.find (fun a -> fst a = arg_name) args)
| _ -> failwith "bla bla"
match call with
| MacroCall(n,al) ->
let m = macros |> List.find (fun m -> match m with | MacroDef(n1,_,_) -> n1 = n | _ -> false)
let mname,margs,mbody =
match m with
| MacroDef(a,b,c) -> a,b,c
| _ -> failwithf "macros argument contains something else: %A" m
let rec x_to_string = function
| String s -> s
| Stringize x -> x_to_string x
| ArgRef(an) -> x_to_string (eval (snd(al |> List.find (fun (n,_) -> n = an))))
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,_) -> n
and eval = function
| String s -> String s
| Stringize x -> String (x_to_string x)
| ArgRef(an) -> String (x_to_string (snd(al |> List.find (fun (n,_) -> n = an))))
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,al1) ->
run macros (MacroCall(n, al1 |> List.map (fun (an,ax) -> an,eval ax)))
match mbody with
| ArgRef(an) -> snd(al |> List.find (fun (n,_) -> n = an))
| Stringize(x) -> String(x_to_string x)
| String s -> String s
| MacroCall(mn,al1) ->
run macros (MacroCall(mn, al1 |> List.map (fun (an,ax) -> an,eval ax)))
| MacroDef(_,_,_) -> failwithf "No nested macros supported. Found one in %s: %A" n mbody
| _ -> failwithf "'call' argument shall be a MacroCall expression but is a %A" call
let macros =
[
MacroDef ("W", [], String "124")
MacroDef ("str1", ["a"], Stringize (ArgRef "a"))
MacroDef ("str2", ["a"], MacroCall("str1", ["a",ArgRef "a"]))
]
let calls =
[
MacroCall("W",[])
MacroCall("str1",["a",MacroCall("W",[])])
MacroCall("str2",["a",MacroCall("W",[])])
]
calls
|> List.map (fun c -> run macros c)
The macros variable contains the list of predefined macros we want to explore. They are defined in terms of the (minimal, low tech) MacroExpr type.
The calls variable contains a list of macro invocations, using the same technique.
Even if we ignore the implementation of the function run for now, we see something interesting:
The macro definition for "str2" forwards its argument 'a' to a macro call to str1. An ArgRef - a reference to the argument list of "str2". Languages which follow the eager evaluation principle will not pass that ArgRef down to the next macro evaluation but instead attempt to resolve it first. After all, else the evaluation of "str1" would have to know about the arglist of the caller "str2".
Hence, the argument for the call of str1 from str2 is ["a",MacroCall("W",[])], whereas a direct invocation of macro str1 with ["a",MacroCall("W",[])] is first resolved by evaluating the macro "W" to String "124".
The last 2 lines in the code run all calls and the results yielded are not as expected:
val it : MacroExpr list = [String "124"; String "124"; String "W"]
Now, as an exercise, you could try to change the run function such, that it behaves as the c preprocessor does. Tip: sub-functions x_to_string and eval are the culprits ;)
The fixed version of those 2 sub-functions is:
let rec x_to_string = function
| String s -> s
| Stringize x -> x_to_string x
| ArgRef(an) -> x_to_string ( (*eval*) (snd(al |> List.find (fun (n,_) -> n = an)))) // disabled eval
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,_) -> n
and eval = function
| String s -> String s
| Stringize x -> String (x_to_string x)
| ArgRef(an) -> String (x_to_string (eval (snd(al |> List.find (fun (n,_) -> n = an))))) // added eval
| MacroDef(_,_,_) -> failwith "No nested macros supported."
| MacroCall(n,al1) ->
run macros (MacroCall(n, al1 |> List.map (fun (an,ax) -> an,eval ax)))
... and now the result is as expected:
val it : MacroExpr list = [String "124"; String "W"; String "124"]
Related
I am working on a program where the user can send me all sort of objects at runtime, and I do not know their type in advance (at compile time). When the object can be down-cast to an (F#) array, of any element type, I would like to perform some usual operations on the underlying array. E.g. Array.Length, Array.sub...
The objects I can get from the users will be of things like box [| 1; 2; 3 |] or box [| "a"; "b"; "c" |], or any 'a[], but I do not know 'a at compile time.
The following does not work :
let arrCount (oarr: obj) : int =
match oarr with
| :? array<_> as a -> a.Length
| :? (obj[]) as a -> a.Length
// | :? (int[]) as a -> a.Length // not an option for me here
// | :? (string[]) as a -> a.Length // not an option for me here
// | ...
| _ -> failwith "Cannot recognize an array"
E.g both arrCount (box [| 1; 2; 3 |]) and arrCount (box [| "a"; "b"; "c" |]) fail here.
The only solution I found so far is to use reflection, e.g. :
type ArrayOps =
static member count<'a> (arr: 'a[]) : int = arr.Length
static member sub<'a> (arr: 'a[]) start len : 'a[] = Array.sub arr start len
// ...
let tryCount (oarr: obj) =
let ty = oarr.GetType()
if ty.HasElementType && ty.BaseType = typeof<System.Array> then
let ety = ty.GetElementType()
let meth = typeof<ArrayOps>.GetMethod("count").MakeGenericMethod([| ety |])
let count = meth.Invoke(null, [| oarr |]) :?> int
Some count
else
None
My question: is there a way to use functions such as Array.count, Array.sub, etc... on arguments of the form box [| some elements of some unknown type |] without using reflection?
Since F# is statically type-safe it tries to prevent you from doing this, which is why it isn't trivial. Casting it to an array<_> will not work because from an F# standpoint, array<obj> is not equal to array<int> etc, meaning you would have to check for every covariant type.
However, you can exploit the fact that an array is also a System.Array, and use the BCL methods on it. This doesn't give you Array.length etc, because they need type-safety, but you can essentially do any operation with a little bit of work.
If you do have a limited set of known types that the obj can be when it is an array, I suggest you create a DU with these known types and create a simple converter that matches on array<int>, array<string> etc, so that you get your type-safety back.
Without any type safety you can so something like this:
let arrCount (x: obj) =
match x with
| null -> nullArg "x cannot be null"
| :? System.Array as arr -> arr.GetLength(0) // must give the rank
| _ -> -1 // or failwith
Usage:
> arrCount (box [|1;2;3|]);;
val it : int = 3
> arrCount (box [|"one"|]);;
val it : int = 1
This other answer on SO has a good way of explaining why allowing such casts makes the .NET type system unsound, and why it isn't allowed in F#: https://stackoverflow.com/a/7917466/111575
EDIT: 2nd alternative
If you don't mind boxing your entire array, you can expand on the above solution by converting the whole array, once you know it is an array. However, the first approach (with System.Array) has O(1) performance, while this approach is, necessarily, O(n):
open System.Collections
let makeBoxedArray (x: obj) =
match x with
| null -> nullArg "x cannot be null"
| :? System.Array as arr ->
arr :> IEnumerable
|> Seq.cast<obj>
|> Seq.toArray
| _ -> failwith "Not an array"
Usage:
> makeBoxedArray (box [|1;2;3|]);; // it accepts untyped arrays
val it : obj [] = [|1; 2; 3|]
> makeBoxedArray [|"one"|];; // or typed arrays
val it : obj [] = [|"one"|]
> makeBoxedArray [|"one"|] |> Array.length;; // and you can do array-ish operations
val it : int = 1
> makeBoxedArray (box [|1;2;3;4;5;6|]) |> (fun a -> Array.sub a 3 2);;
val it : obj [] = [|4; 5|]
Curiously, this is a non-issue in languages like C# and VB, while you may have to do some extra work for F#. You can't do this in general, because F# doesn't have co-variant types.
Vote for that feature here!.
But we do have flexible types which give us rather limited contra-variance, which we can work with.
let anyLength (arr : #obj[]) =
arr |> Array.length
And,
let iarr = [| 1; 2; 3|]
let sarr = [|"a"; "b" |]
anyLength iarr // 3
anyLength sarr // 2
I'm a newbie at F#,
I've got a List that contains arrays, each arrays contains 7 Strings.
I want to loop through the Arrays and do some kind of Array.map later on,
However my problem is that I can't send individual arrays to some other function.
I don't want to use for-loops but focus on the functional way using pipelines and mapping only.
let stockArray =
[[|"2012-03-30"; "32.40"; "32.41"; "32.04"; "32.26"; "31749400"; "32.26"|];
[|"2012-03-29"; "32.06"; "32.19"; "31.81"; "32.12"; "37038500"; "32.12"|];
[|"2012-03-28"; "32.52"; "32.70"; "32.04"; "32.19"; "41344800"; "32.19"|];
[|"2012-03-27"; "32.65"; "32.70"; "32.40"; "32.52"; "36274900"; "32.52"|];]
let tryout =
stockArray
|> List.iter;;
Output complains about List.iter:
error FS0001: Type mismatch. Expecting a
'string [] list -> 'a' but given a
'('b -> unit) -> 'b list -> unit'
The type 'string [] list' does not match the type ''a -> unit'
When trying Array.iter, same difference:
error FS0001: Type mismatch. Expecting a
'string [] list -> 'a' but given a
'('b -> unit) -> 'b [] -> unit'
The type 'string [] list' does not match the type ''a -> unit'
In C# I would simply go about it with a foreach to start treating my arrays one at a time, but with F# I feel real stuck.
Thank you for your help
The question is not clear, even with the extra comments. Anyway, I think you will finally be able to figure out your needs from this answer.
I have implemented parseDate and parseFloat in such a way that I expect it to work on any machine, whatever locale, with the given data. You may want something else for your production application. Also, how theInt is calculated is perhaps not what you want.
List.iter, as you already discovered, converts data to unit, effectively throwing away data. So what's the point in that? It is usually placed last when used in a pipe sequence, often doing some work that involves side effects (e.g. printing out data) or mutable data operations (e.g. filling a mutable list with items). I suggest you study functions in the List, Array, Seq and Option modules, to see how they're used to transform data.
open System
open System.Globalization
let stockArray =
[
[| "2012-03-30"; "32.40"; "32.41"; "32.04"; "32.26"; "31749400"; "32.26" |]
[| "2012-03-29"; "32.06"; "32.19"; "31.81"; "32.12"; "37038500"; "32.12" |]
[| "2012-03-28"; "32.52"; "32.70"; "32.04"; "32.19"; "41344800"; "32.19" |]
[| "2012-03-27"; "32.65"; "32.70"; "32.40"; "32.52"; "36274900"; "32.52" |]
]
type OutData = { TheDate: DateTime; TheInt: int }
let parseDate s = DateTime.ParseExact (s, "yyyy-MM-dd", CultureInfo.InvariantCulture)
let parseFloat s = Double.Parse (s, CultureInfo.InvariantCulture)
let myFirstMap (inArray: string[]) : OutData =
if inArray.Length <> 7 then
failwith "Expected array with seven strings."
else
let theDate = parseDate inArray.[0]
let f2 = parseFloat inArray.[2]
let f3 = parseFloat inArray.[3]
let f = f2 - f3
let theInt = int f
{ TheDate = theDate; TheInt = theInt }
let tryout =
stockArray
|> List.map myFirstMap
The following is an alternative implementation of myFirstMap. I guess some would say it's more idiomatic, but I would just say that what you prefer to use depends on what you might expect from a possible future development.
let myFirstMap inArray =
match inArray with
| [| sDate; _; s2; s3; _; _; _ |] ->
let theDate = parseDate sDate
let f2 = parseFloat s2
let f3 = parseFloat s3
let f = f2 - f3
let theInt = int f
{ TheDate = theDate; TheInt = theInt }
| _ -> failwith "Expected array with seven strings."
The pipe operator |> is used to write an f x as x |> f.
The signature of List.iter is:
action: ('a -> unit) -> list: ('a list) -> unit
You give it an action, then a list, and it gives you a void.
You can read it thus: when you give List.iter an action, its type will be
list: ('a list) -> unit
a function to which you can pass a list.
So when you write stockArray |> List.iter, what you're actually trying to give it in place of an action is your list - that's the error. So pass in an action:
let tryout = List.iter (fun arr -> printfn "%A" arr) stockArray
which can be rewritten as:
let tryout = stockArray |> List.iter (fun arr -> printfn "%A" arr)
However my problem is that I can't send individual arrays to some other function
List.map and similar functions allow you to do precisely this - you don't need to iterate the list yourself.
For example, this will return just the first element of each array in your list:
stockArray
|> List.map (fun x -> x.[0])
You can replace the function passed to List.map with any function that operates on one array and returns some value.
Im trying to create a calculator in f# using two arrays, one which stores the numbers and the other to store the operator symbols. I need the symbols array to pattern match the symbol and depending on the operator take the first two elements from the array and do the operation and add the new number into the head of the 2nd array.
open System
[<EntryPoint>]
let main argv =
printfn "%A" argv
let Add x y = x + y
let Sub x y = x - y
let Div x y = x * y
let Mul x y = x / y
printfn "1 > Calculator \n2 > Load from txt file"
let chosenIn = Console.ReadLine();
//This is where I need to do the operation and after call the sum function
//again until there's only one element left in the number array
let rec sum num (numArray : int[]) sym (symArray : string[]) () =
let rec calc () =
printfn "Enter Sum"
let input = Console.ReadLine()
let intInput = input.Split()
let numArray = [|for num in intInput do
let v , vp = System.Int32.TryParse(num)
if v then yield vp|]
let symbolArray = [|for symbol in intInput do
match symbol with
| "+" -> yield symbol
| "-" -> yield symbol
| "/" -> yield symbol
| "*" -> yield symbol
| _ -> ignore 0|]
calc()
match chosenIn with
| "1" -> calc()
| "2" -> printfn "File"
| _ -> printfn "Invalid"
0 // return an integer exit code
In response to the answer #Liam Donnelly posted to his own question: I'll leave aside questions like "is that really the best way of solving the problem", just commenting on how to better write the code you currently have.
Array slicing and concatenating the way you are doing it here can be written as
let newNumArray = Array.append [| result |] numArray.[2..]
However, I would use F# lists rather than arrays for your task. With lists, you can do pattern matching to access the first 2 elements. Pattern matching, in my view, wins over direct indexing because you can directly encode corner cases, and get the F# compiler to remind you of corner cases. Do the same thing for the operators. You can do both operators and operands in the same go. It will then look something like this:
let rec sum2 (numArray : int list) (symArray : string list) =
let newNum, newSym =
match numArray with
| [] -> failwith "No numbers left to process"
| arg1 :: [] -> failwith "There's only one number left to process"
| arg1 :: arg2 :: args ->
match symArray with
| op1 :: ops ->
let result =
match op1 with
| "+" -> Add arg1 arg2
| "-" -> Sub arg1 arg2
| "*" -> Mul arg1 arg2
| _ -> failwithf "Operator not recognized: '%s'" op1
// Return the result, concatenate the non-processed
// numbers. Return the non-processed operators
result :: args, ops
| _ -> failwith "I've run out of operators?"
<snip>
Also, returning a "default result" if you don't recognize the operators is something that I consider very risky (even though the practice is rather widespread)
If you use lists (F# lists, that is), you can directly access the elements at indices 1.. via head: let newSymArray = symArray.Head or use List.head
Take a step back each time you see yourself writing a for loop in F#. They are cumbersome to write and error-prone. Most of the typical use-cases for loops are covered by F# library functions, so have a good read through those. Your printing loop can be written way shorter by doing:
newNumArray
|> Seq.iter (printfn "%i")
I've managed to make the function which performs the task I needed for it to do and I'm sure there's a much more code efficient way of taking the first elements of the arrays by using Array.copy with filters but I'm new to f# so I just it the way I was confident with
let rec sum (numArray : int[]) (symArray : string[]) =
let result = match symArray.[0] with
| "+" -> Add numArray.[0] numArray.[1]
| "-" -> Sub numArray.[0] numArray.[1]
| "*" -> Mul numArray.[0] numArray.[1]
| _ -> 0
let newNumArray = [|
for i = 0 to numArray.Length - 1 do
if i = 0 then yield result
if i > 1 then yield numArray.[i]|]
let newSymArray = [|
for i = 0 to symArray.Length - 1 do
if i > 0 then yield symArray.[i]|]
if newNumArray.Length > 1 then
sum newNumArray newSymArray
else
for i = 0 to newNumArray.Length - 1 do
printfn "%i" (newNumArray.[i])
let x=[|15..20|]
let y=Array.map f x
printf "%O" y
Well, I got a type information.
Is there any way to print each element of "y" with delimiter of ",", while not having to use a for loop?
Either use String.Join in the System namespace or F# 'native':
let x = [| 15 .. 20 |]
printfn "%s" (System.String.Join(",", x))
x |> Seq.map string |> String.concat "," |> printfn "%s"
Using String.concat to concatenate the string with a separator is probably the best option in this case (because you do not want to have the separator at the end).
However, if you just wanted to print all elements, you can also use Array.iter:
let nums= [|15..20|]
Array.iter (fun x -> printfn "%O" x) nums // Using function call
nums |> Array.iter (fun x -> printfn "%O" x) // Using the pipe
Adding the separators in this case is harder, but possible using iteri:
nums |> Array.iteri (fun i x ->
if i <> 0 then printf ", "
printf "%O" x)
This won't print the entire array if it is large; I think it prints only the first 100 elements. Still, I suspect this is what you're after:
printfn "%A" y
If the array of items is large and you do not want to generate a large string, another option is to generate a interleaved sequence and skip the first item. The following code works assuming the array has at least one element.
One advantage of this approach is that it cleanly separates the act of interleaving the items and that of printing. It also eliminates having to do a check for the first item on every iteration.
let items = [| 15 .. 20|]
let strInterleaved delimiter items =
items
|> Seq.collect (fun item -> seq { yield delimiter; yield item})
|> Seq.skip(1)
items
|> Seq.map string
|> strInterleaved ","
|> Seq.iter (printf "%s")
I have an array like this,
[|{Name = "000016.SZ";
turnover = 3191591006.0;
MV = 34462194.8;};
{Name = "000019.SZ";
turnover = 2316868899.0;
MV = 18438461.48;};
{Name = "000020.SZ";
turnover = 1268882399.0;
MV = 7392964.366;};
.......
|]
How do I sort this array according to "turnover"? Thanks
(does not have much context to explain the code section? how much context should I write)
Assuming that the array is in arr you can just do
arr |> Array.sortBy (fun t -> t.turnover)
I know this has already been answered beautifully; however, I am finding that, like Haskell, F# matches the way I think and thought I'd add this for other novices :)
let rec sortData =
function
| [] -> []
| x :: xs ->
let smaller = List.filter (fun e -> e <= x) >> sortData
let larger = List.filter (fun e -> e > x) >> sortData
smaller xs # [ x ] # larger xs
Note 1: "a >> b" is function composition and means "create a function, f, such that f x = b(a(x))" as in "apply a then apply b" and so on if it continues: a >> b >> c >>...
Note 2: "#" is list concatenation, as in [1..100] = [1..12] # [13..50] # [51..89] # [90..100]. This is more powerful but less efficient than cons, "::", which can only add one element at a time and only to the head of a list, a::[b;c;d] = [a;b;c;d]
Note 3: the List.filter (fun e ->...) expressions produces a "curried function" version holding the provided filtering lambda.
Note 4: I could have made "smaller" and "larger" lists instead of functions (as in "xs |> filter |> sort"). My choice to make them functions was arbitrary.
Note 5: The type signature of the sortData function states that it requires and returns a list whose elements support comparison:
_arg1:'a list -> 'a list when 'a : comparison
Note 6: There is clarity in brevity (despite this particular post :) )
As a testament to the algorithmic clarity of functional languages, the following optimization of the above filter sort is three times faster (as reported by VS Test Explorer). In this case, the list is traversed only once per pivot (the first element) to produce the sub-lists of smaller and larger items. Also, an equivalence list is introduced which collects matching elements away from further comparisons.
let rec sort3 =
function
| [] -> []
| x::xs ->
let accum tot y =
match tot with
| (a,b,c) when y < x -> (y::a,b,c)
| (a,b,c) when y = x -> (a,y::b,c)
| (a,b,c) -> (a,b,y::c)
let (a,b,c) = List.fold accum ([],[x],[]) xs
(sort3 a) # b # (sort3 c)