I guess this is one good way:

1
2
3
4
5
6
7
8
9
10
let convertTo7bit (value:int) =
    Seq.unfold (fun i ->
        if i=0u then 
            None 
        else
            let by = byte(i ||| 0x80u)
            let nextI = i >>> 7
            Some(by, nextI)
    ) (uint32 value)
    |> Seq.toList 

Typically turning a single value into a sequence of values is done by Seq.unfold

[link:msdn.microsoft.com]

By on 5/9/2010 3:17 PM ()

thanks for that Brian, I havent yet looked at Seq.unfold so thats very interesting

The code I posted was simplified as I assumed a list would be easier to deal with, In my current code I write to a stream returning the number of bytes written, from a performance point of view it would be nice to write direct to the stream rather than having to loop through the list...

By on 5/9/2010 3:57 PM ()

I managed to tweak the code to this and its now doing what I wanted, are there any optimizations that I could do?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let convertTo7bit value =
    Seq.unfold (fun i ->
        if i = 0 then 
            None 
        else
            let shifted = i >>> 7
            let lower = 
                match shifted with
                | shifted when shifted > 0 -> (i &&& 0x7f) ||| 0x80
                | _ -> i &&& 0x7f
                
            Some(lower, shifted)
    ) value
    |> Seq.toList 
By on 5/11/2010 3:08 AM ()

Here's a tail recursive version that calls an arbtrary function on each value. (I think I'm interpreting the problem right?)

1
2
3
4
5
6
7
8
9
10
let convertTo7Bit s i =
  let rec f (s:byte->unit) u = 
    match u>=0x80u with
    | false -> s (byte u)
    | true -> 
      s (byte(u|||0x80u))
      f s (u>>>7)
  f s (uint32 i)

convertTo7Bit (System.Console.WriteLine) 0x6f7f

-Neil

By on 5/11/2010 7:11 AM ()

I think thats functionally what I want (no pun intended :) )

How would I go about using the pipeline operator to test an array of ints with these functions outputting each item to the console?

Do I have to modify the signature of the convertTo7bit ?

Cheers

Dave.

By on 5/12/2010 4:04 PM ()

>> Do I have to modify the signature of the convertTo7bit?

You don't have to, but if I were going to use the pipeline I probably would modify it to something more composable like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 

let convertTo7Bit i =
  let rec convertTo7Bit' l u = 
    match u>=0x80u with
    | false ->  (byte u)::l
    | true -> 
      convertTo7Bit' ((byte(u|||0x80u))::l) (u>>>7)
  List.rev (convertTo7Bit' [] (uint32 i))


let rec writeIt = function
  | [] -> printfn ""
  | h::t ->
    printf "%A " h
    writeIt t


let a = [| 0x0; 0x1; 0xFF; 0x6f7f3b |]

a |> Array.map convertTo7Bit |> Array.iter writeIt

You could use sequences instead of arrays as well.

-Neil

By on 5/14/2010 7:51 AM ()

In the last example, I put in the "writeIt" function as a place where you could add custom formatting. Here is a version that uses standard printing and sequences. The sequence should prevent the creation of an intermediate array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 

let convertTo7Bit i =
  let rec convertTo7Bit' l u = 
    match u>=0x80u with
    | false ->  (byte u)::l
    | true -> 
      convertTo7Bit' ((byte(u|||0x80u))::l) (u>>>7)
  List.rev (convertTo7Bit' [] (uint32 i))


let a = [| 0x0; 0x1; 0xFF; 0x6f7f3b |]

a |> Array.toSeq 
  |> Seq.map convertTo7Bit 
  |> Seq.iter (printfn "%A")
By on 5/14/2010 9:51 AM ()

Thanks for the info, Im still learning at the moment so its a bit of a struggle comping from a strictly imperative programming.

why was the resulting List reversed?

By on 5/14/2010 5:17 PM ()

>>its a bit of a struggle comping from a

>>strictly imperative programming

In F#, it can be particularly tough, since it supports multiple paradigms. Writing an F# program can be like a conversation between two multi-lingual people: slipping in and out of various languages even within sentences, lol.

>>why was the resulting List reversed?

Nothing arcane; for some odd reason, I thought that was the order the results were wanted in. Looking back over the thread, I don’t see any evidence for my assumption. Chalk it up to spring fever, lol. Remove the List.rev if the opposite order is OK.

-Neil

By on 5/15/2010 8:06 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper