Raul wrote:
> Yeah... personally, I consider explicit code to be a subset of tacit code.
I think of explicit and tacit as two distinct but related languages. That “:”
is tacit doesn’t mean the programs written in it are tacit: I could
(theoretically) write a tacit Lisp interpreter, but that doesn’t mean the Lisp
programs I pass to it are written in J.
> Still, even if you do not like the appearance of the code I offered,
> perhaps you could at least tell me if there is something wrong with
> what it does?
This question somewhat misses the point.
Say this were English class and I asked you to compose a haiku on the topic of
winter. Say then that you came back with a sublime, stirring sonnet on winter
that captured the bitter winds; the trees sparking with ice crystals as if they
were fruiting diamonds; the lamps glowing in twilight windows; the yearning for
spring. In short, you delivered to me a beautiful poem which precisely evoked
the subject. A work of art whose like hasn’t been seen before in the world.
Except the assignment was a haiku, and you gave me a sonnet.
In other words, the “how” is not a means here, but an end. The requirement for
tacit is precisely that: a requirement. It is a fundamental part of the
specification, not a suggestion on coding style. Note that, absent this
requirement, Am would *not be required at all*, as we could simply write the
target modifiers explicitly and dispense with the intermediate metaprogramming
step.
If it helps, your audience is J programmers, not end users. The result to keep
your eye on is the *actual notation*, not the output of the program. The
object is not to transform inputs to outputs, but to assist J programmers in
writing purely (purely!) tacit code. Just as there are guides on how to compose
haikus, here we are writing a guide on how to write J, tacitly.
If you want to talk about *why* that’s a goal, I’d be happy to have that
conversation (but not today; I’m not feeling very eloquent).
So: yes, absolutely, your code produces the correct output for a given set of
inputs. But while that’s necessary, it’s not sufficient.
It may help clarify my aims if I provide an example of what I’m looking for. So
I went ahead and implemented the idea I referenced earlier:
> Exercise for the very ambitious reader: define a tacit adverb opTheat
> (operating theatre), which, given a verb (the surgeon), derives another
> tacit adverb, such that
>
> surgeon opTheat
> ((<":0)`) (surgeon`) (@.(0; 1 2))
>
> The objective is to be able to provide an convenient utility / interface for
> adverbial programmers, so that their responsibility is only to write the
> core a.r.-transforming function (i.e. perform the surgery), and not always
> have to prepare the patient and the operating theatre themselves.
You can see the implementation at [1], but the short story is you can now
create perfectly tacit adverbs simply by creating a (tacit) verb which expects
an atomic representation as input, and produces another atomic representation
as output.
This permits us to produce arbitrary J structures, of any part of speech,
tacitly. Here’s the example we’ve been working with from Pepe:
NB. Given the fork (v0 v1 v2), bends the outer tines
NB. such that it produces (v0@[ v1 v2@])
NB. For rationale, see the thread:
NB.
http://www.jsoftware.com/pipermail/programming/2015-December/043657.html
xform =. (left center right)`'' ('[' atop~ ])`(']' atop~
])`]@.((;:'left right') i. [)"0 L:1 ]
atop =. '@' <@; <@:,&boxopen
Notice this is simply a tacit verb which both operates on and produces the
atomic representation of a simple 3-verb train. Now, we only need to pass this
verb to our magical new adverb, and:
(+: + -:) xform Pare
+:@[ + -:@]
Thus:
3 4 (+: + -:) xform Pare 2 4
7 10
Or, as a simpler example, the identity adverb:
+ ]Pare
+
+/ ]Pare
+/
3 ]Pare
3
a: ]Pare
++
||
++
Note that this actually executed the resulting a.r. to produce a (derived)
entity. Returning to the original goal of Am, which was simply to produce the
a.r. directly and defer execution to the caller, then:
Ar =: ] Par NB. Note “Par”, not “Pare” (no “e, no Execution)
+/ Ar
+-------+
|+-+---+|
||/|+-+||
|| ||+|||
|| |+-+||
|+-+---+|
+-------+
(+/ % #) Ar
+-----------------+
|+-+-------------+|
||3|+-------+-+-+||
|| ||+-+---+|%|#|||
|| |||/|+-+|| | |||
|| ||| ||+||| | |||
|| ||| |+-+|| | |||
|| ||+-+---+| | |||
|| |+-------+-+-+||
|+-+-------------+|
+-----------------+
Now, the implementation is rough and I’m sure there’s room for improvement, but
note to Pepe: no wickedness was employed :)
One frustration I encountered which significantly complicated the solution was
that this:
adverbWhichProducesAnAdverb =: 1 : '/'
anotherAdverb =: ~
totalAdverb =: adverbWhichProducesAnAdverb anotherAdverb
+ totalAdverb
|syntax error: totalAdverb
| +totalAdverb
is a syntax error in J. I haven’t thought through why that is, or should be,
the case (grammatically speaking), but this is not the first time it’s tripped
me up [2].
In the case of the pare.ijs script, it precluded any meaningful amount of code
reuse. If someone has a grammatical explanation for this error, I’d love to be
walked through it.
-Dan
[1] Pare script: Process Atomic Representations and Execute:
http://www.jsoftware.com/svn/DanBron/trunk/environment/pare.ijs
<http://www.jsoftware.com/svn/DanBron/trunk/environment/pare.ijs>
[2] Verb pipeline utility foundering on the inability to create adverb trains
via derived adverbs:
http://www.jsoftware.com/pipermail/programming/2010-June/019755.html
<http://www.jsoftware.com/pipermail/programming/2010-June/019755.html>
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm