3

Let's say I have the following J expression:

# 3 ((|=0:)#]) 1+i.1000

This counts the number of numbers between 1 and 1000 that are evenly divisible by 3. (Now, before anyone points out that there's an easier way to do this, this question is about the syntax of J, and not mathematics.)

Let's say I define a monadic function for this, as follows:

f =: monad define
# y ((|=0:)#]) 1+i.1000
)

This works great with a single argument, e.g.,

    f 4
250

If I pass a list in, I get a length error:

    f 1 2 3
|length error: f

Now, I completely understand why I get the length error. When you substitute the list 1 2 3 for the y argument of the monad, you get:

# 1 2 3 ((|=0:)#]) 1+i.1000

If you know anything about J, it's pretty clear why the length error is occurring. So, I don't need an explanation of that.

I want to define the function such that when I pass a list, it returns a list, e.g.,

   f 1 2 3
1000 500 333

How can I either (a) redefine this function to take a list and return a list or (b) get the function to work on a list as-is without being redefined, perhaps using some adverb or other technique?

Gregory Higley
  • 15,923
  • 9
  • 67
  • 96
  • 2
    I just realized that the real answer is `f"0 ] 1 2 3` using the _rank_ conjunction. (The superfluous `]` prevents me from having to use parentheses.) – Gregory Higley Jun 02 '10 at 21:36

2 Answers2

2

I recommend the much simpler approach of defining your verb as rank zero. Working with the verb you provided, here's a simple way to do that:

   f =: monad define "0
# y ((|=0:)#]) 1+i.1000
)

   f 1 2 3
1000 500 333

The only change is the "0 added after the word 'define'.

kaleidic
  • 3,070
  • 1
  • 21
  • 22
  • 1
    Knowing the desired behaviour of the function makes it easier to decide to define it as rank 0. That being said, I'd have simply used `f every` or `f"0`. – MPelletier Aug 17 '10 at 01:17
1

This is for (b) case:

    (f@{. , $:@}.) ^: (0 < #) 1 2 3
1000 500 333
YasirA
  • 9,531
  • 2
  • 40
  • 61
  • Wow. I didn't know you could say `(0<#)`! I thought you had to say `(0:<#)`. Pretty cool. – Gregory Higley May 23 '10 at 20:42
  • @Gregory Higley: Since verbs in J are applied to arguments from right to left, `(0 < #) 1 2 3` is the same as `0 < (# 1 2 3)` or `0 < # 1 2 3`. `(0: < #)` which you suggested in turn is a *fork* we were talking about [in here](http://stackoverflow.com/questions/2864835). Consider also `3 * 5 + 2`, it's evaluated to `21` ;) – YasirA May 24 '10 at 11:09
  • 2
    It is necessary to see (0 < #) as a special form of a fork, rather than saying the parentheses don't matter. The latest version of J treats the noun in the expression as a verb. It's a rare case of syntactic sugar in J; (noun verb verb) is interpreted as (noun"_ verb verb) – kaleidic Sep 30 '10 at 10:38