24 ноября 2013 в 22:02

Язык программирования J. За что любить?

image
J – самый ненормальный и самый эффективный язык из известных мне языков. Он позволяет быстро разрабатывать, а также вызывать ненормативную лексику у людей, незнакомых с ним и смотрящих на код.

J слишком необычный. И сложный для изучения. У людей, сталкивающихся с J не хватает мотивации, чтобы его изучить. Синтаксис непривычный.
В этом посте я хотел помочь вам заглянуть дальше, что будет, если вы его изучите и чем он интересен. По своему опыту знаю, что преимущества этого языка сразу не очевидны. В посте я не собираюсь останавливаться на разборе конструкций. Только в обзоре. Предлагаю просто окунуться в примеры, попробовать ощутить мощь языка. Узнать, чем прекрасен язык, без изучения. Писать статьи, обучающие программированию на нем – дело сложное и думаю, не нужное. Он не так прост, чтобы это сделать кратко, а с обучающими материалами на официальном сайте нет никаких проблем. Главное – желание. Им и займемся.

Немного истории



До J был APL. Язык APL разработан Кеннетом Айверсоном во время преподавания в 50-х годах в Гарварде вычислительной математики. Специально для преподавания он разработал свою нотацию. Далее этот язык был перенесен на машины и стал известен как APL (скромное: A Program Language). APL работает с массивами и оптимизирован под работу с ними.

У языка APL есть небольшой недостаток. Операции обозначаются нестандартными символами. Для работы с ним нужна специальная клавиатура. Таким образом, назрела необходимость создать новый язык, более дружественный к стандартным устройствам ввода. Айверсон инициировал создание диалекта APL, который использует ASCII символы. Так Кеннет Айверсон совместно с Роджером Хуэем в начале 90-х создали язык J. В это время от команды Айверсона «откололся» Артур Уитни. Он имел разногласия по поводу того, как создавать J, и занялся созданием своего языка – K. Который также стал успешным языком.

Краткий обзор J



Скачать и установить J можно по ссылке www.jsoftware.com. Там же есть обучающие материалы и различная документация.

J – функциональный язык. Но язык не обычный, не классический функциональный. Не лиспоподобный. Единица данных — n-мерный массив, а не список.

J является интерпретатором (в этой реализации). С динамической типизацией.

Выражения строятся из глаголов, имен существительных, наречий, герундиев, союзов и прочего. Нас в данном посте будут интересовать глаголы (аналог функции/операции) и имена существительные (данные). Имена существительные – это не совсем данные, как в императивных языках. Они имутабельны. Таким образом, то, что в J называют присвоением, скорее является «именованием».

Имя существительное – это n-мерный массив. Создать имя существительное можно, например, так:

   3 5 $ 0

Мы получаем двумерный массив 3 на 5, состоящий из нулей. Можно получить массив любой мерности. Частным случаем является массив нулевой мерности — это скаляр. Одномерный массив – вектор. Таким образом, единица данных в J – n-мерный массив. Чтобы построить массив, заполненный не нулями, а нужными нам числами, после знака $ мы можем записать в строку нужные данные через пробел. Например строка:

   3 5 $ 1 2 3

Создаст и выведет массив 3 на 5 и заполнит по очереди повторяющейся последовательностью 1 2 3:

1 2 3 1 2
3 1 2 3 1
2 3 1 2 3


Для создания скаляра достаточно одного числа:

  a =: 4

Здесь я уже показал, как присваивается имя. Т.е. a у нас уже равно 4. Для создания вектора достаточно писать числа в строку через пробел:

   4 5 3 6
4 5 3 6


* Как вы уже догадались, J работает в интерактивном режиме, сразу выводит результат

Теперь о типах. В J кроме мерности массива, есть тип его элементов. Т.е. элементы всегда однотипные. Числовых типов несколько: логический (0, 1), целый, целый с любым количеством знаков, рациональный, действительный, комплексный. Также вместе с числовыми типами есть специальные числа: минус бесконечность, бесконечность, неопределенность. Динамическая типизация J замечательно подходит для математических операций – он на каждой операции сам определит, какие в нем числа. Например, если к матрице целых чисел применить квадратный корень, то можем получить либо действительные, либо комплексные числа. В зависимости от элементов первоначального массива.

Также в J, кроме числовых типов есть
1) символ (literal). В J также можно обрабатывать текст. Текст в случае J – это вектор из символов. Чтобы задать символ, нужно его заключить в одинарные кавычки. Чтобы задать вектор из символов – достаточно текст заключить в одинарные кавычки.
2) бокс (коробка, boxed) – это упакованный тип. Т.е. любую матрицу можно упаковать и получить бокс. А из боксов можно составить массив. С помощью боксов, таким образом, можно создавать деревья.
И еще несколько специальных типов, рассматривать которые не будем.

С существительными разобрались. Теперь, что представляют собой глаголы.
Глагол похож на операцию в математическом выражении в других языках. В J глаголы бывают двух видов: монадные (monad) и диадные (dyad). Это аналогично унарной и бинарной операциям. И это дает замечательную возможность: для создания глаголов не нужны имена для входных данных. Входных данных всегда одно или два – правое и левое.

Есть специальные правила, как формировать в одну строку глагол из других глаголов, не используя при этом никаких имен переменных.

Итак, первый стандартный пример:

  avg =: +/%#

Глагол avg – среднее арифметическое вектора. Обратите внимание на его тело – всего 4 символа. Здесь у нас всего три глагола – сложить числа (+/), взять длину вектора (#) и разделить первое на второе (%).

* Сложить числа в векторе обозначается символами + и /. Первый – сумма двух чисел, а второе – поставить операцию между всеми элементами (т.е. левый фолд). Так как слеш занят, то операция деления в J обозначается знаком %.

Создадим вектор и применим к нему наш глагол:

  a =: 5 3 7 0 2 4
  avg a
3.5

Получили среднее арифметическое вектора.

Как же происходит эта магия? В J используются такие простые правила. Во-первых, операции в J не имеют приоритета и выполняются справа налево. Если мы напишем выражение:

  2 * 3 + 4
14

Получаем 14, а не 10. Что, в общем-то, упрощает построение выражений. Если надо изменить порядок – используются скобки:

  (2 * 3) + 4
10

Не пугайтесь, это только что были выражения, вычисляющие значения напрямую, а когда мы писали avg =: +/%#, то мы задавали глагол, комбинируя глаголы.

Теперь разберем, как работает глагол вычисления среднего арифметического.
Когда глагол состоит из трех глаголов подряд, то сначала применяются крайние глаголы к существительным, а потом средний глагол к правому и левому по отношению к нему результату.
Вот так:


Если глагол состоит из 5 глаголов, то сначала выполняются три правых, как показано выше, потом берутся два левее и в таком же порядке выполняется дальше. Например, глагол взятия максимального из двух элементов:  «>.». Следовательно, максимальный из списка: «>./»
И напишем глагол, который находит сумму максимального значения и среднего арифметического:

  d =: >./++/%#

Применяем к вектору:

  d a
10.5

Как это работает:

Обратите внимание, что когда я пишу «как это работает», то я не имею ввиду, что знаю, в какой последовательности выполняет эти глаголы J. Я только объясняю смысл, как надо понимать такую строку глаголов. Строкой глаголов мы говорим, что мы хотим. А как — решает J.

Выше я описал только одно из правил построения выражений. Просто ради того, чтобы вы уловили суть, как это возможно, кратко описывать в строку сложные алгоритмы и в чем кроется секрет лаконичности J. Естественно, J больше и описывать в посте всё нет смысла.

Иногда невозможно описать задачу так, чтобы глаголы принимали только два простых массива как аргументы (левый и правый). Иногда нужно писать глаголы, аналоги функций с бОльшим количеством аргументов. Это можно обойти боксированием. Т.е. можно задавать вектор боксов, в которых лежат, по сути, ряд разных значений, аналогично входным параметрам функции в других языках. А в глаголе их можно оттуда доставать и распаковывать. Также в глаголах реализуется рекурсия.

Описанная выше форма записи глаголов в J называется таситной (tacit).

Теперь несколько примеров, без объяснения, как они работают.

Примеры



1. INNER JOIN

Рассмотрим такой пример на SQL. У нас есть две таблицы:
CREATE TABLE Customers (ID INT, Name TEXT, Age INT, Salary INT)
CREATE TABLE Orders (OID INT,  Date  DATETIME,  CustomerID INT, Amount INT)

Как-то их заполняем. И такой запрос:
SELECT * FROM Orders o
INNER JOIN Customers c ON o.CustomerID = c.ID AND o.Amount < 2000 

Специально соединяю таблицы не по равенству, а через более сложный предикат, чтобы немного усложнить задание.
И попробуем сделать то же самое на J.

  createTable =: [:|:,.&a:
  union =: ([:{.[),:[:([:<[:;]#~~:&a:)"1([:{:[),.([:{:]){~([:{.])i.[:{.[
  insert =: [union[:({.,:([:([:<[:(]$~[:1&,#)>)"0{:))[:|:[:>]
  rows =: {.([:<,:)"1 1[:|:[:([:<"1[:,.>)"0{:
  value =: [:(]`{.@.([:1&=#))[:,[:>[((([:<[)=[:{.])#[:{:])[:>]
  pr =: [:,[:(([:>[)(([:<([:>[),.[:>])"0 0)"0 1[:>])/[:([:<[:rows>)"0]
  join =: 1 : '((([:{.[:>{.),:[:([:<(>"0))"1[:{:[:1 2 0&|:[:>([:,u"0)#]) (pr y))'

В общем-то, это весь код, позволяющий решить данную задачу. Нужные глаголы есть. Создадим и наполним таблицы:

  Customers =: createTable 'ID';'Name';'Age';'Salary'
  Orders
=: createTable 'OID';'Date';'CustomerID';'Amount'

  Customers
=: Customers insert (<'ID'; 1),(<'Name'; 'Ramesh'),(<'Age'; 32),(<'Salary'; 2000)
  
Customers =: Customers insert (<'ID'; 2),(<'Name'; 'Khilan'),(<'Age'; 25),(<'Salary'; 1500)
  
Customers =: Customers insert (<'ID'; 3),(<'Name'; 'kaushik'),(<'Age'; 23),(<'Salary'; 2000)
  
Customers =: Customers insert (<'ID'; 4),(<'Name'; 'Chaitali'),(<'Age'; 25),(<'Salary'; 6500)
  
Customers =: Customers insert (<'ID'; 5),(<'Name'; 'Hardik'),(<'Age'; 27),(<'Salary'; 8500)
  
Customers =: Customers insert (<'ID'; 6),(<'Name'; 'Komal'),(<'Age'; 22),(<'Salary'; 4500)
  
Customers =: Customers insert (<'ID'; 7),(<'Name'; 'Muffy'),(<'Age'; 24),(<'Salary'; 10000)

  
Orders =: Orders insert (<'OID'; 102),(<'Date'; '2009-10-08'),(<'CustomerID'; 3),(<'Amount'; 3000)
  
Orders =: Orders insert (<'OID'; 100),(<'Date'; '2009-10-08'),(<'CustomerID'; 3),(<'Amount'; 1500)
  
Orders =: Orders insert (<'OID'; 101),(<'Date'; '2009-11-20'),(<'CustomerID'; 2),(<'Amount'; 1560)
  
Orders =: Orders insert (<'OID'; 103),(<'Date'; '2008-05-20'),(<'CustomerID'; 4),(<'Amount'; 2060)


Проверим, что у нас в таблицах:

  Customers
ID Name Age Salary
1
2
3
4
5
6
7
Ramesh
Khilan
kaushik
Chaitali
Hardik
Komal
Muffy
32
25
23
25
27
22
24
2000
1500
2000
6500
8500
4500
10000

  Orders
OID Date CustomerID Amount
102
100
101
103
2009-10-08
2009-10-08
2009-11-20
2008-05-20
3
3
2
4
3000
1500
1560
2060

И запрос с предикатом:

  (([:2000&>'Amount'&value)*.'CustomerID'&value='ID'&value) join Customers; <Orders
ID Name Age Salary OID Date CustomerID Amount
2
3
Khilan
kaushik
25
23
1500
2000
101
100
2009-11-20
2009-10-08
2
3
1560
1500

Вот так всё просто. Обратите внимание, что J — язык общего применения и в нем нет средств для обработки реляционных данных. Код, который выше, до создания и наполнения таблиц — вся логика. join может принимать любой предикат.

Пример на самом деле не сложный, т.к. массивы в чем-то схожи с таблицами, а боксы (коробки) J рисует в прямоугольниках, что позволяет сразу таблицы и отображать.

2. Решатель судоку

  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@,


Это весь код. Создадим входную матрицу:
  ]m =: 9 9 $"."0 '200370009009200007001004002050000800008000900006000040900100500800007600400089001'
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


Применяем к ней глагол и получаем решение:
  s 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

Более короткие решения
Показанный выше код состоит из 148 символов, включая пробелы и переносы строк. Есть решения короче. Например:
http://nsl.com/k/sudoku/aw3.k
Это решение занимает всего 72 (!!!) символа. Но это решение Артура Уитни, создателя языка К. И решение на К. Артур Уитни – Бог программирования, соревноваться с ним не имеет смысла.
Мое решение содержит незначащие пробелы, вокруг присваивания (минус 10 символов) и можно еще «заинлайнить» глаголы, что тоже поможет выиграть несколько символов. Но не хочу ради краткости ломать красивый и понятный код ))

Уверен, что для J существуют способы написать короче, а у меня сказывается недостаток опыта.


3. Prolog

Хочется показать код на J для более практичной задачи и не близкой к матрицам/массивам. Слышал сомнения, что векторный подход подходит для парсинга. Пришла идея выбрать простую задачу для поста, решение которой связано с парсингом. Реализую Prolog. Точнее, не весь Prolog, т.к. задача не практическая и времени и усилий много тратить не хочется. Это будет подмножество Prolog-а, чтобы показать, что в принципе таситная форма записи годится и для таких задач. В этом Prolog-е, если его так можно назвать, не будет даже отсечения. Только простые факты и правила, операция «и», «или». Итак, код:

  frq =: [:-.[:(2:|+/)\''''&=
  
sp =: (#@[)([:<[}.[:>])"0 0[(]</.~[:+/\E.*.[:frq]),
  
spf =: [:<[:([:','&sp[:-.&')'=&'('{"0 1,.&',')>
  
cl =: #~[:-.e.&(33{.a.)*.frq
  parse
=: [:([:<[:((spf@{.),(}.`([:<[:([:<[:spf"0[:'),'&sp>)"0[:');'&sp[:>{:)@.(2:=#)))[:':-'&sp>)"0 _1:}.[:'.'&sp cl

  isVar
=: [:(91&>*.64&<)[:a.&i.[:{.>
  
replace =: ((]i.~[:{.[){([:{:[),]`([:<[$:[:>])@.([:32&=[:3!:0[:>]))"2 0
  
gp =: [:>[:{.>
  
gv =: [:(#~[:+./"1 isVar"0),.
  
suit =: ([(0:`(([:(#=[:#[:~.[:{.|:)[:~.[:(#~[:-.[:isVar"0[:{:|:)gv)*.([:*./[:+./[:(isVar"0,=/),:))@.(([:#[)=[:#]))[:gp])"1 0#]
  
sr =: [(](replace~[:|:])"2[:(([:-.[:isVar{:)"1#])[gv~[:gp])"1 0 suit
  groupVars
=: [:([:<]$~2:,~[:-:#)"1[:>[:([:<[:;(>@[)([:<,"1 1)"1 2(>@]))/]</.~[:{.|:
  
isRuleTrue =: ([:+./([:*./](isTrue~[:>])"1 0[:>[)"0 1)`(0:<[:#getVarsFromRule)@.(0:<#@gv@;@;@[)
  
isTrue =: ]((a:&e.@])+.[:+./[(isRuleTrue~[:>])"1 0[:-.&a:])[:{:[:|:[:-.&(a:,a:)[:(0 2$a:)&,[:>sr
  getVars
=: ;(([:<[:~.(>@{.@[)gv[:gp])`((>@{.@[)$:(<@<@gp@])([replace~[:|:[:>])"0 0(}.@[)getVarsFromRule~[:>[:{:[:>])@.([:<:[:#[:>]))"1 0 sr
  getVarsFromRule
=: ](([:{.])#~[(isRuleTrue~[:>])"1 0[:{:])[:|:[(],[:<[replace~[:|:[:>])"1 0[:]`groupVars@.(0:<#)[:~.[:;[:;]([:<[getVars~[:>])"1 0[:;[

  goal =: ([:<S:0[:{.[:parse[:,&'.'])([:{&(>'No';'Yes')isTrue)`([:(]`((>@{.),[:' = '&,[:>{:)@.(2:=#))"1[:>getVars)@.([:+./[:isVar"0[)([:parse[)

Это весь код. Собственно, парсер в первой части решения. Задача парсинга такого простого Prolog-а, конечно, примитивна. Но всё же, J можно применять для парсинга. И для более сложных задач парсинга.
Единственная «сложность» в парсере — Prolog допускает создание атомов из произвольных символов, если они берутся в одинарные кавычки. Иначе парсер был бы значительно короче. И еще, я специально не пользуюсь никакими библиотечными глаголами. Для того, чтобы вы оценили мощь самого языка, насколько быстро можно что-то написать с нуля. Есть и библиотека для работы с текстом. Есть библиотека для работы с регулярными выражениями.

Зададим код на Prolog-е:
  prolog_code =: 0 : 0
male(jeff).
male(fred).
female(mary).
parents(jeff, vince, jane).
parents(mary, vince, jane).

sister_of(X,Y) :- female(X),
      parents(X, F, M),
      parents(Y, F, M).
)
  

И пару вопросов.
«Приходится ли Мери сестрой Фреду?»:
  prolog_code goal 'sister_of(mary, fred)'
No

«Кому Мери приходится сестрой?»:
  prolog_code goal 'sister_of(mary, X)'
X = jeff

X = mary


Заключение


Надеюсь, вы прониклись тем, как на J можно кратко решать сложные задачи. На счет легкости, у вас, возможно, сомнения.

Цель примеров – показать код в таситной форме. Вы обратили внимание на то, что в коде практически нет каких-то нестандартных библиотечных глаголов? Весь код почти состоит из пунктуации. Это элементарные глаголы J. Конечно, никто не заставляет писать так, не вводя свои глаголы, не давая им осмысленных имен. Но высокоуровневость J предрасполагает в силу краткости кода не вводить новые имена. Цена усилий на создание нового кода мала, что приводит к тому, что реже хочется код прятать за именем. В целом со временем это приводит к тому, что программист на J читает одни и те же глаголы, которых не так много, и со временем учится всё лучше и лучше читать код. Код становится яснее и яснее.

Я думаю, что каждый программист, работающий на каком-то мейнстримном ООП-языке, с грустью согласится, какой сейчас ад с библиотеками и фреймворками. Правильные практики программирования призывают инкапсулировать код, прятать за осмысленными именами. Если усилия на создание кода достаточно велики – больше появляется имен. И когда вы, например, приходите в новый коллектив работать с проектом, от языка в коде мало что остается – вам нужно изучать новые для вас сущности, всё, чему дали имена предыдущие программисты. Изучение нового языка всегда грозит изучением библиотек, а их количество стремительно растет. J не решает эту проблему, но отдаляет.

J как язык имеет достаточно высокий порог вхождения. Поначалу он практически не читаем. Вы, изучив все глаголы, сможете с трудом на нем писать, но читать даже свой код не сможете. Но со временем, сможете это делать всё легче и легче. Это не произойдет с другими языками.

Также, надо упомянуть, что это не значит, что J имеет слабую поддержку и в нем недостаточно библиотек. Много уже наработок, от работы с excel-файлами, базами данных, до работы с видео. Также J мультипарадигменный, на нем можно писать не только в tacit форме, но и в императивной. С циклами и ветвлениями. С обработкой ошибок. J поддерживает ООП.

Работа с J напоминает не кодирование, а вывод формулы. Вы, поначалу, будете всматриваться в код, скорость набора значительно ниже. Но при всем при этом, результат даже поначалу будет получаться быстрее, чем в других языках. Даже не имея сверхбольшого опыта и читаемости кода, через время окажется, что сесть решить задачу на J кажется гораздо проще, чем решить на любом другом, более знакомом языке. Работа с J напоминает работу с мощным калькулятором, а не языком программирования. У вас нет ощущения, что вы создаете что-то на века. Скорость получения результата дает больше смелости в кодировании и вы легче пробуете различные варианты.

Благодаря этому у J есть ниша – обработка данных, особенно в финансовой сфере. На J легко «вращать» данными, проверять различные гипотезы. А если нужно – сохранить скрипт и использовать как программу. J удобен в проектах для обработки данных. Там где нужны сложные алгоритмы. Причем, под сложностью алгоритмов я подразумеваю «полезную сложность», т.е. сложность преобразования данных, а не алгоритмы для оптимизации. При всём при этом, J достаточно производителен. Пусть вас не пугает то, что он интерпретатор. Интерпретатор он только в том плане, что выполняет выражения построчно. Но если в строке записано выражение глагола, то он его выполняет один раз, запоминая, а далее при применении глагола к данным, работает уже быстро. Т.к. обрабатываются обычно данные большого объема, то оптимизации в J показывают неплохую производительность. Также J может работать с библиотеками, написанными на других языках. Что позволяет оптимизировать проблемные места.

Этот язык благодаря своим свойствам, хорош для создания прототипов. При этом прототип имеет большие шансы не быть переписанным, т.к. или производительность будет устраивать, или можно провести оптимизации только проблемных участков.

Это всё хорошо, но есть одна проблема в использовании J в командных проектах – мало специалистов. Если вы решите использовать J в проекте, то высокая вероятность, что не найдете людей.

И, тем не менее, J можно использовать не только для командной работы. Он дает сильный обучающий эффект. Работа с J меняет взгляды на алгоритмы в целом, «выворачивает сознание». Оказывает положительное влияние на работу с другими языками.

Также этот язык очень удобен для работы, как вспомогательный язык. У меня среда J всегда открыта и я не пользуюсь калькулятором или excel. Когда нужно распарсить что-то или сгенерировать код для другого языка – J – отличное средство.

Ссылки


1. Официальный сайт: www.jsoftware.com
2. Предлагаю почитать отличную статью — Язык программирования J, введение
+74
56328
177
m36 40,5

Комментарии (128)

0
Monnoroch #
Глаголы — это как в хаскеле point-free нотация, это круто; только, если переменных несколько, то начинается ад, чтобы растасовать их по нужным операциям.
+14
SamKrew #
Теперь я точно знаю, что моя жена — программист на J. В смсках тонна с̶м̶а̶й̶л̶и̶к̶о̶в̶ кода.
+47
Indexator #
Жесть! Это как программирование через регулярные выражения…
Нет, вы меня не заставите! Больше никогда!
+46
ncix #
Я такие языки называю «Write-only language» (WoL). Пояснять, думаю, не надо.
Есть WoL и среди популярных языков — XSL и regexp.
В некоторых клинических случаях и SQL в него превращается, несмотря на максимальную близость к естественным языкам.
+15
m36 #
Наверное не совсем донес идею, а наоборот испугал непонятным кодом.

Он не такой уже непонятный. Чтобы понимать язык, нужно знать его слова. Джей по словам-примитивам намного богаче, чем привычные языки программирования. Например, никого не убивает в С++, операция >>, или ++, или просто скобки {}, служебное слово class и тому подобное.
Также и здесь.
Я в посте хотел объяснить именно эту логику, потому что люди думают эмоциями в таких случаях. Если вас пугает синтаксис, то это где-то аналогично, как пугаться иностранного языка и думать, что им пользуются дураки только – он же на ваш родной не похож. Это «попроще» — просто ваши ожидания от языка. Вам хочется, чтобы он сразу был понятен. Не изучая слова. Но тогда, он либо должен быть похож на естественный язык, причем желательно родной (а таких нет еще), либо не содержать слов, а позволять их побольше самому писать. В этом случае, заметьте, что вы бъете по своим воротам. Разве не надоело в каждой новой компании разбиратьяс я с новым методом DoSomethingEveryYearBefore2012? Слова понятны, но они не из языка программирования – это наносное. А наносят бог весть что. И каждый раз нет претензий к самому языку, претензии только к предыдущим именователям.
Ожидания от языка, которого вы не знаете, не всегда играют хорошую роль. Этих глаголов здесь штук 150 и за долгое время работы они становятся узнаваемыми. Правила комбинирования глаголов довольно простые. Поэтому, еще очень спорный вопрос, на каком языке код понятнее.
Далее, наиболее важный плюс джея – это работа с многомерными массивами. Т.е. представьте себе алгоритмическую сторону ваших программ. Вам часто надо создать массив. Тут делается элементарно. Хотите траспонировать? |: без проблем. Хотите развернуть список/массив. |. без проблем. Хотите уникальные элементы найти? ~. без проблем. Вот эти маленькие комбинации избавляют вас от кучи кода в других языках и вы мыслите совсем на другом уровне. Код без циклов, практически, вы только вращаете кубы, клеите их, находите пересечения, проекции – что угодно. А то, что эти операции обозначаются значками – это во-первых кода меньше, а во-вторых не особо им из нашего мира дашь подходящее название. Это векторно-массивные операции. Которыми можно легко выражать почти любой алгоритм.
+34
marshinov #
Он не такой уже непонятный. Чтобы понимать язык, нужно знать его слова. Джей по словам-примитивам намного богаче, чем привычные языки программирования. Например, никого не убивает в С++, операция >>, или ++, или просто скобки {}, служебное слово class и тому подобное.
Также и здесь.

Позволю с вами не согласиться.
isVar =: [:(91&>*.64&<)[:a.&i.[:{.>
replace =: ((]i.~[:{.[){([:{:[),]`([:<[$:[:>])@.([:32&=[:3!:0[:>]))«2 0
gp =: [:>[:{.>
gv =: [:(#~[:+./»1 isVar«0),.
suit =: ([(0:`(([:(#=[:#[:~.[:{.|:)[:~.[:(#~[:-.[:isVar»0[:{:|:)gv)*.([:*./[:+./[:(isVar«0,=/),:))@.(([:#[)=[:#]))[:gp])»1 0#]
sr =: [(](replace~[:|:])«2[:(([:-.[:isVar{:)»1#])[gv~[:gp])«1 0 suit
groupVars =: [:([:<]$~2:,~[:-:#)»1[:>[:([:<[:;(>@[)([:<,«1 1)»1 2(>@]))/]</.~[:{.|:
isRuleTrue =: ([:+./([:*./](isTrue~[:>])«1 0[:>[)»0 1)`(0:<[:#getVarsFromRule)@.(0:<#@gv@;@;@[)
isTrue =: ]((a:&e.@])+.[:+./[(isRuleTrue~[:>])«1 0[:-.&a:])[:{:[:|:[:-.&(a:,a:)[:(0 2$a:)&,[:>sr
getVars =: ;(([:<[:~.(>@{.@[)gv[:gp])`((>@{.@[)$:(<@<@gp@])([replace~[:|:[:>])»0 0(}.@[)getVarsFromRule~[:>[:{:[:>])@.([:<:[:#[:>]))«1 0 sr
getVarsFromRule =: ](([:{.])#~[(isRuleTrue~[:>])»1 0[:{:])[:|:[(],[:<[replace~[:|:[:>])«1 0[:]`groupVars@.(0:<#)[:~.[:;[:;]([:<[getVars~[:>])»1 0[:;[

Вот это вообще не понятно, не читаемо и невозможно поддерживать.
+7
m36 #
Вам да. Также, как и китайский язык. Непонятен и перевести невозможно.
+21
Bal #
Пример некорректный. Есть особенности работы человеческого мозга, которые не позволяют эффективно парсить подобные структуры.

Код на чистом китайском же, при наличии практики, как раз будет распознаваться вполне адекватно.

Эргономика — давно не шаманство, а вполне точная наука, при чём часто не эмпирическая, а базирующаяся на той же нейрофизиологии (в конкретике распознавания).
0
m36 #
Есть особенности работы человеческого мозга, которые не позволяют эффективно парсить подобные структуры.


В отношении джея это утверждение для меня не очевидно. А личный опыт говорит об обратном.
Люди говорят, что в Лиспе скобки — самое вкусное. И что это круто. Я их не понимаю, потому как глазами разбирать, где какая скобка закрывается — мне неуютно. Джей же как раз наоборот — эргономичен. Вилки и крючки (правила построения выражений) как раз минимизируют скобки, позволяют писать и читать линейно сложные алгоритмы, а не только последовательные преобразования.

Да, джей конечно, позволяет и говнокод писать. И мой вот этот код, кстати, не показатель. Я его не особо напрягаясь написал, не рефакторил. Там в конце слишком длинные строчки (у меня большой широкий монитор )), может больше скобок чем нужно. Но для меня этот код еще в зоне комфорта, я с ним справляюсь, читаю, мог бы и пострашнее написать.

Кстати, в этом тоже плюс джея. На нем можно достаточно легко написать вот такие длинные большие штуки и они работают. И не париться. Там внизу писали, что джей используется когда много данных и мало времени. Это отчасти верно. Джей — он как инструмент для быстрой обработки данных, здесь и сейчас. Иногда и не надо ничего рефакторить, возможно, это одноразовый был бы код в реальной задаче.
+6
Bal #
>В отношении джея это утверждение для меня не очевидно.

Оно очевидно хотя бы тем, что мозг человека не умеет распознавать число «закорючек». Не важно, скобки это или крючки. Только медленным пересчётом по одной. Из-за этой особенности и родилось структурное программирование, которое позволяет разделить блоки визуально на порядки ускоряя распознавание структуры. Вы же в J от этого принципа отходите, на чём сильно проигрываете в анализе кода.
+1
Flammar #
Эргономичность языка программирования сильно зависит от IDE, в которой на нём пишут. Читабельность «функционального стиля» на Java1.6+GoogleCollections сильно больше в IDE, чем в без неё. Особенно это видно при сравнении такого стиля с работой через традиционные циклы — с IDE писать «функционально» и читать «функциональный» код становится лучше и проще по сравнению с ними.
+1
withoutuniverse #
Я знаю синтаксис с++ подобного языка программирования.
Если мне понадобится найти велосипедный алгоритм, я пойму любой из языков, похожий на с++, java, c#, as3, pascal и прочие. Я смогу использовать найденный код, даже если придется его переписать.
Если взять ваш пример с языками, то с++ подобные языки — русский, белорусский, украинский. Язык J в таком случае можно отнести к китайскому.
+2
Flammar #
Язык J в таком случае можно отнести к китайскому.
Язык J в таком случае претендует на место Ithkuil'a или даже чего-то более мощного…
–2
m36 #
А вам не очевидно, что я, например, вполне себе читаю, иначе бы просто не смог бы написать сколько кода write-only?

isVar =: [:(91&>*.64&<)[:a.&i.[:{.>

Отрыть коробку, взять первый элемент со списка (символ), узнать его номер в алфавите (ASCII), и истина, если он входит в интервал — (91;64) — и называется isVar. Вспоминаем, что в прологе переменные пишутся с большой буквы.
Читается такой код элементарно, никаких хитростей нет. Просто надо знать эти элементарные глаголы и правила построения выражений.
+4
ncix #
Скажите, а какой современный язык программирования вам не знаком? Готов поспорить, что если такой есть, вы легко сможете понять по коду о чем речь в принципе.
Теперь возьмем разработчика на этом языке и покажем ему программу на J.
<реакцию вы и так знаете>

Теперь надеюсь понятно, в чем разница?

Но, в любом случае спасибо вам за статью, очень полезно бывает расширить кругозор.
–4
m36 #
C#, допустим.
Готов поспорить, что если бы программист написал методами или в одном методе код, то в любом случае этот код выше читается намного проще. Просто пройтись глазами справа налево.
И это простенький глагол. Если бы написали побольше алгоритм, то мне только на небо надо было бы надеяться, что программист, назвав как-то метод в другом классе в другом файле, делает в том методе то, что говорит его название. Если оно говорит.

Только linq где-то сравнится с джеем, но оно не достаточно мощное, кода раза в 4 будет больше обычно. И более захламлен точками, скобками методов, ненужным именами параметров.

А вообще, где-то похоже по ощущениям. На джее вообще, ощущения как и на SQL. Только на последнем реально бывает очень тяжело выразить довольно простые мысли, в отличии от джея. Где-то в мозгах так же на SQL комбинируете множества, как и на джее, но там сложности из-за отсутствия упорядоченности, индексного доступа. На джее же всё пишется легко.
+24
sheknitrtch #
Простите, но синтаксис языка J сделан не для людей. Например: глагол деления — %, запись отрицательных чисел — _4, _10, глагол вычисления корня — %:
Это контринтуитивно. И мне, как математику и программисту, запись
max(a) + sum(a)/len(a)

понятнее, проще для поддержки и поиска ошибок, чем
d =: >./++/%#
d a
–2
m36 #
позвольте возразить )

На счет выбора знаков, почему именно эти — я не в курсе истории. Наверняка были на то причины.

Но вот это:
max(a) + sum(a)/len(a)
понятно, пока оно просто. А так:
sum(a)/len(a) + max(a)
Тоже понятно. Тогда так:
sum(a)/len(a)<<2 + max(a) Упс, уже надо смотреть приоритеты.
А если надо к сумме добавить максимальное, а потом всё поделить? Только скобки. Когда как в джее всего лишь меняются местами операции. Если выражения усложняются, то вам как математику и программисту на каком-то уровне придется пойти покурить и передохнуть, чтобы понять длинное выражение со скобочками.

В этом то и плюс джея — вилки и крючки. И отсутствие приоритета операций. Именно это и позволяет писать большие выражения, а потом так же их легко читать. Вам сейчас просто кажется из-за незнания синтаксиса, что там ужас написан. Но привыкнув к нему, он начинает давать профит. В лиспе, например, тоже передумали писать, как привыкли математики. И не для усложнения, а для упрощения.
+11
sheknitrtch #
Позвольте возразить. Вы постоянно говорите, что после многолетнего опыта языка J можете легко читать сложные выражения, так вот программисту достаточно неделю учить язык Python, чтобы прочитать вот это

[ days[i:i+7] for i in range(0, len(days), 7) ]


Если выражения усложняются, то вам как математику и программисту на каком-то уровне придется пойти покурить и передохнуть, чтобы понять длинное выражение со скобочками.

В современных языках как раз избегают писать длинные выражения в одну строку. Гораздо понятнее и удобнее разбивать сложный алгоритм на несколько более простых, которые затем комбинируются понятными операторами.
В языке J наоборот стараются много действий закодировать в короткой записи. Только встаёт вопрос отладки таких программ. Как быстро вы сможете найти ошибку в следующем алгоритме?

s =: ({. , }. /: 12"_ o. }. - {.) @: /:~
g =: _2: }. 0: > (-~1&|.) 11&0.@:* +@:(-~ 2&|.)
r =: (1"_ , g , 1"_) # ]
hull2 =: [: r^:_ s

Подсказка: это алгоритм нахождения выпуклой оболочки ;)
–15
m36 #
В современных языках как раз избегают писать длинные выражения в одну строку. Гораздо понятнее и удобнее разбивать сложный алгоритм на несколько более простых, которые затем комбинируются понятными операторами.

Так это не недостаток джея, а преимущество.
Разбивают код на куски, когда внимание не справляется. Чем лучше сделан язык, чем меньше напрягается внимание при чтении, тем бОльшие куски способен программист «обработать» за раз. Слишком много маленьких кусков — каждый может и понятен, но на уровень выше проблема — слишком много кусков.

В общем, джей позволяет писать бОльшими кусками и не запрещает разбивать на меньшие.

Как быстро вы сможете найти ошибку в следующем алгоритме?

Плотно в проектах я давно с джеем работал. С тех пор развилось IDE хорошо, появились какие-то средства отладки. Но вообще, ни разу как-то не видел надобности в таких средствах. Действительно, через время пишется на этом языке легко. А в побольше проектах надежность кода гарантируется как обычно — юнит-тестами.
0
m36 #
Странно, за что столько минусов? Где я не логичен?

Джей как язык не запрещает разбивать на какие угодно куски. Поэтому он в этом плане не хуже других. Джей ко всему этому позволяет снизить нагрузку на внимание и писать бОльшие куски кода, находясь в зоне комфорта. Т.е. значит, он лучше, не так ли?

То, что вы критикуете, что программист пишет большую часть логики в одном предложении, так это потому, что для него так комфортно писать, что есть, несомненно, плюсом. И ваша критика основывается только на непонимании, почему этот программист понимает этот код. А именно, не знание глаголов и правил построения. Вам кажется тот код сложным? Чистый и простой код. Просто обратите внимание на скобки. Их много? Нет. Если их не много, то внутри код читается линейно. Давайте разберем первое:
s =: ({., }. /: 12"_ o. }. — {.) @: /:~

справа налево. Первый глагол:
/:~
Обозначает отсортировать по возрастанию. Тут наверное вектор, т.к. в задаче вектор. Я давно статью читал и вообще в код не вникаю сейчас, с нуля разбираем. Сортировка — понятно, что это такое.
Далее союз @: — говорит, что после сортировки надо делать то, что в скобках.
В скобках берем три первых (с конца) глагола:
}. — {.
Отсечь голову вектора (списка) и от этого получившегося списка отнять голову.
Следующие два глагола берем:
12"_ o. }. — {.
Сначала выполняется первый левый, потом тот, что посредине, берет правую (уже вычисленную раннее) и левую часть.
12"_ — это хитрый глагол, порождающий константу (12), вне зависимости от аргументов. Просто число не подошло бы, т.к. требуется глагол, а не существительное. Т.е. по сути, далее, если в прямом режиме, без глаголов писать, то выполнится выражение:
12 o. к нашему обрезанному и отнятому списку
12 o. — это поиск угла комплексного числа. К списку применяется, значит там список комплексных чисел — применится к каждому. Берем новые два глагола:
}. /: 12"_ o. }. — {.
То же самое. Сразу левый выполняем — отрезать голову исходному отсортированному (за скобками вначале) списку. И диадный глагол сортировки — это значит, что находим перестановку для углов справа и в этом порядке располагаем список слева. Т.е. перемещаем все комплексные числа так, чтобы углы, если их взять, были отсортированы.
Снова берем два глагола:
{. ,}. /: 12"_ o. }. — {.
Взять голову отсортированного списка и запятой приклеить к списку справа — т.е. отсортированному (без головы)

Всё.
Ничего сложного в разборе такого выражения нет, оно читается линейно.
Коротко и словами объяснить, что делает глагол? находится наименьший элемент из комплексных чисел (сначала ищут по действительно части, потом по мнимой), далее точки сортируются по углам относительно него.

+1
Googolplex #
Я полагаю, дело в том, что, например (если я правильно понял ваше объяснение) такой код:

def order(numbers: List[Complex]): List[Complex] = {
  val minimal = numbers.min
  numbers.sortBy(number => abs(number.phase - minimal.phase))
}


(который аж в пять раз больше, какой ужас!) может понять практически любой программист, имеющий минимальные навыки хотя бы в одном современном языке, не обязательно в Scala. Программист, начинающий изучать Scala, но без бэкграунда в других языках, это тоже, скорее всего, поймёт, причём очень быстро.

А код, который вы только что разобрали, непонятен не только непосвящённым (вот откуда можно понять, что 12 o . — это взятие фазы комплексного числа, а?), но я боюсь, и начинающим изучать J тоже.
+1
m36 #
Этот код, который написан, понятен и да, он больше. Но он понятен, но не использует по всей видимости только изначальные языковые вещи. (Я не знаю Питон).
sortBy — это скорее уже библиотечная функция, как и тип List, даже если они из коробки.

Почему это важно? Потому что я показал разбор только одной строки, которая удачно, только с сортировкой связана. На джее таким же образом можно сделать всё. Кстати, у вас голова не вычитается, это меняет алгоритм, потому как 0 может получиться не только у самого себя, но и у точек на одной линии. Далее, вы не сортируете углы относительно минимальной точки. Вы сортируете углы относительно 0+j0, просто отняв угол минимальной точки и взяв абсолютное значение. Это был тест, насколько я пойму код другого неизвестного языка?

На джее, аналогичный вашему код будет поменьше:

s =: /:[:|-/12"_ o.],:<./


И специально, для ненавидящих таситную форму джея и любителей абстракций, то же самое в экслисит форме с именами, чтобы не раздражали значки глаз:
min =: <./
angle =: 12&o.
sortBy =: /:
abs =: |

s =: monad define
   y sortBy abs
(angle y) (angle min y)
)



Как видите, этот код не хуже вашего питоновского, но он все же хуже того, что в таситной форме как по мне.
Почему 12 выбрано? Это к создателям джея. Это язык такой, что там элеметнарным глаголам имена не раздаются направо и налево. o. применяется для разных случаев.
0
m36 #
Я извините, не внимателен. Scala, а не Питон.
0
Googolplex #
Далее, вы не сортируете углы относительно минимальной точки. Вы сортируете углы относительно 0+j0, просто отняв угол минимальной точки и взяв абсолютное значение.

Значит, я не понял ваших объяснений. Я, к сожалению, не помню сходу алгоритм нахождения выпуклой оболочки, использующий комплексные числа, и из кода на J, естественно, я его тоже не понял.

Что такое «сортировка углов относительно минимальной точки» также не совсем понятно. Для меня эта фраза означает «сортировка значений углов по метрике в R относительно угла минимальной точки», и это именно то, что я написал.

Но он понятен, но не использует по всей видимости только изначальные языковые вещи. (Я не знаю Питон).
sortBy — это скорее уже библиотечная функция, как и тип List, даже если они из коробки.

Почему это важно? Потому что я показал разбор только одной строки, которая удачно, только с сортировкой связана. На джее таким же образом можно сделать всё.

Я опять не понял, что вы хотели сказать. Вы имеете в виду, что те глаголы, которые использу.ются в примере, встроены в язык, а типы и методы вроде List и sortBy являются частью стандартной библиотеки? А какая разница? Из Scala стандартную библиотеку убрать нельзя в принципе, поэтому классы коллекций вполне можно считать частью языка как платформы. Я не вижу существенной разницы этого с наличием встроенного в язык функционала, разве что последнее менее гибко.

o. применяется для разных случаев.
Есть такой очень важный принцип, особенно в обучении. Называется «принцип наименьшего удивления». Когда я вижу sortBy, я могу с достаточной долей уверенности предполагать, что это какой-то вариант сортировки. Приставка By также намекает, что мы будем указывать то, с помощью чего нужно сортировать. То же самое с фазой комплексного числа: minimal.phase, особенно в контексте того, что minimal имеет тип Complex, однозначно говорит, что мы хотим взять значение фазы. 12 o., к сожалению, об этом говорит чуть менее, чем никак. Особенно если учесть, что, судя по всему, 13 o. и 11 o. будут делать что-то совершенно другое, если это вообще будут корректные выражения.

В этом, собственно, и ответ на ваш вопрос. Вы не только утверждаете, что это очевидно и легко (с этим, в принципе, я могу согласиться — для кого-то продвинутая теория категорий или тот же китайский легки и понятны, всё-таки всё в мире относительно), но вы также утверждаете, что это проще и понятнее, чем идентификаторы, приближенные к человеческому пониманию кода. Я так полагаю, что именно с этой вашей позицией здесь и не согласны.
0
m36 #
Я опять не понял, что вы хотели сказать. Вы имеете в виду, что те глаголы, которые использу.ются в примере, встроены в язык, а типы и методы вроде List и sortBy являются частью стандартной библиотеки? А какая разница?

Разница небольшая, но есть. Просто я показал как разобрать удачную для Scalа строку джея. Но джей с нуля позволяет и другие, неудобные для других языков вещи писать кратко. Все таки — это работа с многомерными массивами, а не списками.
Вот, расскажу, что делается в предыдущем примере в этом коде. Хотя код аналогичен вашему, но мог бы быть и другим.
s =: /:[:|-/12"_ o.],:<./


Найти минимальный элемент. Склеить его снизу к входящему вектору, получить двумерную матрицу. НАпример такую

3 7 8 2 9
2 2 2 2 2
Найти у каждого элемента угол. И отнять от второй строки первую. Далее, найти перестановку для сортировки этого массива и применить эту сортировку к исходному массиву.

Да, это Спарта. Но в джее мышление немного как бы шире списков. Этим он и прекрасен.

То, что там непонятные значки, так это из-за таситности записи. Из-за крючков и вилок. Значок легко пишется рядом с другим и несложно отличается. Если бы была надобность только буквенные названия глаголам писать — это как раз был бы ад. Никакой таситной формы бы не получилось. Между каждым надо пробел, имена длинные — какая же тогда вилка или крючек? Три глагола — и приехали, строка закончилась.

А отказываться от этой формы записи только ради понятных названий — это бессмысленно, если поработать с этой формой. Она таки прекрасна и позволяет выражать даже сложные задачи линейно, в одну линию, часто без скобок, и читается легко по порядку, не сносит мозг группировками.

Потом, эти значки — это операции с массивами, а не привычные нашему ООП-мозгу названия из нашего реального мира. Тяжело им названия подавать и чтобы они были более понятные чем значки. Тут нет объекта птичка или бизнес-правило. Если soryBy еще куда ни шло, то там есть и похитрее операции. Плюс к этому, джеист мыслит этими многомерными массивами, его воображаемая очевидность для вас будет совсем не очевидна, даже если он назовет.

Однажды меня попросили описать алгоритм для документа, это была жесть. Мне надо было или врать, или говорить: берем 6-ранговый массив, меняем 3 ранг с пятым и находим проекцию на вектор с операцией агрегации такой-то. Технический писатель отказалась переводить и оформлять этот документ.

Так что тяжело в учении — легко в бою. Эти значки — неплохая и вынужденная вещь. Я думаю, было бы лучше, если бы там были по одному символу на глагол значки и какие-то покрасивее, чтобы картинка подсказывала, что за операция. Но клавиатуры не позволяют. И вообще, это не критичная проблема. За неделю можно заучить все эти комбинации.

НЛО прилетело и опубликовало эту надпись здесь
0
m36 #
А, я не понял вопрос правильно, понял как общий вопрос, сколько бы я искал ошибку в коде джея такого объема.

Я не знаю алгоритма выпуклой точки, читать не хочется. В принципе он где-то понятен, сортировки по углам и обход, но если брать ваш код, то вполне читается.

11&0. — это свалит джей, т.к. нет глагола с цифрой ноль и точкой. буква о с точкой есть. Если вы сюда внесли ошибку. Вообще эта «хитрость» с нулем ищется почти мгновенно, если это в IDE перенести. Глагол о. зеленым рисуется, цифра фиолетовым. Т.е. даже если шрифты бы были неудобные

И читается он также легко.
Второй глагол (g) описывать не буду, т.к. голова у читающих сломается. Там два сдвига вектора, на один и два элемента, разности с исходными, поиск сопряженного, перемножение их, нахождение углов, проверка, меньше углы нуля и отрезать два с хвоста. Всё читается, много логики, а что за логика, надо смотреть — зачем это в алгоритме. Этот глагол вычисляет булевский вектор. Если вас пугает такая сложность и много логики в этом глаголе, то представьте себе этот код на Си. Он не будет понятнее. Сложный алгоритм и останется сложным, для тех, кто не понимает, зачем производятся такие действия (не знает алгоритма) и такой математики, допустим, что такое сопряженное число.

Третий глагол добавляет единицы в голову и хвост вектору, который вернул второй глагол g. Он возвращал без двух элементов, этот глагол их добавляет. И применяет вектор как фильтр к аргументу.

Ну и последний: применяет s — т.е. сортирует по углам исходный вектор. А далее, применяет r в цикле, до тех пор, пока вектор не перестанет меняться.

Неясность моего описания связана только со сложностью алгоритма, а не с джеем. Джей ничего не усложняет
+5
Bal #
В этом то и плюс джея — вилки и крючки. И отсутствие приоритета операций.


Тогда куда приятнее Forth. Отсутствие приоритета при отсутствии «вилок и крючков» :) А программы мало того, что прекрасно читаются, так ещё самодокументируемость считается важнейшим атрибутом «thinking forth». В J же писать самодокументирующиеся программы, как я понимаю, вообще невозможно. Соответственно, придётся тратить время сперва на параллельное документирование, потом, время спустя — на синхронизацию комментариев и изменений.
0
Flammar #
C++, кстати, тоже многими и давно считается «Write-only language»… В С++11 что-то улучшили, правда…
НЛО прилетело и опубликовало эту надпись здесь
+7
ncix #
Да, я согласен, что язык состоит из слов и их можно выучить.Но есть важное отличие J от всех современных высокоуровневых языков. Все современные языки как раз таки стараются быть похожими на естественный, и двигаются в этом направлении (например C->C++->C#). Таким образом, программист на Delphi не особо напрягаясь может понять программу на C++, хотя бы концептуально, даже если никогда на плюсах ни строчки не написал.

Понять J не зная его — невозможно.

И второй момент — комментарии. Я не представляю как в эту адовую конструкцию их вставить. Раскроете тайну?
0
m36 #
а, да. Комментарии нужны, просто я хотел кпд языка показать. Обычно, под каждый глагол аннотацию желательно писать. Потому как глаголы обобщенные, но часто при создании глагола программист какие-то ожидания на них вешает, тип массива например. Вот, в isVar нужно передавать бокс с текстовой строкой. Хотя, из тела видно, но можно, обычно пишут.

Комментарий после NB.

Не особо плюсы или шарп и естественные. Они позволяют просто давать имена. А ООП ближе к естественному мышлению, чем массивное программирование. Но имена и здесь в джее хорошо даются глаголам, можно и классы писать. Никакой разницы в этом нет. Просто джей позволяет это делать меньше. Хотите, делайте очень маленькие простые глаголы и каждому давайте имя. Будет как в С++
+10
Ataraxer #
Вы одержимы идеей минимализации кода, причем в очень болезненной форме. Когда я прочитал в этом году замечательную книжку про Haskell (дада, ту самую, со слоником) и крайне впечатлился его элегантностью и экспрессивностью мне тоже стало противно писать длинные конструкции на других языка, вспоминая, как легко то же самое можно выразить на Haskell какой-нибудь простенькой композицей функций. Вот только Haskell при этом действительно остается читаемым (если не перебарщивать символьными операторами и хорошо структурировать свой код), а J — это просто набор закорючек, которые превартятся в тыкву, как только их попытается прочитать человек отличный от того, кто их написал.
+1
Flammar #
делайте очень маленькие простые глаголы и каждому давайте имя
Изрядная морока — 60% рабочего времени придумывать имена, причём уникальные, причем непонятно в каком scope-е уникальные…
0
Flammar #
SQL я вообще не смотрю без Notepad++ с PoorMan'sSQLFormatter…
0
Flammar #
regexp
Ага, без переменных и констант любой язык стал бы «Write-only»…
+7
suguby #
вел у нас факультет по программированию в далеком 87 году странный дядечка, мы к нему ходили на ВЦ программить на APL на ДВК (!) в 9-м то классе…
листинги я хранил до института, на первом уже курсе забыл что это такое написаное, на 3-м выкинул.
До сих пор помню инстайт понимания как «оно массивы обрабатывает» :) на ДВК кстати было много странных символов на клаве, да.

не хочу сейчас в такое врубаться. python лучше :)
+5
ncix #
А я вот открыл программу, которую писал 15 лет назад на QuickBasic. Написано конечно адово, но в целом все ясно.
+3
Bal #
Бейсик отличается как раз очень простым и прозрачным синтаксисом. В этом плане хорош и его внук — Python. Хотя, конечно, уже заметно сложнее и неоднозначнее. Но на подобных языках, действительно, проще поддерживать код. Как свой, годы спустя, так и чужой. Одной из причин (хотя далеко не единственной), по которым я с Perl ушёл — даже при постоянном самоконтроле всё равно так и норовил где-то сэкономить и влепить оборот, который сложно понять в своём коде несколько лет спустя.
0
bolk #
С чего вдруг Пайтон стал внуком Бейсика?
+3
Bal #
Python создавался под влиянием ABC (и с опытом его разработки). ABC создавался как улучшенный Бейсик.

Вообще, я ещё не зная про это родство, когда первый раз Питон увидел, сразу о Бейсике подумал :)
0
AraneusAdoro #
Он создавался как замена бейсику, но ближе скорее к алголу.
0
bolk #
Википедия утверждает:
ABC задумывался для использования в целях, аналогичных применению Бейсик, Паскаля и AWK

«В целях аналогичных применению» не подразумевает родство. Кроме того, если рассматривать «аналогичных применению» как признак родства, то у ABC целых три предка.

У Пайтона языков, которые оказали на него влияния вообще вагон: ABC, Modula-3, C/C++, Smalltalk, Lisp, Fortran, Miranda, Java и Icon.

На этом фоне «генетический вклад» Бейсика совершенно теряется.
+1
Bal #
Ну, очевидно же, что подразумевается не биологическое родство с двумя разнополыми предками :)

В «генетике» языков рассматривают именно взаимное влияние. И в Python опытный глаз видит ряд генетических остатков Бейсика. Посмотрите на input и print, например :)
–1
bolk #
Понятное дело, что влияние. Только влияние языков не по названиям операторов считается, а по заимствованию идей. Оператор PRINT, например, есть в Фортране — в одном из самых старых языках, не знаю есть ли там INPUT, подозреваю, что есть.

Какие идеи Пайтон взял из Бейсика? На мой взгляд — ни одной.
+1
Bal #
Оператор PRINT, например, есть в Фортране


Он там совсем другой.

Какие идеи Пайтон взял из Бейсика?


А какие идеи были в Бейсике? :) Простота, универсальность, нестрогая типизация, интерактивность, расширенная диагностика ошибок, изоляция от железа, изоляция от ОС? Чего из перечисленного нет в Питоне?

Но, в любом случае, в наследовании языков смотрят не на идеи обычно, а на типичные способы решения тех или иных вопросов. И напомню, я утверждал, не что Питон — прямой потомок Бейсика. Он потомок ABC. Который уже, в свою очередь, потомок Бейсика. Соответственно, влияние Бейсика уже минимально. Но — заметно намётанному глазу,
–1
bolk #
Ещё раз. ABC — не потомок Бейсика, откуда вы это взяли.

А глаз у меня намётан, могу дать пару пруфлинков.
+1
Bal #
ABC — не потомок Бейсика, откуда вы это взяли.


Сложно не назвать потомком язык, который задумывался как замена Бейсику, который повторяет многие принципы Бейсика и который похож на него лексически.
+1
bolk #
Да не задумывался он так. Написано же — задумывался как замену Бейсику, AWK и Паскалю.

Во-первых, как замена. Замена не значит заимствование идей.
Во-вторых, замена трёх языков, а не одного. Причём AWK похож на Бейсик, как трактор на помидор — помидор красный, а трактора дверки наружу открываются.
0
Flammar #
Какие идеи Пайтон взял из Бейсика
В частности, не заключать условия в if и циклах в скобки, в отличие от С. И более, по сравнению с С, «вербозный» синтаксис…
–1
bolk #
Почему вы решили, что это Бейсик вообще? А не Кобол, например?
+1
Bal #
Кобол — язык со строгой статической типизацией. Ну и идеологически имеет с Бейсиком мало общего.
–1
bolk #
А Пайтон — объекто-ориентированный язык, поддерживающий функциональное программирование и вообще ничего общего с Бейсиком не имеющий.
0
Flammar #
Там же:
Испытал влияние:Сетл, Алгол 68[1]
Повлиял на:Python, Agena
0
Flammar #
Википедия пишет, что ABC создавался под влиянием SETL и ALGOL 68, Бейсик среди «предков» не упоминается.
+2
Rascko #
А, собственно, какие тут пяни есть, которых нет в APL (кроме того, что весь код можно в ASCII-символах печатать)?
+9
pashkoff #
у J есть ниша – обработка данных, особенно в финансовой сфере


Что-то, с учетом недавней статьи про IT в банках, мне кажется, что J в финансовой сфере привлекателен, в первую очередь, как раз своей мало-читаемостью.
+2
Indexator #
Почему-то вспомнилось
0
Flammar #
Ага, почему-то мне это кажется «Как 45 минут терять в секунду по $172 222 виртуальных денег, которые никто не собирался допускать до покупки на них чего-то материального», что-то в этом роде…
+17
skiedr #
Цель примеров – показать код в таситной форме.


А я думал показать читателю какой же он идиот, что не может понять такие простые и коротенькие примеры! ;)
+3
yndi #
А мне очень понравилось, давно интересовался этой группой язков (APL, J), но всё никак не удосуживался поближе с ними познакомиться. Теперь благодаря вам появилось стойкое желание поиграться с ним в консольке.
+10
Sauron #
> createTable =: [:|:,.&a:
С этого места и далее ничего понять нельзя, потому как не ясна суть используемых глаголов.
+15
Suvitruf #
«J – самый ненормальный и самый эффективный язык из известных мне языков.»
Он неэффективен хотя бы тем, что такой код невозможно поддерживать.

p.s. а ещё над Brainfuck смеялись…
–4
YourSearchExpert #
Выглядит реально жудко :)
+4
YourSearchExpert #
Я хотел сказать, что код очень трудно читаем. Я сомневаюсь, что написание и чтение такого кода может быть эффективным. Например, нужно найти какой-то кусок кода через поиск в редакторе, где делается код. И как это сделать? Везде комменты добавлять?
+27
vk2 #
Взрыв на фабрике знаков препинания (как мы как-то называли sendmail.cf)
+5
vladob #
Я скажу, когда нужен J — это когда у вас данных больше, чем времени.
У меня один коллега (за 40) на нем «лабает» и в течение 3-х последних лет закрывает весьма нехилый фронт работ по анализу и управлению потоками данных. Причем он по образованию не Ай-Ти, а «предметник» — Animal Science.

Беда пришла нежданно.
Объем работ/данных вырос.
Коллеге в подмогу дали 2-х молодых, вооруженных дот-нетом и джавой.
Молодые скололись, «ни асилили» J.
Сейчас они всей группой учат питон и пытаются на него мигрировать.

Я делал два подхода к J.
Но мне аналогичные задачи комфортнее делать в R.
0
inetstar #
К слову говоря, если заменить всякие знаки препинания красивыми иконками, то, наверное, было бы намного проще понимать.
+1
Onmyoji #
Так вот для чего на самом деле нужны клавиатуры типа Optimus
0
inetstar #
Хорошая мысль. Но ещё тогда нужен и редактор типа Optimus, который автоматом вставляет иконки в текст по аналогии как IM-клиенты вставляют смайлики. Есть идеи?
0
AraneusAdoro #
К слову говоря, APL.
–1
inetstar #
В статье была ссылка на APL. И в APL не использовались красивые интуитивно-понятные иконки.
+2
AraneusAdoro #
А какие вам нужны иконки? Я лично не могу себе представить, например, интуитивно понятную иконку для curtail, behead или ravel. К тому же, код будет совсем уже смайликовым.
+1
Quiensabe #
Имхо, понятно почему в первой версии языка были не ASCII символы, а собственные обозначения. И, по моему — это именно то что нужно языку.

Если бы для всех этих |:, |., ~. и т.п. — были свои уникальные знаки (а для большинства уже есть подходящие математические знаки операций над множествами). Тогда код выглядел бы не тарабарщиной, а очень похоже на обычный математический язык,

Дело только в создании хорошей IDE, наподобие Matlab. А в идеале, вообще движок для рукописного ввода…

Интересно, если что-то подобное?
0
Bal #
Интересно, если что-то подобное?


В начале темы как раз APL упоминался. В оригинале он именно на своей системе символов.

+1
Rascko #
Лет семь назад мне пришлось столкнуться с APL — там как раз «крючки». Минус такого подхода — нужно либо увеличивать шрифт по сравнению с «чисто текстовым» языком, либо ломать глаза и блюсти чистоту монитора. Ну и плюс там была неуютная ситуация какого рода: в APL один и тот же крючок может значить разные вещи, в зависимости от того, интерпретируется ли он, как унарный или как бинарный оператор. Например, А|B — это остаток от деления B на A. А просто |B — это абсолютное значение B. Плюс в некоторых случаях «одним крючком» рисуются вещи, которые в «привычных языках» рисовались бы двумя — например, есть отдельные операторы Nand(«Not and») и Nor(«Not or»).
+2
Quiensabe #
Именно поэтому я не предлагаю вернуться к APL, а только «визуализировать» J.
Судя по статье язык J — во многом похож на обычные математические выкладки. Но в обычных формулах используется много спец. символов и символов со специальным размещением аргументов (интеграл например), поэтому математические выкладки выглядят читабельнее.

Например, что проще: или Abs(Sin(Sqrt(10.5*X)))/(Exp(3*Ln(X*X))-0.143)+2*Pi*X?

Если взять за основу стандартные алгебраические знаки для работы с матрицами, векторами и пространствами, плюс добавить какие-то свои — может получится достаточно наглядно. А запись на нескольких уровнях позволит избавиться от «леса» скобок…

При этом от канонической записи отказываться незачем. Можно параллельно показывать ASCII запись и «формульную», как в некоторых математических пакетах.
Тем более что язык настолько сжат, что экономить место совершенно незачем, все равно на экран влезет такое количество логических конструкций что удержать их одновременно в голове нереально…

Понятно что знаков получается много, и тем кто уже знает J — учить новые знаки нет особого смысла. Но если сохранить возможность использовать в формулах ascii запись, то этот недостаток нивелируется. А вот для начинающих, такая запись будет полезна.

Например мне после статьи захотелось поставить J периодически его использовать (вроде мегакалькулятора). Мне поначалу понадобятся от силы 10-15 операторов, Из которых большая часть уже имеет стандартный символ или в алгебре или в комбинаторике. Возможность их использовать для меня открыла бы дверь в этот язык.

p.s. Имхо, возможность записывать формулы в алгебраическом виде давно пора внедрять в распространенные IDE. Это сделало бы код многих программ (особенно научных) гораздо читабельнее. Может есть что-то в этом роде?
0
kulinich #
пример функции на APL:
Пример

–1
Quiensabe #
Этот код также малочитабелен. Я предлагаю нормальный формульный редактор.

Что-то типа такого:
image

Здесь принцип немного другой, но по идее, если считать что красным — ascii запись, а синим — формульная.
И править можно и тот и другой вариант — должно быть удобно.
+2
Bal #
Поразительно, как на таком W/O-языке не смогли написать 99 bottels извращённее, чем на том же Perl :)
0
Nomad1 #
и в самом деле, автор с такой фамилией мог бы и получше постараться — азиат ведь, в глифописи разбираться должен :)
+4
Karapuzzzz #
Язык программирования на смайликах.
0
potan #
Я пытался выучить K, но оказался неспособным запомнить значения разных знаков в разных контекстах (типа того, что + как одноместная операция охначает транспорирование).
Но за то научился писать в pointfree стиле на Haskell, что мне потом помогало.
А синтаксис особых проблем не вызвал :-).
+1
Optik #
Напоминает некоторые либы, написанные на скале, где дорвавшийся до def <=!+ () {} программист отрывается по полной.
+1
VlaZ #
Интересный и необычный синтаксис. На мой личный взгляд — плохо читаем. В связи с этим возникает вопрос — кто-нибудь использовал его в реальных проектах? Если да, то поделитесь, пожалуйста, опытом, что на нем было сделано и какие преимущества это дало. А особенно — не было ли потом проблем с поддержкой.
0
Monnoroch #
Еще бы примеры продакшн-кода. То есть, вполне может статься, что автор поста предоставил (не)умышленно нечитаемый образец кода (сишный код тоже в 1 строку можно написать весь), и при соблюдении некоторых правил, которые, в целях облегчения поддержки, должны выполняться в настойщих проектах-неоднострочниках, код станет существенно понятней.
+1
AraneusAdoro #
Такой вот пример есть в книге «J for C programmers»

Вычисление среднедневного остатка
NB. Verb to convert TAB-delimited file into numeric array
rdtabfile =: (0&".;.2@:(TAB&,)@:}:);._2) @ ReadFile @<

NB. Verb to process journal and account files
NB. y is (# days in current month);(Account filename);
NB.   (Journal filename)
acctprocess =: monad define
'ndays acctfn jourfn' =: y

NB. Read files
'acctano openbal' =. |: rdtabfile acctfn
'jourano jourday jouramt' =. |: rdtabfile jourfn

NB. Verb: given list of days y, return # days that
NB. each balance is a day's closing balance
wt =. monad : '(-~ 1&(|.!.(>:ndays))) 0{"1 y'

NB. Verb: given an Account entry followed by the Journal
NB. entries for the account, produce (closing balance),
NB.  (average daily balance)
ab =. monad : '(wt y)({:@] , (%&ndays)@(+/)@:*)+/\1{"1 y'

NB. Create (closing balance),(average daily balance) for
NB. each account.  Assign the start-of-month day (1) to the
NB. opening balance
cavg =. (acctano,jourano) ab/.(1,.openbal),jourday,.jouramt

NB. Format and print all results
s =. 'Account %d: Opening %d, closing %d, avg %d\n'
s&printf"1 acctano ,. openbal ,. cavg
''
)

Прошу прощения, что без подсветки.
+1
splatt #
Мне понравилась аналогия с китайским языком, которую автор статьи привел выше в комментариях. Безусловно, если потратить несколько (а на самом деле, десятки) лет на изучение китайского языка, то вы сможете на нем читать и писать, и иероглифы уже не будут вам казаться такой жуткой кашей. Вопрос только в том, стоит ли оно того? Окупятся ли потраченные на это годы?

Проблема в том, что не понятно, в каких реальных проектах/задачах J настолько удобно использовать, что бы потом можно было бы сказать: «да, не зря я учил его все эти годы». По статье этого не понятно, как непонятно и то, существуют ли такие ситуации/задачи.

Основная аргументация автора статьи, почему стоит учить J, заключается в том, что J позволяет кратко записывать алгоритмы. Это правда. Годы изучения китайского языка тоже позволят вам записывать целые тексты в очень кратком виде. Но согласитесь, не это является причиной, по которой его учат иностранцы, а совсем наоборот — это отталкивает многих. И если бы исторически не сложилось бы так, что на китайском говорит миллиард человек, то вряд ли его бы вообще кто-нибудь учил, кроме людей, которые занимаются этим ради фана, и что бы похвастаться.

Зато с английским языком совсем другая ситуация — он прост, и несмотря на то, что в китайском вы сможете написать поэму на маленьком листочке, а в английском вам придется исписать тетрадный лист, китайцы учат в массе своей английский, а не наоборот.

0
BubaVV #
Китайский язык годен, если его учить с детства, в соответствующем окружении и при этом не видеть других языков. Тут, наверное, такая же ситуация
+5
m36 #
Зря вы так пугаетесь джея. Выучить его вполне возможно, не верная аналогия с китайским. Просто дольше, чем обычные языки. Но а разве слишком долго сами языки другие изучаются?

Я джей изучил за месяц по вечерам. Просто прочитал и опробовал все примеры в книге Lerning J. Я ее даже конспектировал. Неделю заучивал на память все глаголы. Просто, зазубривал. Наверное, для джея это важно, т.к. их там достаточно. Но и надо сказать, что такое зазубривание — не так много времени и занимает.
После этого делал первое свое большое задание. Тоже с месяц по вечерам. Было очень сложно. Но постепенно мышление привыкало мыслить массивами.
После этого был готов работать. Пошел на работу на этом языке. Хотя как-то работать и мог, нельзя сказать, что ясно понимал текст и хорошо писал. В процессе, с год этот навык улучшался.

Так что вполне в разумные сроки можно изучить. Возможно, это требует какого-то специального мышления, у меня статистики нет.
0
vladob #
Уважаю!
Я так в свое время осваивал Lisp, потом R.

А другого и не дано, по-видимому.
Само ветром не надУет.
0
splatt #
Я разве ставлю под сомнение тот факт, что изучение J — легче китайского?
Я говорю о том, что непонятна область его применения, и как следствие — нету ответа на вопрос, «зачем нужно тратить время и усилия на его изучение».
0
vladob #
Если отвечать упрощенно прагматично — есть такие рабочие места с весьма привлекательными условиями по зарплате и пр.

Ну это если аргументы типа «Ну, во-первых, это красиво...» Вы считаете несущественными и не относящимися к делу.

+3
iHun #
Если посмотреть на текст, не читая заголовок, можно подумать, что это очередная статья про обфрускацию JS.
0
JIghtuse #
Читал об APL. Язык интересный, уже решивший некоторые задачи, с которыми сейчас сталкиваются новые языки. Но синтаксис — да, очень сложный. Даже Rust с его тремя типами указателей выглядит проще, не говоря уж о C, Python и Go. Где-то встречал сравнение языков с точки зрения простоты использования (или популярности) и количества ключевых слов. Как раз в Go указывалось меньшее число, чем в C.
0
vladob #
Читал об APL.

Спасибо за ссылку. Прочитал, получил удовольствие.

В тексте по ссылке мне понравилось сравнение APL-языков в области обработки «больших данных» с классикой музыки — Бетховен и иже с ним.
Они не соберут полные стадионы поклонников (как Lady Gaga или Hive с Hardoop'ом ), но будут жить, впечатлять призводительностью и мастерством создателей еще долго, если не всегда.
Хорошая статейка по ссылке.

Мое мнение — ниша J и подобных — программирование с данными.
С Большими Данными — в частности.
И в этой области, как нигде, видна разница php, к примеру, и J.
0
Alexeyco #
А разница C++ и J видна?
0
m36 #
Если вы отличный специалист в С++, то всегда можно написать программу, работающую быстрее, чем на J. Но разница будет: месяц по сравнению с час, утрированно, работы программиста. Иногда это просто неприемлемо. Пусть J и медленнее, но он достаточно производителен. Причем не факт, что он будет медленнее, если писать на плюсах в лоб.

Я так прямо не могу дать сравнительные тесты, просто из своего опыта. Потому что допиливали проблемные места кода на джее с помощью С или плюсов.
Местами он заметно неэффективен. Причем, эти места даже понятны, можно привыкнуть. Он энергичный, не ленивый. И в непонятной ситуации для сохранения имутабельности данных делает копию. А копии — это весь массив, который может быть большим. Поэтому там неэффективна рекурсия.
Но и оптимизируется легко. Пишете на С эту часть. Джей передает туда ссылку на массив и вы уже делаете, что хотите.
+11
Alexeyco #
> Так Кеннет Айверсон совместно с Роджером Хуэем в начале 90-х создали язык J.

Так и вижу. Начало 90-х, какая-нибудь конференция. Говорит Кеннет Айвенсон:
— Здравствуйте! Мы вместе с Роджером Хуэем разработали…
— Мы тоже все ху__м с того, что вы разработали…

А если серьезно, то я дико завидую тем, кто программирует на подобном. Потому, что мне даже лисп не дался… чего уж там говорить…
0
burjui #
Lisp очень прост, на самом деле, и я не шучу. Если хотите, почитайте SICP (про Scheme) или Practical Common Lisp. Для Scheme есть неплохая минималистичная среда разработки — Dr. Racket.

Что до J… Я бы на таком программировать побоялся. Да, с опытом будешь читать эту символьную кашу быстрее, но всё равно это дольше парсить, чем даже код STL на C++.
0
Carzil #
<joke>Этим студентом был Урбан Мюллер</joke>
0
Biga #
На perl тоже можно кодить смайликами, но J явно круче.
0
quarck #
Похоже что J — это как Ифкуиль, только в программировании, а не в естественных языках.
+1
jakobz #
Во многих языках сейчас есть лямбды и прочие штуки, на которых сделаны eDSL-ки например для работы с коллекциями (LINQ то же, всякие map/filter во многих языках). Не проще ли в своем языке построить уютненький eDSL для задач, решаемых J? Все-таки и порог вхождения сильно ниже будет, и расширять это можно как угодно, интегрировать сторонний штуки не нужно. В каких случаях J будет лучше чем такой eDSL?
0
Alesh #
Статья обстоятельная и даже интересная, но по прочтению возникает вопрос: «А зачем?» Ведь кроме перла есть еще масса языков на которых можно писать врайтонли код)
0
PsyHaSTe #
ТС, я извиняюсь, но по-моему выбирая из
Рассмотрим такой пример на SQL. У нас есть две таблицы:
CREATE TABLE Customers (ID INT, Name TEXT, Age INT, Salary INT)
CREATE TABLE Orders (OID INT,  Date  DATETIME,  CustomerID INT, Amount INT)

и
  createTable =: [:|:,.&a:
  union =: ([:{.[),:[:([:<[:;]#~~:&a:)"1([:{:[),.([:{:]){~([:{.])i.[:{.[
  insert =: [union[:({.,:([:([:<[:(]$~[:1&,#)>)"0{:))[:|:[:>]
  rows =: {.([:<,:)"1 1[:|:[:([:<"1[:,.>)"0{:
  value =: [:(]`{.@.([:1&=#))[:,[:>[((([:<[)=[:{.])#[:{:])[:>]
  pr =: [:,[:(([:>[)(([:<([:>[),.[:>])"0 0)"0 1[:>])/[:([:<[:rows>)"0]
  join =: 1 : '((([:{.[:>{.),:[:([:<(>"0))"1[:{:[:1 2 0&|:[:>([:,u"0)#]) (pr y))' 

очевиден ответ, какой язык более «человечен». Мне кажется, даже ассемблер понятнее, чем это. Просто какой-то ад и израиль, я не могу представить, что это написал человек, больше похоже на автогенерацию, причем очень нехилого обфускатора…
+3
m36 #
Вопрос

Вы часто на SQL-ле пишете сам движок субд? Код, который ниже, который на джее — не делает выборку, он создает возможность такой работы. Навесить парсер SQL и можно писать к такой СУБД уже какие-то запросы.
–3
PsyHaSTe #
Я всегда считал, что ЯП придумывают для решения определенных задач. Этот язык — эзотерический, его практическое использование — невозможно. Во-первых потому что он тупо не семантичен. Во-вторых, время индивидуалов-гениев прошло, никто не напишет нормальный проект в одиночку, поэтому нужны более массовые языки, чем вывод /dev/random. Ответ товарища vladob более чем подтверждает эту точку зрения.
+2
m36 #
Слишком резкие высказывания. Его используют. Я всеми силами тут пытаюсь объяснить, что язык семантичен, не стоит дураками китайцев например, называть, или немцев, что ж они очень семантический русский не пользуют? Чтобы понять, насколько семантический язык, надо его знать и сравнить, а не пугаться всего, что непонятно.

Это скорее психологическая реакция. Дети в школе так делают — называют всё, что непонятно, идиотизмом. Физику, математику. «какой это идиот придумал?»

Знание глагогов приводит к их узнаванию в тексте, логично. Что приводит к чтению кода. Логично. А вот, насколько сложный код можно записать и насколько легко он читается, при условии, что вы знаете язык — это и будет семантичностью.

При одинаковой сложности алгоритмов непонятный джей выигрывает у понятных языков легко. Благодаря информативности на символ. Даже если вы не мгновенно прочитаете строку, то быстрее прочитаете смысл, чем будете рыться в классах, методах, куче файлов и тому подобное. И при этом в голове строить ту же картинку из разрозненных кусков.

+1
PsyHaSTe #
Математику придумывали не одно тысячелетии. Как вы думаете, они случайно используют большие формульные выкладки, огромные значки интегралов, всякие полосочки вроде модулей, кучу словосочетаний вроде sin, cos, arctg и пр. для обозначения того, для чего хватило бы какого-нибудь спец.символа? Все же учебник по высшей математике намного понятнее, чем написанное выше. А то вы выполняете функции архива: длинные частовстречаемые последовательности (ключевые слова) заменяете спец.символами. Количество информации на миллиметр экрана повышается, а вот качество восприятия этой информации — понижается, причем экспоненциально. Как в примере выше, я скалу никогда в жизни не видел, C/C++/C# и пр, баловался и функц. языками и прочим, мне хватило одного взгляда чтобы понять, что делает метод товарища Googolplex

Бывают разные люди. Некоторым биологам не может придти в голову, что изучать 30 лет сексуальные потребности особой разновидности жучков-боровичков не является крайне занимательным занятием. Я уважаю ваш выбор и выбор создателей этого языка. Но ваше восприятие — это отклонение от нормы, глупо ждать, что подобное может получить популярность. Хотя пример с судоку очень показателен и краток, но писать что-то серьезнее второй лабораторки по информатике, имхо, на подобном языке не стоит. По крайней мере языки появляются и исчезают, и я не позавидую человеку, которму придется отлаживать хотя бы пару десятков подобных строк. Особенно, если к тому моменту этот язык отомрет по тем или иным причинам… А вот если подобное случится со скалой, любой человек, знакомый с linq или любым функц. языком найдет ошибку и исправит.
+2
m36 #
я участвовал в реальных проектах, написанных на джее: датамайнинг.

Один из проектов — высоконагруженный сервер, нереляционная субд, для датамайнинга. Кластер, шардинг. Это еще в далеком 2005 году, когда такие слова не были особо в обиходе у программистов модными.

Я лично, например, писал там еще математические сервер, считающий ОЛАП-преобразования. Еще про олап мало кто слышал.

Так что язык вполне годный для работы в продакшине. И язык используется, как бы не казалось это вам странным.

Посмотрите на главной странице http://www.jsoftware.com/ в разделе Representative Users кто его использует и найдете Hewlett Packard, Intel, Microsoft и много других.

И не стоит противопоставлять математику джеевской форме записи. Иначе все языки попадут под такую категорию. Не говорю только о Лиспе, а даже и о плюсах и Scala. В математике звездочки вместо умножения не пишут, наклонную черту вместо деления не пишут. Или во многих других языках есть графические способы записать интеграл?
Математика создавалась тысячелетия, но далеко не вся. Интегралы только во время Ньютона появились. И сейчас появляются новые значки. И не думаю, что Кенет Айверсон глупее араба две тысячи лет назад.

Я лично тоже считаю, что один красивый уникальный значок на глагол был бы понятнее, чем комбинация из двух. Но клавиатуры мешают. И это не критично. А сама форма записи и разбора предложений — очень и очень неплохая в джее.
+1
Flammar #
Математику придумывали не одно тысячелетии
Если говорить о современной математической нотации, то, судя по Википедии, все знаки кроме "+" и "-" придумали в 17 веке и позже, "+" и "-" — в конце 15 века.
0
akalenuk #
К слову сказать, Айверсон придумал APL (IBM) именно как разновидность математической нотации. Новая нотация должна быть проще, логичнее и удобно записываться в строчку. Ну и в целом у него получилось. К классической нотации даже до учебника по высшей математике привыкают лет десять, APL можно освоить за семестр или два.

J страдает не из-за плохой нотации, а из-за неподходящих средств ее выражения. Нотация хорошая. Но для того, чтобы читать J, надо не просто знать нотацию, а еще и то, как он ложится на ASCII. Это двойной барьер для восприятия, да. Хотя и преодолимый.
0
bolk #
Вы, кажется, не поняли. Вторая ваша цитата — это и есть «СУБД на коленке», которая реализует похожий на первую цитату синтаксис.

Правда, мне тоже кажется, что в продакшне такому коду не место.
–1
Alesh #
Правда, мне тоже кажется, что в продакшне такому коду не место.

Основное требование к продакшен коду, что бы когда вы уйдете на повышение или покинете компанию, другой человек разобрался бы с кодом в кратчайшие сроки и мог делать правки. А с кодом на этом языке, никто разбираться не будет, и я думаю даже пробовать не будут.
–1
bolk #
Да, мой Капитан!
+3
AraneusAdoro #
Сравнивать надо другое:
CREATE TABLE Customers (ID INT, Name TEXT, Age INT, Salary INT)
CREATE TABLE Orders (OID INT,  Date  DATETIME,  CustomerID INT, Amount INT)
Customers =: createTable 'ID';'Name';'Age';'Salary'
Orders =: createTable 'OID';'Date';'CustomerID';'Amount'
+1
p4p #
Действительно, ([(0:`(([:(#=[:#[:~.[:{.|:)[:~.[:(#~[:-.[:isVar«0[:{:|:)gv)*.([:*./[:+./[:(isVar»0,=/),:))@.(([:#[)=[:#]))[:gp])«1 0#] — что тут сложного?
0
Vitter #
А на сколько возможно оторваться от матриц? И писать более абстрактный код, нежели работа с матрицами на J?

Кстати, с матрицами элементарно работает MatLab(matrix laboratory) и, вроде, R
+4
vladob #
На месте автора я уже вышел бы из дискуссии.
Он все сказал.

Дальнейшая дискуссия бесполезна — только минусов нахватает.
Его комментарии еще на одну статью по J (или про технологии/проекты, которые он упомянул в связи с ним) тянут легко.

Статья про J более чем своевременна.
Я уверен — многие попробуют себя и узнают что-то новое про свои возможности, а как следствие, возможно, подкорректируют свои амбиции.

На вопрос «как рефакторить не понимая кода?» отвечу вопросом как если бы заказчиком был я —
«Вы серьезно собираетесь что-то рабочее рефакторить, не понимая кода?!
И показав неспособность и/или нежелание его понимать?

А как ТЗ мое?
Вы тоже „отрефакторите“ по самое нехочу до уровня своего понимания?
Нет-нет, спасибо…
Будем искать с перламутровыми того, кто понимает».

Рефакторят такие задачи просто — не трогают рабочий код пусть он хоть на китайском. хоть на J, хоть на ANSI C, хоть на Фортране с Лиспом пополам.
Потому как такой код, как правило, воплощает вещи более концептуальные, а посему долгоживущие.

Но это только мое мнение.

+5
lucky_brick #
че все разнылись то?

сложно, непонятно.

идите пишите на php своем.
И никогда ничего не ищите по тегам

лисп, рефал, хаскель, джей…

бизнес-программирование такое прикольное!
0
burjui #
Lisp и Haskell поставить в один ряд с J — это уже слишком (Refal не знаю). Не знаю, как там насчёт сложности, а по уровню понятности (читабельности):
  • Haskell — 8/10
  • Lisp — 7/10
  • ARMv7 assembler — 5/10
  • Brainfuck — 1.1/10 (синтаксис проще, чем у J)
  • J — 1/10
0
akalenuk #
Проблема читаемости J в том, что это адаптация APL под ASCII. Нотация APL непривычная, но неплохая. Не хуже привычной математической. Конечно, если взять его графемы и «втиснуть» в алфавит телетайпа, получится плохо. Это примерно как писать по-русски латиницей, только в восемнадцать раз хуже.

И вот меня все не покидает одна забавная конфабуляция: APL на планшетах. Символы можно рисовать пальцем, например, можно выбирать на нарисованной клавиатуре. Хранить код в уникоде вообще не проблема. Краткость в условиях небольшого экрана — огромный плюс. Мне почему-то кажется, что для обработки каких-нибудь данных в полевых условиях это все было бы полезно и интересно.

Но почему-то J под андройд есть, а APL нет.
+1
vladob #
Последний мой комментарий в этой теме.

Уперлись в нечитаемость для «непрофи» в J.
Но есть прецеденты.

Ноты!
Отдельный (письменный!) язык.
И ничего!
Плачут миллионы детей во всем мире, но жуют кактус учат нотную грамоту…

Еще раз спасибо автору.
0
Bal #
Нотам нет полноценной альтернативы вне нотной записи.

Там где есть, вместо нот, как раз, используют более привычные символы — те же гитарные табулатуры.

Наконец, нотная запись — это именно аналог уже упоминавшегося китайского. Альтернативная знаковая система, но полноценная знаковая система, эффективно распознаваемая мозгом. Синтаксис же J к такой, увы, не относится (в отличие, скажем, от синтаксиса APL).
0
vladob #
полноценная знаковая система, эффективно распознаваемая мозгом. Синтаксис же J к такой, увы, не относится


Но чьим-то мозгом он все-таки распознается.
Как миним — могзом автора поста.

Хоть это признайте и разойдемся друзьями.
0
Bal #
>Но чьим-то мозгом он все-таки распознается.

В контексте, всё же, речь о быстром распознавании структуры целиком была. А не о последовательном чтении токенов.

>Хоть это признайте и разойдемся друзьями.

Это завсегда пожалуйста :)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.