Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Just getting into functional programming and F# with the most appropriately titled Functional Programming Using F#. I wrote the following function definition for problem 2.4 but I'm thinking there's most likely a more elegant and/or idiomatic solution:

let rec occurrencesFromIth = 
    let bool2int x = if x then 1 else 0
    function
    | str:string, i, _ when i >= str.Length -> 0
    | str, i, ch -> 
        isIthChar (str,i,ch ) |> bool2int |> (+) (occurrencesFromIth (str,i+1,ch ))

isIthChar is defined as:

let isIthChar ( str:string, i, ch ) = str.[i] = ch

The actual problem description is:

Declare the F# function occFromIth:

string * int * char -> int where occFromIth(str,i,ch) = the number of occurrences of character ch in positions j in the string str with j >= i.

Hint: the value should be 0 for i >= size str.

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

A simple recursive function would be:

let rec occFromIth s i ch = 
  if i >= String.length s then 0
  else (if s.[i] = ch then 1 else 0) + occFromIth s (i + 1) ch
share|improve this answer
    
Ooh, you can use String.length instead of string.Length to avoid specifying the type, nice. –  svick Sep 17 '13 at 15:43
    
first answer, simpler than mine, and uses recursion which is in the spirit of the current book chapter and exercises so gets the answer check. –  hejoco Sep 18 '13 at 2:24
add comment

First of all, I think that your isIthChar function is an overkill: it usually doesn't make sense to write a function that's that short.

To write the occurrencesFromIth itself, I would use sequence expression to generate the indexes to test and then use Seq.sumBy to count the matching characters:

let occurrencesFromIth (str : string, start, ch) =
    seq { start .. str.Length - 1 } |>
        Seq.sumBy (fun i -> if str.[i] = ch then 1 else 0)

I would prefer to use something like Seq.count even more, but there is no such method. You could use Count() from LINQ, which makes the code shorter, but I guess that is less idiomatic (and means you can't use |>):

let occurrencesFromIth (str : string, start, ch) =
    let indexes = seq { start .. str.Length - 1 }
    indexes.Count (fun i -> str.[i] = ch)
share|improve this answer
    
You could use Seq.sumBy (fun i -> if str.[i] = ch then 1 else 0) in place of fold. –  Daniel Sep 17 '13 at 15:21
    
@Daniel Yeah, that's better, edited in. –  svick Sep 17 '13 at 15:38
    
if could check two answers would check this one also. More functional/declarative in my novice opinion. Gotta learn me some Seq but that is in a few more chapters. (The reason for the isIthChar function is that it was the answer to the previous exercise so reuse was implied - but that doesn't matter, your criticism is valid in general) –  hejoco Sep 18 '13 at 2:29
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.