⬆️ ⬇️

J can be readable

Tin! It's like regular expression programming ...

No, you will not force me! Never again!
I look at the code and feel like an idiot. Is it really not an esoteric language like brainfuck? Is someone really using them? And then these programs are read?
quicksort=: (($:@(<#[), (=#[), $:@(>#[)) ({~ ?@#)) ^: (1<#)
Perl nervously smokes on the sidelines.
Habrahabr about J



image J - Korean among programming languages. The explosion at the factory of special characters. A lot of brackets, points, slashes, and it all also works. None other than at the behest of black magic, and even Satan himself.



Some of those who write to J forget the simple rules for writing any code in pursuit of brevity or just being carried away. These rules are not new, but they acquire critical meaning in relation to APL-like languages, because when reading constructs like ((]i.~[:{.[){([:{:[),]`([:<[$:[:>])@.([:32&=[:3!:0[:>]))"2 0 even a trained brain rolls up into a tube.

')

So, simple rules for writing readable code in J under the cut.



Without a dictionary under the cat is better not to meddle. You were warned.

And I recall a list of useful links here .





Use mnemonics



If it is inconvenient or just doesn’t want to crawl into the dictionary often, to peek, what kind of symbols denote this or that function or what does that construct mean - wrap it in a verb:

  head =: {. tail =: {: head 9 8 3 0 6 1 2 5 4 7 9 tail 9 8 3 0 6 1 2 5 4 7 7 


Divide and rule



Sometimes it is better to break the complex, intricate structure into a few more simple ones.

  logistic =: dyad : '(^ - y % x) % x * *: >: ^ - y % x' exp =: dyad : '^ - y % x' logistic =: dyad : '(x exp y) % x * *: >: x exp y 


Comments



J comments begin with NB. , and this is the case when they can not be much ! If you get into a standard library or industry code, you can stumble upon tons of comments; often they are several times larger than the code itself: it is difficult to write self-documenting code in J, and the efforts usually do not justify themselves.



More gaps, good and different



The average one-liner in J consists of twenty weakly related symbols at first glance, there is no need to complicate the reading once again. Properly spaced spaces and brackets will help to understand the structure of even the most confusing verb.

  (]%[**:@>:@])[:^[:-%~ (] % [ * *:@>:@]) [: ^ [: - %~ 


Explicit is better than hidden



For complex expressions, it is often better to use explicit writing instead of tacit.

  (] % [ * *:@>:@]) [: ^ [: - %~ dyad : '(] % (x * *:@>:@])) ^ -y%x' 


Hooks and forks are your friends



For those who did not know or forgot:

  (fg) y ⇔ yf (gy) x (fg) y ⇔ xf (gy) (fgh) y ⇔ (fy) g (hy) x (fgh) y ⇔ (xfy) g (xhy) 


These simple constructions often help to reduce the amount of code by a factor of two to three, practically without compromising its readability.



Governing structures



J has all the usual control structures, but you can only use them inside an explicit verb.



Branches work the same way as in any other language: if the condition T returns 1, go to block B , otherwise move to the next block else./elseif. , if he is.

 if. T do. B end. if. T do. B else. B1 end. if. T do. B elseif. T1 do. B1 elseif. T2 do. B2 end. 


while. and whilst. execute block B , while T returns 1, with the difference that whilst. skips checking for the first pass, so B always executed at least once.

 while. T do. B end. whilst. T do. B end. 


for. just executes B as many times as there are elements in T ; for_i. creates variables i and i_index - an element and its index, respectively.

 for. T do. B end. for_i. T do. B end. 


select. proceeds to the first Ti , matched with T , executing the corresponding block. fcase. - case. with "falling through."

 select. T case. T0 do. B0 case. T1 do. B1 fcase.T2 do. B2 case. T3 do. B3 end. 


If block B fails, execute block B1 , otherwise just ignore it.

 try. B catch. B1 end. 





Let's try to apply these rules to the solver sudoku from this post .

Source Source Code:

  i =: ,((,|:)i.9 9),,./,./i.4$3 c =: (#=[:#~.)@-.&0 t =: [:(([:*/_9:c\])"1#])i&{+"1 1(>:i.9)*/[:i&=i.&0 r =: [:,`$:@.(0:e.,)[:;(<@t)"1 s =: 9 9&$@r@, 


The result of the transformation:

  cells =: ,./^:2 i. 4 # 3 rows_cols =: ((, |:) i. 9 9) indices =: , rows_cols, cells no_errors =: verb : '(-: ~.) y -. 0' substitutions =: verb : '(indices { y) +"1 1 ((>:i.9) */ indices = y i. 0)' remove_wrong =: verb : 'y #~ */"(1) _9 no_errors\"1 y' try =: remove_wrong @ substitutions solve =: verb define variants =: y whilst. 0 e. ,variants do. variants =: ; (<@try)"1 variants end. ,variants ) sudoku =: verb : '9 9 $ solve , y' 


Work result
  m 2 0 0 3 7 0 0 0 9 0 0 9 2 0 0 0 0 7 0 0 1 0 0 4 0 0 2 0 5 0 0 0 0 8 0 0 0 0 8 0 0 0 9 0 0 0 0 6 0 0 0 0 4 0 9 0 0 1 0 0 5 0 0 8 0 0 0 0 7 6 0 0 4 0 0 0 8 9 0 0 1 sm 2 8 4 3 7 5 1 6 9 6 3 9 2 1 8 4 5 7 5 7 1 9 6 4 3 8 2 1 5 2 4 9 6 8 7 3 3 4 8 7 5 2 9 1 6 7 9 6 8 3 1 2 4 5 9 6 7 1 4 3 5 2 8 8 1 3 5 2 7 6 9 4 4 2 5 6 8 9 7 3 1 sudoku m 2 8 4 3 7 5 1 6 9 6 3 9 2 1 8 4 5 7 5 7 1 9 6 4 3 8 2 1 5 2 4 9 6 8 7 3 3 4 8 7 5 2 9 1 6 7 9 6 8 3 1 2 4 5 9 6 7 1 4 3 5 2 8 8 1 3 5 2 7 6 9 4 4 2 5 6 8 9 7 3 1 


Now the code shows what it does! I think this is a success.

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



All Articles