Re: [racket-users] recursive function with multiple arguments

2019-04-12 Thread Matthias Felleisen

A bit of modernity yields this: 

(define (project-pop.v1 y r k thetasd t [i 1])
  (cond
[(= i t) (list y)]
[else (define theta (flvector-ref (flnormal-sample 0.0 thetasd 1) 0))
  (define y1 (* y (- r (* r (/ y k))) (exp theta)))
  (cons y (project-pop y1 r k thetasd t (+ i 1)))]))

Since this is really a fold, you could also use one of the Racket 
comprehensions to bring across the intent: 

(define (project-pop.v2 y r k thetasd t)
  (define-values (_ l)
(for/fold ((y y) (l '())) ((i (in-range 0 t 1)))
  (define theta (flvector-ref (flnormal-sample 0.0 thetasd 1) 0))
  (values (* y (- r (* r (/ y k))) (exp theta)) (cons y l
  (reverse l))

Given how short these functions are, v1 is just fine. 

Or you could stick to the original R design and write an imperative vector-fill 
function: 

(define (project-pop.v3 y0 r k thetasd t)
  (define y (make-vector t y0))
  (for ((i (in-range 1 t 1)))
(define theta (flnormal-sample 0.0 thetasd 1))
(define y@i-1 (vector-ref y (- i 1)))
(vector-set! y i (* y@i-1 (- r (* r (/ y@i-1 k))) (exp (flvector-ref theta 
0)
  y)




-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] recursive function with multiple arguments

2019-04-11 Thread David Storrs
Others have already given elegant solutions, but if you'd like a simple
transliteration that does not require a struct, here you go:

#lang racket
(require math)

(define (logmod y r k thetasd)
  (define theta (flvector-ref (flnormal-sample 0.0 thetasd 1) 0))
  (list (* y
   (- r (* r (/ y k)))
   (exp theta))
r k thetasd))

(define (project-pop y r k thetasd t [i 1])
  (if (= i t)
  (list y)
  (cons y (apply project-pop (append (logmod y r k thetasd) (list t (+
i 1)))

(project-pop  1.0 1.8 20.0 0.1 25)


If you'd like to reduce it to one function, you could do this:

(define (project-pop y r k thetasd t [i 1])
  (if (= i t)
  (list y)
  (cons y (project-pop (let ([theta (flvector-ref (flnormal-sample 0.0
thetasd 1) 0)])
(* y (- r (* r (/ y k))) (exp
theta)))
   r k thetasd t
  (+ i 1)

(project-pop  1.0 1.8 20.0 0.1 25)


On Thu, Apr 11, 2019 at 1:50 AM  wrote:

> Hi All,
>
> I'm trying to better understand recursion. I decided to rewrite the
> logmodr function from this blog post
>  as
> a recursive function. I was easily able to write the recursive functions if
> all but one of the arguments were set to default values. But I was
> completely stumped by how to handle the situation without using default
> argument values. After a considerable amount of flailing about, I finally
> realized that I could accomplish this task by passing the arguments as a
> struct (see code below). I find the struct approach relatively intuitive
> but it strikes me as quite verbose. Are there other (better?) ways to
> handle this task?
>
> Thanks,
>
> Travis
>
>
> #lang racket
>
> (require math)
>
> (struct args (y r k thetasd) #:transparent) ; only 'y' changes in
> project-pop function below
>
> (define (logmod args-struct)
>   (define theta (flvector-ref (flnormal-sample 0.0 (args-thetasd
> args-struct) 1) 0))
>   (args (* (args-y args-struct) (* (- (args-r args-struct) (* (args-r
> args-struct) (/ (args-y args-struct) (args-k args-struct (exp theta)))
> (args-r args-struct)
> (args-k args-struct)
> (args-thetasd args-struct)))
>
> (define (project-pop args-struct t [i 1])
>   (define y (args-y args-struct))
>   (if (= i t)
>   (list y)
>   (cons y (project-pop (logmod args-struct) t (+ i 1)
>
> (project-pop (args 1.0 1.8 20.0 0.1) 25)
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] recursive function with multiple arguments

2019-04-11 Thread Matt Jadud
Hi Travis,

Others will probably have better insights.

The only part that would be able to be replaced with a recursive call in
logmodr seems to be the loop itself. It is walking the list/vector y from
the second element to t (which... does numeric on a vector coerce it to a
length? I have no idea what numeric(t) does in this context. I sometimes
lose my mind trying to think about everything in R as a vector, and
where/when different functions do different things depending on what you
pass as a value...).

My termination condition is when i is equal to t, and otherwise, I do the
calculation, attaching the current calculation to the result of calculating
the rest of the values in the range. (In the for loop in the original
logmodr, this comes out looking like assignment to a vector, but we'll cons
up a list instead.) I have no idea if my pseudocode below puts the list in
the correct order... that could be fixed in a number of ways.

If I were translating this code, I would personally consider allocating the
vector and just doing the direct transliteration with a for loop. I don't
know that I would try and convert the code to a recursive call... but, as a
learning exercise, it makes sense why you're thinking about it.

The HtDP design recipe helps in thinking about how to break these kinds of
questions down. In this case, I had to think about whether there was a
recursion over a list/vector (there doesn't seem to be), but instead it
seemed like I'm building up my results in a list/vector. Therefore, I
needed to think about the recursion on the range of numbers and choose my
termination condition accordingly. From there, I also needed to figure out
what information was initialization, and what information needed to be
passed through the loop. Ultimately, I might pass a fair number of
parameters, but that's because I have to maintain the correct local scope
for each recursive call. I could also use an internal function definition
for some of these things, so that values that don't change are defined
once, and the function that is implementing the loop closes over those
values just once. This would cut... theta from the list of parameters, and
possibly also k and r, because they don't change. (Ha! K&R don't change.
That's a C pun!)

Bad humor aside, my point was that I could probably define a calc function
that had an internal calc* function (using either an internal define or a
letrec), and it would only take i and y as parameters. calc* would then
implement the "loop".

Someone will, no doubt, post a cleaner example that is three lines long and
only uses letrec and lambda, but here was my take on your question. But,
this was more fun then getting started on grading.

Cheers,
Matt

(define (rnorm t thetasd)
  (list 1 2 1))

(define (calc i y t r k theta)
  (cond
[(= i t) '()]
[else
 (cons (* (list-ref y (sub1 i))
  (- r (* (/ (* r (list-ref y (sub1 i))) k)
  (exp (list-ref theta i)
   (calc (add1 i) y t r k theta))]))

(define (logmodr yinit t r k thetasd)
  (let ([y (list yinit)]
[theta (rnorm t 0 thetasd)])
(calc 0 y t r k theta)))

On Thu, Apr 11, 2019 at 1:50 AM  wrote:

> Hi All,
>
> I'm trying to better understand recursion. I decided to rewrite the
> logmodr function from this blog post
>  as
> a recursive function. I was easily able to write the recursive functions if
> all but one of the arguments were set to default values. But I was
> completely stumped by how to handle the situation without using default
> argument values. After a considerable amount of flailing about, I finally
> realized that I could accomplish this task by passing the arguments as a
> struct (see code below). I find the struct approach relatively intuitive
> but it strikes me as quite verbose. Are there other (better?) ways to
> handle this task?
>
> Thanks,
>
> Travis
>
>
> #lang racket
>
> (require math)
>
> (struct args (y r k thetasd) #:transparent) ; only 'y' changes in
> project-pop function below
>
> (define (logmod args-struct)
>   (define theta (flvector-ref (flnormal-sample 0.0 (args-thetasd
> args-struct) 1) 0))
>   (args (* (args-y args-struct) (* (- (args-r args-struct) (* (args-r
> args-struct) (/ (args-y args-struct) (args-k args-struct (exp theta)))
> (args-r args-struct)
> (args-k args-struct)
> (args-thetasd args-struct)))
>
> (define (project-pop args-struct t [i 1])
>   (define y (args-y args-struct))
>   (if (= i t)
>   (list y)
>   (cons y (project-pop (logmod args-struct) t (+ i 1)
>
> (project-pop (args 1.0 1.8 20.0 0.1) 25)
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
Y

[racket-users] recursive function with multiple arguments

2019-04-10 Thread travis . hinkelman
Hi All,

I'm trying to better understand recursion. I decided to rewrite the logmodr 
function from this blog post 
 as 
a recursive function. I was easily able to write the recursive functions if 
all but one of the arguments were set to default values. But I was 
completely stumped by how to handle the situation without using default 
argument values. After a considerable amount of flailing about, I finally 
realized that I could accomplish this task by passing the arguments as a 
struct (see code below). I find the struct approach relatively intuitive 
but it strikes me as quite verbose. Are there other (better?) ways to 
handle this task?

Thanks,

Travis


#lang racket

(require math)

(struct args (y r k thetasd) #:transparent) ; only 'y' changes in 
project-pop function below

(define (logmod args-struct)
  (define theta (flvector-ref (flnormal-sample 0.0 (args-thetasd 
args-struct) 1) 0))
  (args (* (args-y args-struct) (* (- (args-r args-struct) (* (args-r 
args-struct) (/ (args-y args-struct) (args-k args-struct (exp theta)))
(args-r args-struct)
(args-k args-struct)
(args-thetasd args-struct)))

(define (project-pop args-struct t [i 1])
  (define y (args-y args-struct))
  (if (= i t)
  (list y)
  (cons y (project-pop (logmod args-struct) t (+ i 1)
  
(project-pop (args 1.0 1.8 20.0 0.1) 25)


-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.