LINUX.ORG.RU

Сортировка списка во время компиляции

 , , ,


0

2

Начал писать на досуге небольшую библиотеку шаблонных контейнеров. Вот ее часть, включая сортировку списка.
Эта замечательная программа определяет два списка, затем сливает их в один и сортирует. Во время компиляции. Ни одной переменной во время исполнения не пострадало.
А способен ли на такое Lisp, Haskell, Agda, Coq, Epigram или Mercury?

Вот зачем нужен такой ппц, а?

Я уж лучше «препроцессором» пройдусь... Это будет работать с любым ЯП.

true_admin ★★★★★
()

Вот ее часть, включая сортировку списка.

По ссылке классический С++, бессмысленный и беспощадный. У меня в глазах зарябило от всех этих template

А расскажите, какой практический юз кейс, так сказать, у этой вашей библиотеки?

anonymous
()

Ад.

А способен ли на такое Lisp, Haskell, Agda, Coq, Epigram или Mercury?

Ты забыл OCaml, SML и Prolog.

ymn ★★★★★
()

Для чего нужен TMP, кроме тестирования кода?

blexey ★★★★★
()
Ответ на: комментарий от ymn

Это только кусочек библиотеки. А вообще пишу интерпретатор именно Prolog. Тоже в compile-time на C++

nerdogeek
() автор топика
Последнее исправление: nerdogeek (всего исправлений: 1)

На кой ляд тебе сортировка списка констант IRL? Просто потому что «я могу»? И да на этом нашем говнолишпе туева куча списков сортируется во время компиляции без всякой магии. Совсем.

staseg ★★★★★
()
Последнее исправление: staseg (всего исправлений: 1)
Ответ на: комментарий от yoghurt

В общем, да. Целое «оборачивается» шаблонным типом Value

template< typename T, T v = T() >
struct Value
{
    enum { val = v };
    typedef T value_type;
};

nerdogeek
() автор топика

А какой в этом смысл? Я не часто встречаю вкомпиленые данные, которые надо сортировать. Если же ты это просто, что бы выпедрется, то вынужден тебя огорчить: лисп может любые преобразования делать на этапе компиляции, поскольку макросы лиспа позволяют использовать любые определенные в проге функции(только на этапе компиляции). Так что ненужно и «Lisp, Haskell, Agda, Coq, Epigram или Mercury» не переплюнул.

Aswed ★★★★★
()
(defmacro msort (&rest lst) `(quote ,(sort lst #'>)))
anonymous
()

Эта замечательная программа определяет два списка, затем сливает их в один и сортирует. Во время компиляции.

А способен ли на такое Lisp?

Это шутка такая что ли?

#.(defconstant +funny-list-1+ '(3 2 1))
#.(defconstant +funny-list-2+ '(5 4 6))

(let ((v (list . #.(sort (append +funny-list-1+ +funny-list-2+) #'<))))
  (print v))
korvin_ ★★★★★
()
Ответ на: комментарий от Aswed

«Lisp, Haskell, Agda, Coq, Epigram или Mercury» не переплюнул.

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

unlog1c ★★★
()
Ответ на: комментарий от korvin_

Это при чтении же, а у автора при компиляции. Надо как-то так.

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defconstant +list-1+ '(3 2 1))
  (defconstant +list-2+ '(5 4 6)))

(defmacro macrosort (list pred)
  `',(sort (eval list) (eval pred)))

(macrosort (append +list-1+ +list-2+) #'<)

=> '(1 2 3 4 5 6)

Но таки встречный вопрос ТС. Способны ли плюсы сделать сортировку списка при *чтении сорцов*, как в примере korvin_?

naryl ★★★★★
()
Ответ на: комментарий от true_admin

Я уж лучше «препроцессором» пройдусь... Это будет работать с любым ЯП.

Согласен. Тут даже не то, что препроцессор; просто часть данных надо прегенерировать.

Miguel ★★★★★
()

Ты ведь знаешь, что на compile-time вычисления время тратится больше, чем на подобные в runtime? Это не говоря уже о сотнях излишних строк.

E ★★★
()
Ответ на: комментарий от naryl

Это при чтении же, а у автора при компиляции.

Ага, но в данном случае разница не принципиальна.

Если при чтении, то ещё проще:

Разве что списки не сохранятся для последующего использования.

korvin_ ★★★★★
()
Ответ на: комментарий от naryl

при *чтении сорцов*

C++ не возволяет выполнять управляемые операции ввода/вывода на этапе компиляции

nerdogeek
() автор топика

то не нужно в такой реализации. CTFE нужен, а вот тот плюсовый ужос - нет.

r ★★★★★
()

Эта замечательная программа определяет два списка, затем сливает их в один и сортирует. Во время компиляции.

Ух ты! А можно в студию время сортировки ста миллионов чисел, пожалуйста?

metar ★★★
()

Болезнь всех c++ фанбоев.

А Common Lisp такое умеет, да, даже во время чтения.

'#.(sort '(1 2 3 4) #'>)

Причём, как видишь, всё намного короче

hvatitbanit
()

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

А в CL во время чтения/компиляции можно сделать всего такого, что в вашем C++ просто и не сделаешь. Например, в специфических случаях вместо вызова функции вкомпилировать более простой код

hvatitbanit
()
Ответ на: комментарий от hvatitbanit

Генерируешь код, вызываешь конпелятор и загружаешь новую функцию через dlopen. ECL отчасти так и работает :)

staseg ★★★★★
()
Ответ на: комментарий от Aswed

Каковы преимущества перед лисповскими макросами?

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

unlog1c ★★★
()

А способен ли на такое Lisp, Haskell, Agda, Coq, Epigram или Mercury?

не сомневаюсь, но код на этих языках будет совершенно нечитаем.

crowbar
()
Ответ на: комментарий от crowbar

Ну если для вас код выше читаем хуже полотна на C++, то у меня для вас плохие новости

hvatitbanit
()
Ответ на: комментарий от uber_cat

А аналог механизма подстановки лучшего кода через compiler macro используется многими реализациями, где тип переменной указали заранее через (declare (type ...)). В цепепе это же просто не нужно.

hvatitbanit
()
Ответ на: комментарий от slovazap

Перепиши лучше этот п***ц на constexpr'ах.

Тогда в коде появится императивная скверна! Не бывать сему!

nerdogeek
() автор топика
Ответ на: комментарий от nerdogeek

Есть куда стремиться

* 
; compiling file "/home/vasily/testlol.lisp" (written 18 FEB 2014 05:48:53 PM):

; /home/vasily/testlol.fasl written
; compilation finished in 0:00:00.033
 *list*

(16 24 161 170 179 273 311 351 594 601 740 743 762 857)
*

0.03 секунды

(defparameter *list*
  '#.(let ((part-a (loop repeat 7 collect (random 1000)))
           (part-b (loop repeat 7 collect (random 1000))))
       (sort (append part-a part-b) #'<)))
hvatitbanit
()

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

Какой юзкейс?

Но ты молодец, не каждый осилит такое. Хотя выглядит говняно, признай сам.

anonymous
()
Ответ на: комментарий от naryl

Так же ж нельзя же.

Результат append получит в качестве хвоста литерал из list-2, а потом мы его подвергаем (деструктивному) sort. CLHS 3.7.1 негодует.

LeninGad
()
Ответ на: комментарий от anonymous

Какой юзкейс?

Эту либу использует недописанная реализация Prolog на шаблонах C++.
Поэтому это еще цветочки по сравнением с Prolog на шаблонах C++.

nerdogeek
() автор топика

Святая простота. Лучше задумайся о том, что ты простыни кода мастеришь на плюсах для этой «задачи», которую каждый лиспер решит не задумываясь за 2 сек строчкой кода.

seg-fault
()
Ответ на: комментарий от seg-fault

Про тот же пролог, реализации которого в книжках 'on Lisp' & PAIP, если надо (зачем-то) queries в compile-time обработать, пишешь макрос и вуаля. Выше продемонстрировано как. Это _вообще_ не задача.

seg-fault
()
Ответ на: комментарий от hvatitbanit

Ладно, я думаю автор уже понял, что сложность решения этой задачи на порядок где-то различается. :)

naryl ★★★★★
()
Ответ на: комментарий от naryl

Это я чтобы ещё себя проверить. Я что-то думал даже, что там sort не деструктивный, хотя ещё вроде как недавно что-то на лиспе сортировал :)

hvatitbanit
()

В Template Haskell я нуб нубом

$ cat Ololo.hs

{-# LANGUAGE TemplateHaskell #-}

module Ololo where

import Language.Haskell.TH

(++|) (ListE a) (ListE b) = ListE (a++b)

less (LitE (IntegerL a)) (LitE (IntegerL b)) = a < b

sortE (ListE ys) = ListE $ sortL ys
    where sortL (x:xs) = let ps = filter (less x) xs
                             qs = filter (not.(less x)) xs
                          in (sortL ps) ++ [x] ++ (sortL qs)
          sortL _ = []


a = [| [3, 2, 7] |]

b = [| [2, 2, 1] |]

$ cat tst.hs

{-# LANGUAGE TemplateHaskell #-}

import Ololo
import Control.Monad

main =
    print $(liftM sortE $ liftM2 (++|) a b)
$ runhaskell tst.hs

[7,3,2,2,2,1]

Waterlaz ★★★★★
()
Последнее исправление: Waterlaz (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.