Great explanation Dan, A couple of years ago I put this video together about the adverb '~' .
http://bobtherriault.wordpress.com/2010/11/17/those-tricky-adverbs/ Let me know if you have any interest in developing your explanations into a more multimedia mode. I don't have huge amounts of time (and it does take some time), but I do enjoy doing this stuff. Cheers, bob On 2013-06-13, at 9:48 AM, Dan Bron wrote: > Alexander Epifanov wrote: >> but I did not understand what is the different, >> I mean how it works if it is adverb. > > To understand this error, we must first discuss what adverbs are, how they > behave, and how they differ from verbs. So let's start there. > > ---------- > Adverbs are a different class, or order, of words than verbs. In > particular, they have higher grammatical precedence than verbs, and so > gobble up any suitable arguments lying around before verbs can even see > them. Conjunctions are in this same high-precedence class, but whereas > adverbs only take one argument (on the left), conjunctions take two (one on > the left, the other on the right). You can think of adverbs and > conjunctions as higher-order analogs to monadic and dyadic verbs > respectively.* > > Adverbs are called adverbs because they normally modify verbs: that is, in > typical use, they accept a verb argument and produce verb result, which is > related in some (consistent) way to the argument. The most famous example > is / : > > +/ 2 3 4 NB. Sum of data (Σ s[i]) > */ 2 3 4 NB. Product of data (Π s[i]) > ^/ 2 3 4 NB. Tetration ("power tower") of data > > Here, / takes a dyad (two-argument verb) as an argument, and produces a > monad (one-argument verb)*. The output is related to the input in the > following sense: when the output verb is provided an noun, it inserts the > input verb between each pair of items in the noun, such that: > > +/ 2 3 4 is 2+3+4 > */ 2 3 4 is 2*3*4 > ^/ 2 3 4 is 2^3^4 NB. Note: J executes right-to-left, so this > is 2^(3^4) > > and > > +/ 2 3 4 , 5 6 7 ,: 8 9 10 > is: > 2 3 4 > + > 5 6 7 > + > 8 9 10 > > which, because + is rank 0 (scalar), is: > > 2 3 4 > + + + > 5 6 7 > + + + > 8 9 10 > > etc. > > But bear in mind that taking verb arguments and deriving (consistently) > related verbal results is only the typical case for an adverb. Adverbs can > also take a noun for an argument (an "adjective"); the most common example > is } , which normally takes a noun argument specifying which indices the > derived verb should modify (when it, itself, is applied to nouns): > > putFirst =: 0} > putLast =: _1} > putFirstAndLast =: 0 _1} > > '*' putFirst '12345' > *2345 > '*' putLast 'ABCDE' > ABCD* > '*' putFirstAndLast 'ABCDE' > *BCD* > > So adverbs can take verbs or nouns as inputs, and normally produce verbs as > outputs. But adverbs are not restricted to verbal output; they can produce > anything, including verbs, nouns, and even other adverbs and conjunctions. > Primitive adverbs which produce non-verb results are unusual (primitive > conjunctions are a little more diverse in this regard), but they exist. For > example, when the adverb ~ is applied to a string, it treats the string in > as a name and evokes it, such that 'someName'~ is equivalent to someName > . Therefore ~ can produce anything at all: > > someNoun =: 42 > someVerb =: + > someAdverb =: / > someConjunction =: @ > > 'someNoun'~ > 42 > 'someVerb'~ > + > 'someAdverb'~ > / > 'someConjunction'~ > @ > > > Of course user-defined adverbs will produce anything they're defined to > produce, so you can't know what they'll do without reading the definition or > documentation. That said, user-defined adverbs tend to follow the same > patterns as primitive adverbs: they're almost always abstractions over verbs > which produce verb results; sometimes they take noun arguments and/or > produce noun results, and only very rarely do they produce other adverbs or > conjunctions. > > Ok, with that as a background, we're ready to discuss write_image and the > error you observed. > > --------------- > > The word write_image falls into this "user defined adverb" category. The > reason it was defined as an adverb instead of a verb is so that it can > accept up to 3 arguments (filename, data to write, and a set of options like > image quality or scaling), whereas if it were defined as a verb, it could > accept no more than two arguments. Meaning if write_image had been defined > as a verb, it would have to find some way to pack two arguments into a > single noun, and unpack them inside the definition, which can sometimes lead > to convoluted code. Keeping it as an adverb with three distinct arguments > is very clear and clean. > > But it does stymie attempts to use it like a verb, as you discovered. In > particular, when you embedded it in > > (('small/'&, (write_image)~ ((3 3)&resize_image)@:read_image)@:>) i > > , its higher grammatical priority caused the adverb to seek out an argument > immediately, and since the verb 'small/'&, was on its left and suitable > (because verbs are perfectly acceptable arguments for adverbs), the result > was that write_image bound with 'small/'&, . > Now, the specific coding style** of write_image prevented it from being > executed immediately (if it'd been executed, you'd know it, because you > would have gotten an error: write_image is expecting data [a noun] as an > argument, not a verb like 'small/'&,), but it also allowed the J interpreter > to infer that when it is executed, it will produce a verb. > > So write_image woke up, looked around for an argument, found 'small/'&, , > bound with it, and though it didn't actually execute, the J interpreter knew > its product would be a verb. Knowing this, J proceeded parsing the > sentence, found another verb ((3 3)&resize_image)@:read_image)@:>, and hit a > close paren. Since it had found two verbs in isolation (nestled inside a > cozy pair of parens), it interpreted the train as a hook. This is really no > different from the sentence (%~ i.) 10 where ~ immediately binds to %, the > product of that binding and i. form a hook. > > After forming the hook, the interpreter it hit the noun i and applied the > hook as ('small/'&,write_image~ 3 3&resize_image@:read_image)@:> i . > The interpreter executed 3 3 resize_image read_image > i and got a result. > Up to this point, everything was fine. But now it came time to use the > results it had calculated, and actually execute write_image . That's where > the problem occurred: and it was exactly the error I mentioned earlier, that > the interpreter avoided by deferring the execution of write_image (you can > delay the inevitable, but you can't avoid it). > > That adverb was written expecting that its argument be a noun, and refers to > m, which is the name for the noun argument to an adverb (or conjunction). > But given how you expressed your sentence, in this case argument to > write_image was a verb: 'small/'&, . Therefore m (the name for a noun > argument to an adverb) was undefined, yet write_image tried to use it > anyway. > > J calls the use of undefined names a "value error". This is the same error > as when you type > > someNameIHaventDefinedYet > |value error: someNameIHaventDefinedYet > > in the session manager. > > But a closer analogy is the value error you'd get if you tried to use x > (which names a left argument) in a monadic verb which only has a right > argument: > > monad def 'x + y' 4 > |value error: x > | x+y > > You get a value error because x is undefined, and x is undefined because > monadic (valences of) verbs don't have the concept of a left argument: x is > literally meaningless. > > Similarly, when write_image referred to the noun argument m, the J > interpreter balked: "What noun argument? Your argument is a verb, 'small/'&, > . I don't know what you're talking about." . The name for the > (non-existent) noun argument to write_image, m, was literally meaningless. > All because adverbs have higher precedence than verbs and can accept verbs > as well as nouns as arguments. > > Well, actually, because Cliff decided to define write_image as an adverb so > he could have three separate arguments, without boxing. I know that's a lot > to digest. I'm not known for my laconic style (cf Roger Hui), but I hope > this helps. > > -Dan > > * Technically, all verbs in J are ambivalent; that is, they can be called > with either one argument (on the right) or two arguments (one on the right, > and one on the left). The words "monad"/"monadic" and "dyad"/"dyadic" are > just shorthand for the "one-argument valence of the verb" and "the two > argument valence of the verb" respectively. > > Note that some valences of some verbs have empty domains, such as the dyad > ~. or the monad E. or the monad 4 : 'x + y' etc. That doesn't mean the > valence doesn't exist; it does exist, but it rejects all arguments (a > generalization of the concept that e.g. + rejects any argument that's not a > number). > > Now adverbs and conjunctions (collectively called operators) are analogous > to the monadic and dyadic valence of a verb respectively, but it is exactly > because of their higher grammatical precedence that there is no operator > analog to an ambivalent verb. That is, there is no operator that can take > either one argument or two arguments. Operators' higher binding power > requires that we treat these cases separately - and, incidentally, is the > reason adverbs (monadic operators) take their argument from the left, as > opposed to monadic verbs which take their argument from the right. > > ** The specific coding style that allowed the J interpreter to conclude > write_image would produce a verb without actually executing it was that it > mentioned x and y - which, by definition, refer to the noun arguments to an > explicit verb. Therefore write_image must produce an explicit verb, and x > and y refer to /its/ arguments. > > > > > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
