Thanks for your information about trace. 

   h=:(^ i.@>:)&.>
   hh=: [: < [: (^ [: i. >:) >
   h 6
---------------------------┐
│1 6 36 216 1296 7776 46656│
L---------------------------
   hh 6
---------------------------┐
│1 6 36 216 1296 7776 46656│
L---------------------------
   
 I get a domain error when I try to trace hh even though the function works.

Linda


-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Raul Miller
Sent: Sunday, February 17, 2013 8:40 AM
To: [email protected]
Subject: Re: [Jprogramming] Recursive programming (and scoping therein)

Here's how I would approach this task:

First, I would think about how the sentence gets parsed.  Or, if I was just
learning how that works, I could have J guide me:

   require 'addons/general/misc/trace.ijs'
   trace '*/&>@{@((^ i.@>:)&.>/)@q:~&__'
...
(long output elided)

Note that the current version of trace does some surprising things with user
defined names, but since this sentence has no user defined names I can
ignore that issue.

Then, I would build up a sequence of named definitions which correspond to
those parsing steps.  I would try to give them meaningful names, and I would
comment them with the code I was substituting for to keep me from getting
too lost.  Note also that I could plug my names back into the original for
testing purposes.  For example, using variations on the sentence

   (*/&>@{@((^ i.@>:)&.>/)@q:~&__) 720

If I was impatient, I might implement testing as something that happens when
my definition script gets loaded.

Also, towards the end, I would skip a bunch of steps.  I used the idiom
F@q:~&__ which is equivalent to __ F@q: ] but keeps the left argument of q:
from getting to be too distant from q: itself. Rather than mechanically
translate this idiom (a rather length process, which requires I come up with
worthwhile names for what I think of as garbage intermediate results), I
would just use its replacement.

The resulting definitions would look something like this:

NB. i.@>: monad
oneThroughN=: [: i. 1 + ]

NB. ^ i.@>: dyad
firstNPowers=: [ ^ oneThroughN

NB. (^ i.@>:)&.> dyad
powersInBoxes=: ([: < ([: > [) firstNPowers [: > ])"0

NB. (^ i.@>:)&.>/ monad
combineUsingPowers=: powersInBoxes/

NB. */ monad
multiplyAll=: */

NB. */&> monad
multiplyAllFromBox=: ([: multiplyAll  [: > ])"0

NB. */&>@{ monad
multiplyAllPermutations=: [: multiplyAllFromBox {

NB. */&>@{@((^ i.@>:)&.>/) monad
multiplyAllPowers=: [: multiplyAllPermutations combineUsingPowers

fctrs=: [: multiplyAllPowers __ q: ]

And, at this point, you could do
   sfctrs=: fctrs f.
   5!:4 <'sfctrs'

But note also that if there were any failures in my translations (for
example, maybe I thought I was working with a monad where I was really
working with a dyad), I could isolate them.

And, in fact, when I am debugging tacit J, I use analogous techniques.
 If I do not understand what data I am dealing with at a particular point, I
replace the code which would run after that point so that I can capture the
data.  If I am particularly lost, I might substitute a phrase, replacing it
with  <@,&< in an otherwise working example.
This shows me exactly what the values are and also shows me whether the
context is a monadic or dyadic context.  If I want to see the shapes and do
not know the context, I can use ;&$

Once I have sufficiently explored the data to be able to construct my own
examples, I can extract the phrase (the one I had just replaced) onto the
command line and give it representative arguments.

Anyways, I strongly believe that being able to isolate problems is a crucial
skill for people working with computers.

I hope this helps,

--
Raul

On Sat, Feb 16, 2013 at 10:13 PM, Linda Alvord <[email protected]>
wrote:
> I am trying to write  factrs in simple J.  I hit two snags:
>
>    factrs=: */&>@{@((^ i.@>:)&.>/)@q:~&__
>    5!:6 <'factrs'
> ((((((*/)&>)@{)@(((^ (i.@>:))&.>)/))@q:)~)&__
>    factrs 500
> 1  5  25 125
> 2 10  50 250
> 4 20 100 500
>
>    f=:((((((*/)&>)@{)@(((^ (i.@>:))&.>)/))@q:)~)&__
>    g=:(((^ (i.@>:))&.>)/)
>    g
> (^ i.@>:)&.>/
>    g 500
> 500
>
>    f=:((((((*/)&>)@{)@g)@q:)~)&__
>    h=:(((*/)&>)@{)
>    h
> */&>@{
>    h 500
> 500
>
>    f=:(((h@g)@q:)~)&__
>    f
> h@g@q:~&__
>
>    gg=: 13 :'(<( ^ [: i. >:)>)/ y'
>    hh=:  13 :'*/"1>"0{y'
>
>    ff=:(((hh@g)@q:)~)&__
>    ff 500
> 1  5  25 125
> 2 10  50 250
> 4 20 100 500
>
>    ff=:(((hh@gg)@q:)~)&__
>    ff 500
> |length error: gg
> |       ff 500
> |[-24] c:\users\owner\j701-user\temp\52.ijs
>
> I can't understand  gg  well enough to adjust the rank.
>
> What does  &__  mean?
>
> Linda
>
>
> -----Original Message-----
> From: [email protected]
> [mailto:[email protected]] On Behalf Of Raul 
> Miller
> Sent: Monday, February 11, 2013 3:28 PM
> To: [email protected]
> Subject: Re: [Jprogramming] Recursive programming (and scoping 
> therein)
>
> After reading this, and finally noticing the comment about remel in 
> the original post, I am uncomfortable with this treatment of remel.
>
> A scheme 'alist' is like two J lists, one a list of keys which we 
> search to get an index into the other.  If the types are compatible 
> (probably valid for integers or boxes), this could be a two 
> dimensional array where one of the dimensions is 2.
>
> But the original code is not using an alist, as near as I can tell -- 
> it's just using a list of divisors.  In this context, I think remel 
> would logically be replaced by dyadic use of J's -. primitive.
> Except, this does not work as near as I can tell.  I'm not sure if 
> that's because remel is expected to modify the original alist, or if 
> that's because remel is really meant to treat the alist as a stack 
> where it's removing not only the matching element but all previous 
> elements (which is what the J implementation does).
>
> But ignoring that, and using the original supplied definition, here's 
> how I would translate the original code to J:
>
> allfactors =: af q:
>
> remel =: [ }.~ [: >: i.
>
> af=: dyad define
>   divisors=. y
>   num=. x
>   if.0=#divisors do.,num end.
>   uniquefactors=. ~.divisors
>   ;num;(num&% af divisors&remel)&.> uniquefactors
> )
>
> I have not tried to optimize this for efficiency because the recursive 
> process itself is too inefficient to be worth bothering with.
>
> For reference, here's one of the implementations from that rosetta 
> code link I posted earlier:
>
>    factrs=: */&>@{@((^ i.@>:)&.>/)@q:~&__
>    factrs 12
> 1  3
> 2  6
> 4 12
>
> Obviously you would want to ravel that result before treating it as a
list.
>
>    ,@factrs 12
> 1 3 2 6 4 12
>
> Anyways, I believe that this approach should be more efficient than 
> the use of remel (or whatever that should be) in recursion.
>
> --
> Raul
>
> On Mon, Feb 11, 2013 at 12:01 PM, Marshall Lochbaum 
> <[email protected]>
> wrote:
>> I assume the problems you're having are in getting num and divisors 
>> to work inside the lambda clause. J can handle this fine--just use 
>> tacit code rather than an explicit function for the lambda. Here is 
>> the same code in J.
>>
>> remel =: ([ }.~ [: >: i.)"_ 0
>>
>> allfactors =: af q:
>>
>> af =: [ , 4 : 0 ^: (*@#@])
>>   x (% af&.>(;@:) y <@remel ]) ~.y
>> )
>>
>> af uses a bit of refactoring to avoid having to write the case where 
>> y
>> (divisors) is empty explicitly. We know we want to tack x (num) to 
>> the beginning of the list regardless of what happens in the function. 
>> Once we have made this choice with the [ , at the beginning of af's 
>> definition, we see that the rest of the function should just return 
>> an empty list if passed an empty list for y. Therefore we add 
>> ^:(*@#@]) to af. This means the explicit portion is only executed if 
>> y has nonzero length. Otherwise it will do nothing, that is, return y 
>> which is the empty list we want.
>>
>> The inside of the function is fairly straightforward. We compute the 
>> nub of y to use as the right argument. Then y <@remel ] gives a boxed 
>> list of terms (remel divisors x), and % with left argument x and 
>> right argument ~.y gives the terms (/ num x). We apply af to them 
>> using af&.> to give a list of boxed results and combine these into a 
>> single list with ; .
>>
>> af can also be written in a completely tacit form, although in this 
>> form we can't easily juggle the three terms num, divisors, and 
>> (unique divisors). The easiest way out of this is just to compute the 
>> nub of divisors twice.
>>
>> af =: [ , ((%~.) $:&.>(;@:) (<@remel ~.)@]) ^: (*@#@])
>>
>> This verb uses $: for self-reference, but is largely the same as the 
>> other form of af.
>>
>> I realize that methods like these aren't really equivalent to proper 
>> scoping rules, but I think most of the time they are good enough.
>>
>> Marshall
>>
>> On Mon, Feb 11, 2013 at 01:04:31PM +0000, Alex Giannakopoulos wrote:
>>> Are there any resources on recursive programming in J?  Couldn't 
>>> find much by searching.
>>> I would particularly like to know about scoping, and also so-called 
>>> free variables.
>>>
>>> It seems to me that the enforced naming of variables as 'x' and 'y'
>>> might cause problems in nested functions, necessitating awkward 
>>> renaming and copying.
>>>
>>> I will give a little example here (my apologies to those unfamiliar 
>>> with
>>> Scheme.)
>>> I am trying to write a routine that will return ALL the factors of a 
>>> number, not just the prime ones.
>>> I do this by using an auxiliary routine that takes the number to 
>>> factor and a list of numbers still to combine.
>>>
>>> ;; function (unique numlist) corresponds to J's ~.
>>> ;; function (remel alist elem) corresponds to J's   [ }.~ [: >: i.
>>> ;; function (primefactors n) corresponds to J's   q:
>>>
>>> (define (allfactors n) (af n (primefators n))
>>>
>>> (define (af num divisors)
>>>   (if (null? divisors) (list num)
>>>       (let ((uniquefactors (unique divisors)))
>>>            (flatten
>>>            (cons num
>>>                  (map (lambda(x) (af (/ num x) (remel divisors x)))
>>>                       uniquefactors))))))
>>>
>>> Now I tried to express this in J, but can't even get to first base, 
>>> because of the scoping problems I mentioned.
>>> I realise that recursion is not the primary mode for programming J, 
>>> and a good solution may instead use something like running totals 
>>> (\), but for the time being I am stuck.
>>> Any suggestions gratefully received.
>>> --------------------------------------------------------------------
>>> -
>>> - For information about J forums see 
>>> http://www.jsoftware.com/forums.htm
>> ---------------------------------------------------------------------
>> - For information about J forums see 
>> http://www.jsoftware.com/forums.htm
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
>
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to