LINUX.ORG.RU

Как бы такой алгоритм переложить на чистое ФП

 ,


0

2

Есть такой код:

escape = False
        
unescaped = []
        
for x in data:
    if escape :
        unescaped.append(x ^ 0x7D)
        escape = False
            
    if x == 0x7D:
        escape = True
    else:
        unescaped.append(x)

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

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

неоптимально, но функционально:

es = chr 0x7D
unescape :: [String] -> [String]
unescape [] = []
unescape (es:x:xs) = ord x .|. 0x7D : unescape xs
unescape x:xs = x :unescape xs

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

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

был бы пример, а перенести на питон проблемы не составит. Это мне скорее для понимания, как подобные вещи в принципе реализовывать.

Dark_SavanT ★★★★★
() автор топика
Последнее исправление: Dark_SavanT (всего исправлений: 1)
-module(f).
-export([f/2]).

f([], A) ->
	A;

f([H|T], A) when H == escape ->
	f(T, A);

f([H|T], A) ->
	f(T, lists:append(A, [H])).

сильно не пинайте, всё ещё его изучаю.

nanoolinux ★★★★
()

а зачем ?

решение задачи на питоне - на самом деле один вызов re.sub, так же как и на любом другом языке.

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

регекспы для такой задачи? да вы издеваетесь.

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

НО, если вам в Индии, нужен объём, то можно предложить много всяких подходов..функциональный - не самый выгодный..

Рассмотрите лучше ОО - можно создать класс(шаблон/интерфейс) который представляет исходное нечто, закодить класс substitutionRulezz, ко всему этому фабрику, и наконец-то transformer..возможен такой полёт фантазии, что можно реализовывать года два, лишь бы платили :)

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

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

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

НО, если вам в Индии, нужен объём,

давайте вы не будете меня учить, что мне читать и рассматривать, хорошо?

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

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

qnikst ★★★★★
()

обещанный вариант на байтстрингах с фьюзингом и прочими радостями:

unescape xs = toLazyByteString (s <> (foldl' (<>) mempty t'))
     where (s,t) = span (/=0x7D) xs
           t' = map (\x -> word8 (head x .|. 0x7D) <> bytestring (tail x)) (split 0x7D)

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

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

принятно, но ну его к черту такое решение за рамками интерпретируемых языков :)

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

Ну так. Тред не читай @ сразу отвечай :-). Но от своих слов я не отказываюсь всё равно.

Virtuos86 ★★★★★
()

Как-то так

def unescape(data):
    i = iter(data)
    while True:
        try:
            x = next(i)
            yield next(i) ^ 0x7D if x == 0x7D else x
        except StopIteration:
            break

p.s. код не проверял, мог допустить ошибку, но принцип такой.

p.p.s. наверное можно и проще без десятиэтажных конструкций

BattleCoder ★★★★★
()
Последнее исправление: BattleCoder (всего исправлений: 6)
Ответ на: Как-то так от BattleCoder

Не вижу смысла в данном случае делать ленивые вычисления, поскольку «очищенный» массив будет сразу же попилен на header+payload и дальше разобран.

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

Ну зато ФП стиль. За исключением двух переменных, но это по факту не переменные, а константы - в питоне просто вроде нет констант как таковых.

А ленивость тут особой роли не играет... output = list(unescape(input))

По факту тут нужен генератор списков.

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

По факту, проще (короче) чем с reduce сделать не получиться. С генератором будет муторно, придется делать тройки элементов и отдельно обрабатывать концы.

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

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

да... наверное reduce попроще :) я ваш пост как-то проглядел.

BattleCoder ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.