Fork me on GitHub
#clojure-russia
<
2015-12-04
>
wwall08:12:20

Всем привет. снова я. снова с макросом. Вопрос - при проверке (run (lxmWHILE) "while") вывод - {:value {:value "while", :lang :en}, :pos 1, :type #object[loxy.core$lxmWHILE 0x5a5f0fa9 "[email protected]"]} какое заклинание надо сказать что бы вместо #object[loxy.core$lxmWHILE 0x5a5f0fa9 "[email protected]" было lxmWHILE? макрос тут - http://pastebin.com/bAJ3qXmN

prepor09:12:13

Как упорно ты хочешь написать плохой код )

wwall09:12:26

а какой был бы хорошим?

delaguardo09:12:50

@wwall: а почему ты для p-name кастуешь (str lex-name) а для остальных нет?

delaguardo09:12:29

(map (fn [[x y]] x)) ru-parser-data ) -> (map first ru-parser-data)

prepor09:12:06

wwal: я же писал. у тебя должна быть функция, которая принимает на вход word и возвращает функцию. тебе не нужны тут макросы

wwall09:12:46

смотри - у меня штук 40 этих ключевых слов

wwall09:12:17

ты предлагаешь сделать 40 одинаковых функцих которые отличаются только последовательностью сиволово которые парчиться

wwall09:12:37

парсятся

wwall09:12:27

мне тут макрос нужен только для того что бы уменьшить количество строк кода

wwall09:12:42

он не порождает никаких новых конструкций - просто оборацивает код

wwall09:12:49

оборачивает

nicola09:12:19

Поэтому он и не нужен ;)

wwall09:12:48

дело вкуса.

wwall09:12:53

мне нужен

wwall09:12:59

что бы проще читалось

prepor09:12:41

wwal: для того что бы функции генерировать другие функции ей не нужно быть макросом

prepor09:12:31

wwall: если ты опишешь задачу, покажешь эти defparser и что ты тут вообще используешь мы можем попробовать сделать это все по-другому. я тебе об этом вчера писал

wwall09:12:55

defparser из the/parsatron

prepor09:12:04

wwall: это не дела вкуса. ты пишешь хреновый код. сложный, не поддерживаемый, не компоузебл

wwall09:12:18

задача - построение парсера для простого языка

prepor09:12:51

instaparse кстати видел? )

wwall09:12:25

видел, с ним другие проблемы - язык у меня больной на всю голову

wwall09:12:43

там просто валиться со таковерфлоу

wwall09:12:31

и нет поддержки для регистронезависмых регекспов для кирилицы

wwall09:12:34

плюс компиляция состояний чего мне точно не надо

prepor09:12:58

окей окей. дай линку плз на весь код

prepor09:12:07

и пример ожидаемого результата )

wwall09:12:20

то что есть сейчас - http://pastebin.com/XfPjqa6g граматика языка на инстапарсе - http://pastebin.com/SzpJwMDc

wwall09:12:32

ожидаемый результат - AST в любом виде

prepor10:12:25

wwall: смотри, давай начнем с малого что бы продемонстрировать идею

prepor10:12:49

вот у тебя есть:

(defmacro deftoken-char
  [lex-name char-parser]
  (let [p-name   (make-sym  (clojure.string/join  [lex-name ""]))]
    `(defparser ~lex-name
       [] (let->> [start# (lineno) v# (char ~char-parser)] (always {:type '~p-name :pos start# :value v#})))))
 
(deftoken-char lxmPLUS \+)

prepor10:12:17

Ровно то же самое можно выразить так:

(defn token-char
  [lex-name char-parser]
  (let->> [start (lineno) v (char char-parser)]
    (always {:type lex-name :pos start :value v})))

(defmacro deftoken-char
  [lex-name char-parser]
  `(defparser ~lex-name [] (token-char '~lex-name ~char-parser)))

(deftoken-char lxmPLUS \+)

wwall10:12:42

ммм... нет

prepor10:12:59

почему нет?

wwall10:12:27

s1# (? $ nil) в deftoken мешает

wwall10:12:03

то ключевое слово - это слово между пробелами

wwall10:12:07

а чар - нет

prepor10:12:31

эм? я не понимаю

wwall10:12:39

смотри - вот строка

wwall10:12:51

" пока а=б"

wwall10:12:26

парсер lxmWHILE отработает нормально потому как есть пробелы вокруг

wwall10:12:48

а в вот = если делать как ты предложил - не отработает. нет пробелов

wwall10:12:28

в общем случае ты конечно прав - они сводимы к одному. но конкретно здесь - нет

prepor10:12:52

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

wwall10:12:24

стоп, это я затупил

wwall10:12:30

вперед полез

wwall10:12:36

не прочитал внимательно

wwall10:12:38

извини

prepor10:12:52

ну вот смотри. тут мы во первых избавляемся от странного (т.е. от (make-sym (clojure.string/join [lex-name ""]))). во-вторых четко разделяем процесс формирования собственно парсера (функция token-char) и синтаксической обвязки (макрос deftoken-char)

wwall10:12:14

согласен

wwall10:12:22

и выглядит лучше чем у меня

prepor10:12:49

и главное этим куда понятнее рассуждать, ты вот этой token-char можешь оперировать как обычной функией, передавать ее куда-то, т.е. собственно получать профиты ФП

prepor10:12:10

все эти choice это тоже обычные функции, ты им можешь как обычным функциям скармливать какие-то наборы аргументов без использования макросов

prepor10:12:50

deftoken посложнее, но я пока не вижу причин почему ему не быть написаным в этом же стиле

wwall10:12:11

я тоже. сейчас займусь этим.

wwall10:12:16

спасибо за наводку

wwall10:12:24

ща сделаю правильно

wwall11:12:02

prepor - ты гений.

wwall11:12:07

нафиг это все не надо

wwall11:12:11

можно проще

prepor11:12:47

wwall: страдаю, что это не так ) но рад, что помог

artemyarulin11:12:24

вообще на сколько я помню это стандартный путь у любого кто с кложурой/лиспом работает: 1 Макросы это магия, не буду юзать их 2 Макросы это супер магия - буду везде их юзать! 3 Макросы совсем не магия, буду юзать их тока когда надо

artemyarulin11:12:36

ну по крайней мере у меня так было:)

lowl4tency11:12:25

а -> ->> макросы?

artemyarulin11:12:14

and тоже макрос, помню для меня было открытием

prepor11:12:13

ну когда and это функция оно все же спортивнее

prepor11:12:30

но в кложе так низя

artemyarulin11:12:21

ну еслиб and былоб функцией то тако бы тяжело было писать if (something && something.call()) ...

prepor12:12:10

в смысле? точно так же и писал бы

artemyarulin12:12:05

если б and был функцией а не макросом то (and something (something else)) сначала бы заэвалуэйтил оба аргумента

prepor12:12:45

ну конечно бы говорим о правильной имплементации and-как-функции

prepor12:12:52

с корректным поведением

prepor12:12:06

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

artemyarulin12:12:40

ага. Но я помню вначале был удивлен, потом дошло да

prepor12:12:55

в ленивых языках and это функция

prepor12:12:29

+ в языках которые позволяют тебе отложить выполнение нужного аргумента — тоже. по-идее в скале and можно реализовать как функцию

artemyarulin12:12:00

оу, скала на столько ленива? не знал

artemyarulin12:12:04

надо почитать про нее

prepor12:12:00

scala> def and(left: => Boolean, right: => Boolean) = {
     |   if (left)
     |     if (right) true
     |     else false
     |   else false
     | }
and: (left: => Boolean, right: => Boolean)Boolean

scala> and(true, { println("hello"); true})
hello
res2: Boolean = true

scala> and(false, { println("hello"); true})
res3: Boolean = false

artemyarulin12:12:45

ха, круто

artemyarulin12:12:52

как тебе скала кста вообще?

prepor12:12:06

хз, не буду пока ничего говорить )

andre13:12:04

для начинающих: подскажите пожалуйста, есть map с массивом

{:users [{:id  1} {:id 2}]}
как проще всего добавить в массив новые ключи со значениями из другого массива, т.е. есть массив [7, 8], чтобы в итоге получилось
{:users [{:id  1 :prop 7} {:id 2  :prop 8}]}
, спасибо

rm13:12:56

(map #(merge %1 {:prop %2}) (zip x [7 8])) подозреваю, как-нибудь так

rm13:12:04

в репле не проверял

artemyarulin13:12:04

зиппер моно так-то

andre13:12:15

спасибо

artemyarulin13:12:39

типа (walk #(if (:id %) (assoc % :prop 7) (identity %))

artemyarulin13:12:07

не проверял в репле тоже

artemyarulin13:12:42

а, тут же разные еще значения нужно - неа, тада зиппер будет тут не красиво

turtle15:12:29

А как определить под какой id добавлять?

turtle15:12:09

artemyarulin: у тебя есть какой нибудь пример на cljrn?

prepor15:12:02

да какой зиппер

prepor15:12:12

(let [m {:users [{:id  1} {:id 2}]}]
           (assoc m :users (map #(assoc %1 :prop %2) (:users m) [7 8])))

prepor15:12:03

> (map #(merge %1 {:prop %2}) (zip x [7 8])) подозреваю, как-нибудь так ну т.е. да, только я не знаю откуда тут ты zip взял (очевидно, не из кложи), а zipper тут вообще не нужен

nicola17:12:32

zip (rb,py) -> interleave (clj) но map лучше подходит, можно еще update / update-in использовать - (update m :users (fn [xs] (map #(assoc %1 :prop %2) xs [7 8]))

shinych17:12:20

вопрос по клиентскому роутингу в cljs (secretary): почему в SPA используется не “клиентская” часть урля (после #) а обычный path? проблема в том, что при принудительном рефреше страницы сервер пытается отдать “несуществующий” ресурс. по идее SPA сервер должен уметь отдавать одну страничку, а остальное разруливается клиентским роутингом. решётка была бы кстати. а так получается нужно сервера учить клиентским маршрутам. грешновато как-то, не?

nicola17:12:11

Обычно, оба способа поддерживают

nicola17:12:38

С решёткой и без

shinych17:12:47

то есть на сервере придётся под каждый клиентский рут отдельный компожурный мэпинг заводить, хм

shinych17:12:16

думал это через # обойти, но секретарь с ними как-то не особо дружит, да и, судя по переписке там, народ считает, что hashless URLs это правильный путь. я как-то не очень понимаю этой философии

nicola17:12:19

Думаю там у секретари настроечка должна быть или возьми route-map его можно использовать на обоих концах ;)

shinych17:12:41

о, кстати вариант. но для полдюжины маршрутов усложнять не будем

nicola17:12:57

Хотя обычно ui роуты не соответствуют серверным

nicola17:12:53

По-сути тебе надо стаб написать - который на все запросы будет htmlку отдавать

nicola17:12:18

Если ты серверного рендеринга не хочешь конечно

nicola17:12:23

А то можно reagent на сервере пререндерить, как Дима в статье описал

nicola18:12:01

Получиться фрэндли для поисковиков ;) и без нагрузки на мобилки

artemyarulin19:12:44

@turtle: Пока нет, но счас делаю как раз пример для ом-некста под иос

shinych20:12:04

"секретарь с ними как-то не особо дружит” - оказалось, это не secretary, a accountant (небольшая либа вокруг него, она по дефолту в lein new reagent вписана). там у чуваков очень сильное мнение, что урли с хэшами это зло simple_smile запатчил, попробую там спросить в чём философия

a.espolov20:12:19

@shinych: а bidi почему решили не использовать?

shinych20:12:36

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

chort40921:12:10

Коллеги, возник вопрос. Как вы в своих организациях собираете проэкты? Сейчас пытаюсь внедрить Clojure в своей организации, как билд сервер тут используется Jenkins. Существует плагин https://wiki.jenkins-ci.org/display/JENKINS/leiningen+plugin но на сколько я помню он был косой и кривой и не думаю, что стал лучше учитывая, что Latest Release Date: Sep 25, 2013

artemyarulin21:12:34

эм, у нас докер с лейном просто

artemyarulin21:12:47

или о чем-то другом вопрос?

chort40921:12:39

@artemyarulin: то есть вы собираете уже внутри докеровского контейнера ?

chort40921:12:55

у меня так не получиться … хотят чтобы бегало на алекейшен(wildfly) сервере… так что админам надо отдавать уже готовый .war файл

artemyarulin21:12:26

аа, тада хз, сорри

chort40921:12:46

а собирать его каждый раз у себя на машине - как-то не кашерно

prepor22:12:54

chort409: я не много не в теме, но я не понимаю, что именно нужно от интеграции с женкинсом? вот старый плагин, ок. нафига он нужен? каких возможностей не хватает? чем не нравится сборка war-а просто через баш?

prepor22:12:16

с запуском тестов еще ок, но есть штуки которые умеют clojure.test запускать с выводом в xml junit-а (или как-то так, я опять же не в теме), который уже в свою очередь потребляет jenkins. но в сборке war-а то что?

chort40923:12:33

@prepor: к этому все и идет, что Jenkins будет просто вызывать баш файл. Интересно было, как раз выполнение тестов перед сборкой war. >есть штуки которые умеют clojure.test запускать с выводом в xml junit-а Почитаю про это, спасибо