2014-02-16 3 views
0

Есть ли встроенный эквивалент функции Haskell's until в Python?Эквивалент Haskell «до» в Python

По существу, until применяет функцию f к предоставленному исходному значению v, затем применяет f к f(v), пока условие не будет выполнено. Другими словами, until возвращает результат многократного применения f до тех пор, пока не будет выполнено условие.

я могу реализовать это в Python как так:

def until(cond, func, starting): 
    val = starting 
    while not cond(val): 
     val = func(val) 
    return val 

Должен ли я использовать эту реализацию, или есть какая-то функция библиотеки я должен использовать вместо этого?

+1

Я бы сказал, что я не пытаюсь использовать do/while loop. Цикл do/while является процедурной конструкцией, которая, вероятно, может быть использована для решения этой же проблемы, но я не думаю, что это эквивалентно «до» Haskell. Может быть, это только моя неопытность с Python. –

+1

@BlueIce Не совсем, он спрашивает о встроенной * функции *, а не о выражении. – Bakuriu

+1

Я не думаю, что в нем что-то встроено. У 'itertools' есть хорошие инструменты, которые могут быть знакомы с Haskell, но не тот, кто это делает. Я думаю, что цикл while будет самой естественной реализацией Python. –

ответ

5

Нет, нет встроенной функции, эквивалентной until. Встроенный модуль Python и модуль itertools взяли много вещей из Haskell, но не функцию until. Ваш, вероятно, самый простой и эффективный способ его реализации.

На самом деле реальная проблема заключается в том, что не существует функция, которая возвращает результаты применения функции f итерированным, так что вы каким-то образом есть написать функцию iter_apply, чтобы сделать это.

При реализации iter_apply это довольно легко составить некоторые встроенные функции для получения until:

#from itertools import ifilter as filter # in python2 

def iter_apply(func, value): 
    while True: 
     yield value 
     value = func(value) 

def until2(cond, func, starting): 
    return next(filter(cond, iter_apply(func, starting))) 

# or: 

from itertools import dropwhile 
def until3(cond, func, starting): 
    iterated_values = iter_apply(func, starting) 
    return next(dropwhile(lambda x: not cond(x), iterated_values)) 

Разница во времени:

In [12]: %timeit until(lambda x: x > 10000, lambda x: x+1, 0) 
100 loops, best of 3: 2.33 ms per loop 

In [13]: %timeit until2(lambda x: x > 10000, lambda x: x+1, 0) 
100 loops, best of 3: 2.45 ms per loop 

In [14]: %timeit until3(lambda x: x > 10000, lambda x: x+1, 0) 
100 loops, best of 3: 3.81 ms per loop 
Смежные вопросы