Creating a recursive silent function in J

I am new to J and I tried to create the Fibonacci function as an exercise (always the second function that I create when learning a language). I just can't figure out what exactly is wrong in my way of doing this. I tried to define it as unspoken, but it freezes if the argument is more than one.

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

I also tried to create it explicitly, and it worked fine.

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

I tried to create a silent one from this, replacing 3 with 13, but he made a mistake.

  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 ask someone to explain what exactly I am doing wrong here.

+6
source share
2 answers

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

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

Compare with the more canonical (pseudo-code) definition:

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

First, instead of [ ` c @. (>&1) @. (>&1) that gerund uses is better to use ^:(1&<) . For f(n) if cond(n) else n using the conjunction ^: more idiomatic; ^:0 means "do nothing", and ^:1 means "do it once", so the goal is clear. @. better suited for non-trivial behavior.

Secondly, using the & bond / compose connection greatly simplifies the train. Reusing [: and ] rather confusing and opaque. Refactoring using & combines related operations: first, split n into two, namely n-2 and n-1 , and secondly, add fibn these two numbers.

And finally, "0 for list processing and M. for memoizing. M. quite important in terms of performance, since a simple implementation of the canonical definition will over-call fib(2) . You can get your cake (simple definition) and eat it ( good performance) with built-in eternal reminder.

The source for this specific definition is f0b on this page .

+4
source

Ok, I found it. I executed only the recursive block through the implicit generator and got this block.

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

Then I inserted it into the original play, getting it.

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

And it works like a charm. I also inserted " 0 at the end so that it accepts lists.

+4
source

Source: https://habr.com/ru/post/970714/


All Articles