Как я делаю стиль Python indent/dedent маркеры с alex/haskell?

Эта статья помогла мне многочисленные времена.

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

class PollForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PollForm, self).__init__(*args, **kwargs)
        self.fields['question'].widget = forms.Textarea()

    class Meta:
        model = Poll

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

ОБНОВЛЕНИЕ: Предложенный подход мог быть обобщен для изменения всех полей даты, не вводя каждое имя строго:

from django.forms import fields as formfields
from django.contrib.admin import widgets

class PollForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PollForm, self).__init__(*args, **kwargs)
        for field_name in self.fields:
            field = self.fields[field_name]
            if isinstance(field, formfields.DateField):
                field.widget = widgets.AdminDateWidget()

    class Meta:
        model = Poll

Это работало на меня на python3 и django 1.11

6
задан jrockway 4 October 2009 в 18:10
поделиться

2 ответа

Обратите внимание, что в других языках, чувствительных к пробелам, таких как Haskell, обработка макета действительно выполняется в лексере. Фактически GHC реализует обработку макета в Alex. Вот источник:

https://github.com/ghc/ghc/blob/master/compiler/parser/Lexer.x

В вашем вопросе есть несколько серьезных ошибок, которые сбивают вас с пути, как указывает jrockway . "Я могу' позволяя вам распределять состояние через ваш лексер. Затем посмотрите, как состояние используется в реализации макета GHC для реализации отступа / удаления правил макета. (Найдите «- Обработка макета» в лексере GHC, чтобы увидеть, как состояние перемещается и выталкивается).

позволяя вам распределять состояние через ваш лексер. Затем посмотрите, как состояние используется в реализации макета GHC для реализации отступа / удаления правил макета. (Найдите «- Обработка макета» в лексере GHC, чтобы увидеть, как состояние перемещается и выталкивается).

11
ответ дан 8 December 2019 в 14:44
поделиться

I can't store any global data anywhere with Haskell

This is not true; in most cases something like the State monad is sufficient, but there is also the ST monad.

You don't need global state for this task, however. Writing a parser consists of two parts; lexical analysis and syntax analysis. The lexical analysis just turns a stream of characters into a stream of meaningful tokens. The syntax analysis turns tokens into an AST; this is where you should deal with indentation.

As you are interpreting the indentation, you will call a handler function as the indentation level changes -- when it increases (nesting), you call your handler function (perhaps with one arg incremented, if you want to track the indentation level); when the level decreases, you simply return the relevant AST portion from the function.

(As an aside, using a global variable for this is something that would not occur to me in an imperative language either -- if anything, it's an instance variable. The State monad is very similar conceptually to this.)

Finally, I think the phrase "I can't put all my lexing rules inside any monad" indicates some sort of misunderstanding of monads. If I needed to parse and keep global state, my code would look like:

data AST = ...
type Step = State Int AST

parseFunction :: Stream -> Step
parseFunction s = do
   level <- get
   ...
   if anotherFunction then put (level + 1) >> parseFunction ...
   else parseWhatever
   ...
   return node

parse :: Stream -> Step
parse s = do
   if looksLikeFunction then parseFunction ...

main = runState parse 0 -- initial nesting of 0

Instead of combining function applications with (.) or ($), you combine them with (>>=) or (>>). Other than that, the algorithm is the same. (There is no "monad" to be "inside".)

Finally, you might like applicative functors:

eval :: Environment -> Node -> Evaluated
eval e (Constant x) = Evaluated x
eval e (Variable x) = Evaluated (lookup e x)
eval e (Function f x y) = (f <$> (`eval` x) <*> (`eval` y)) e

(or

eval e (Function f x y) = ((`eval` f) <*> (`eval` x) <*> (`eval` y)) e

if you have something like "funcall"... but I digress.)

There is plenty of literature on parsing with applicative functors, monads, and arrows; all of which have the potential to solve your problem. Read up on those and see what you get.

5
ответ дан 8 December 2019 в 14:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: