One of the other cool features about this project is how the check() functions are loaded based off the type of the node argument:
https://github.com/dosisod/refurb/blob/master/refurb/loader....
This also supports type unions, so you can register your check for binary and unary expressions by typing node as `BinaryExpr | UnaryExpr`.
seems like Scala is moving to more Python like and Python is moving to add some features from Scala.
Why specify all the specific fragments of mypy.nodes, instead of import *?
Docstrings in the middle of code should just die 1/2 of the screen is wasted
Why use a case statement if it only has one match?
I can't even figure out what lines 43-55 do, but that's a lot of nesting
with open(_) as f:
_ = f.read()
(Where _ can be anything, and f can be any name). The traditional alternative to lines 43-56 would be dozens of lines that check the top level of the AST, and if that matches against what the top level of the pattern is expecting, diving one layer deeper and checking that level against the next level of the pattern, etc, until you reach the leaves of your pattern. Once your familiar with pattern matching syntax, this is much easier to quickly read/grok/audit.Very interesting…
One of the projects I occasionally poke at is a burs (bottom-up rewrite system) generator used to do cost-based tree rewriting. Think this is a concept that might make sense in that context, just need to find the time to play…
glob imports are discouraged as it is hard to figure out where a name comes from (or if it’s just a typo).
> Docstrings in the middle of code should just die 1/2 of the screen is wasted
You mean the class level doc string? That shows up in the help of that class, so there is nowhere else to put it.
I also don’t see the point of a match with a single case.
Line 43-55 is the scrutinee (pattern) of the case statement. It only binds values to the given variables and enters the block if `node` matches the quite complex structure shown there.
The alternative would be doing something repetitive like this:
if not isinstance(node, WithStmt):
return
expr = node.expr
if not len(expr) == 1:
return
if not isinstance(expr, CallExpr):
return
callee = expr.callee
if not (isinstance(callee, NameExpr) and callee.name == 'open'):
return
... etc ...
You could do the same thing with duck typing and try/except, but the semantics would be different (sometimes you DO want nominal typing, even in python). if isinstance(node, WithStmt) AND
(len(node.expr) = 1) AND
isinstance(node.expr, CallExpr) AND
isinstance(node.expr.callee,NameExper) AND
(node.expr.callee.name == 'open') then
begin
do stuff here
end;It's a very elegant pattern match on a deeply nested structure. It's declarative, not imperative, so if you are concerned about "nesting complexity", you need not be.
How would you implement this otherwise?
There's too many layers of nesting, in too foreign a syntax for me to even parse.
I suspect it could be done a clearer manner in pascal.
[0]: https://youtu.be/ASRqxDGutpA?t=470 [1]: https://github.com/dosisod/refurb/blob/master/refurb/checks/...