Carrington Cooper
Carrington Cooper

Reputation: 19

Using nested functions to find product of numbers

I need to make a function that given natural number n, calculates the product of the numbers below n that are not divisible by 2 or by 3 im confused on how to use nested functions in order to solve this problem (also new to sml ) here is my code so far

fun countdown(x : int) =
    if x=0
    then []
    else x :: countdown(x-1)

fun check(countdown : int list) =
    if null countdown
    then 0
    else

Upvotes: 1

Views: 254

Answers (2)

sshine
sshine

Reputation: 16115

Using the standard library, a function that produces the numbers [1; n-1],

fun below n = List.tabulate (n-1, fn i => i+1);

a function that removes numbers divisible by 2 or 3,

val filter23 = List.filter (fn i => i mod 2 <> 0 andalso i mod 3 <> 0)

a function that calculates the product of its input,

val product = List.foldl op* 1

and sticking them all together,

val f = product o filter23 o below

This generates a list, filters it and collapses it. This wastes more memory than necessary. It would be more efficient to do what @FPstudent and @coder do and generate the numbers and immediately either make them a part of the end product, or throw them away if they're divisible by 2 or 3. Two things you could do in addition to this is,

  1. Make the function tail-recursive, so it uses less stack space.

  2. Generalise the iteration / folding into a common pattern.

For example,

fun folditer f e i j =
    if i < j
    then folditer f (f (i, e)) (i+1) j
    else e

fun accept i = i mod 2 <> 0 andalso i mod 3 <> 0
val f = folditer (fn (i, acc) => if accept i then i*acc else acc) 1 1

This is similar to Python's xrange.

Upvotes: 2

FPstudent
FPstudent

Reputation: 841

It is not clear from the question itself (part of an exercise in some class?) how we are supposed to use nested functions since there are ways to write the function without nesting, for example like

fun p1 n =
    if n = 1 then 1 else
    let val m = n - 1
    in (if m mod 2 = 0 orelse m mod 3 = 0 then 1 else m) * p1 m
    end

and there are also many ways to write it with nested functions, like

fun p2 n =
    if n = 1 then 1 else
    let val m = n - 1
        fun check m = (m mod 2 = 0 orelse m mod 3 = 0)
    in (if check m then 1 else m) * p2 m
    end

or

fun p3 n =
    let fun check m = (m mod 2 = 0 orelse m mod 3 = 0)
        fun loop m =
            if m = n then 1 else
            (if check m then 1 else m) * loop (m + 1)
    in loop 1
    end

or like the previous answer by @coder, just to give a few examples. Of these, p3 is somewhat special in that the inner function loop has a "free variable" n, which refers to a parameter of the outer p3.

Upvotes: 2

Related Questions