Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a recursive tacit function in J

I'm a newcomer to J and I've been trying to create a Fibonacci function as an exercise (always the second function I create when learning a language). I just can't figure out what exactly is wrong in my way of doing it. I have tried to define it as tacit, but it gets hung if argument is greater than one.

fib =: [ ` (($: (]-1)) + ($: (]-2))) @. (>&1)

I've also attempted to create it explicitly, and that worked fine.

fib =: 3 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'

I tried to create a tacit out of that by replacing 3 with 13, but it threw an error.

   fib =: 13 : 'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'
|spelling error
|   if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.
|   ^
|   fib=:    13 :'if. y>1 do. (fib (y-1)) + (fib (y-2)) else. y end.'

So, I'm asking for someone to explain what exactly I am doing wrong here.

like image 515
seequ Avatar asked Jun 11 '14 18:06

seequ


2 Answers

Here's an alternative that I think is both clearer and more concise:

fibn =: (-&2 +&$: -&1)^:(1&<) M."0

Compare with a more canonical (pseudocode) definition:

fib(n) = fib(n-1) + fib(n-2) if n > 2 else n

First, instead of using [ ` with @. (>&1), which uses a gerund, it's better to use ^:(1&<). For f(n) if cond(n) else n, using the ^: conjunction is more idiomatic; ^:0 means "do nothing" and ^:1 means "do once," so the intent is clear. @. is better suited to nontrivial behavior.

Second, using the & bond/compose conjunction simplifies the train significantly. Repeated uses of [: and ] are rather confusing and opaque. Refactoring using & puts together related operations: first, split n into two, namely n-2 and n-1, and second, add together the fibn of those two numbers.

And, lastly, "0 for list handling and M. for memoizing. M. is rather important from a performance perspective, as a straightforward implementation of the canonical definition will call fib(2) excessively. You can have your cake (a simple definition) and eat it too (good performance) with the built-in memoization adverb.

Source for this particular definition: f0b on this page.

like image 119
rationalis Avatar answered Nov 07 '22 18:11

rationalis


Okay, I found it. I ran only the recursive block through tacit generator and got this block.

   13 : '(f y-1) + (f y-2)'
([: f 1 -~ ]) + [: f 2 -~ ]

Then I inserted that to the original piece, getting this.

fib =: [ ` (([: $: 1 -~ ]) + [: $: 2 -~ ]) @. (>&1)

And that works like a charm. I also inserted " 0 to the end to make it accept lists.

like image 34
seequ Avatar answered Nov 07 '22 18:11

seequ