2015-03-16 2 views
2

Итак, я написал очень красивый код Haskell для моей домашней работы в колледже и выяснил, что они не планируют поддерживать Haskell для наших домашних заданий.Как легко перейти от Haskell к Python 3

Я получил письмо, в котором говорится, что я должен попробовать Python, поскольку на всех поддерживаемых языках он имеет большую часть «функциональных».

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

Так что мой Haskell код

transitions = map (map (splitOn ",")) $ map (splitOn "->") $ drop 5 $ input' 

и мой python3 код

transitions = list(map(lambda x: list(map(lambda y: y.split(","), x)), map(lambda z: z.split("->"), lined_input[5:]))) 

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

Что меня больше всего беспокоит, так это то, что иногда мне приходится использовать x.split, а карта должна быть map (f, x).

Есть ли лучший способ приблизиться к этому?

ответ

5

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

import string 
from functools import * 
from itertools import * 

def take(n, iterable): return islice(iterable, n) 
def drop(n, iterable): return islice(iterable, n, None) 

def splitOn(sep): return partial(string.split, sep=sep) 

transitions = imap(splitOn(','), chain(*imap(splitOn('->'), drop(5, input)))) 

Как вы можете сказать, это довольно грязно. Более вещее решение, вероятно, будет

transitions = (c for a in drop(5, input) 
       for b in a.split('->') 
       for c in b.split(',')) 

Это даже случай, когда я думаю, что регулярные выражения являются приемлемыми:

import re 

def splitOn(*seps): return partial(re.split, '|'.join(re.escape(sep) for sep in seps)) 

transitions = imap(splitOn(',', '->'), drop(5, input)) 

Я все еще в состоянии использовать функциональные методы, такие как отображение, родовое взятие/drop, частичное приложение и понимание, но он намного проще использовать больше возможностей python. Моим любимым для простого случая является простое понимание генератора, но последнее отлично, если вам нужно больше разделителей.

+0

Спасибо. Мне действительно нужен был какой-то соответствующий код python, и это именно так. Я немного пощупаю ваши примеры, чтобы понять, как выглядит python. – ditoslav

4

Есть ли лучший способ приблизиться к этому?

Да. Не пытайтесь перевести свой код из Haskell. Перепишите его, используя идиоматический Python.

Если вы хотите функциональный стиль, посмотрите на functools. Для чего-либо, включающего списки и другие итерируемые объекты, рассмотрите также itertools (это лениво, в отличие от разрезания). Но имейте в виду, что Python - это язык программирования с несколькими парадигмами, и он занимает позицию, что различные проблемы лучше решаются с использованием разных методов.

+0

Несмотря на то, что этот вопрос кажется «основанным на мнениях», я не верю, что кто-то думает, что вы переводите с одного языка на другой. Единственный ответ должен быть вашим :) – KevinDTimm

+0

Как бы вы написали это функционально в python? – ditoslav

+2

@DominikDitoIvosevic: Я, вероятно, начну с более широкого использования выражений генератора и понимания списков. Не называйте 'map (lambda: something, something_else)'; это просто уродливо. 'map()' предназначен для ситуаций, когда вы уже имеете * вызываемый с простым именем. Вы можете просто написать '(x.foo() для x в строке) вместо.Кроме того, используйте 'operator.methodcaller', чтобы избежать лямбда. – Kevin

Смежные вопросы