Re: Using Vitalije's code patterns

2020-01-30 Thread Edward K. Ream
On Wed, Jan 29, 2020 at 11:10 PM Thomas Passin  wrote:

>> Methods can be used outside their class, say within another class, only
be instantiating a "helper" instance of the method's class.  That's a
clumsy pattern.

> This isn't quite  as true as you might think.  You can reuse them - in
other classes - by direct assignment:

Interesting. It's a pattern I haven't used yet.

> Where you can get into trouble is when class A's init code causes
conflicts with class B.  So you have to be thoughtful about initialization.

I'd rather just instantiate a helper class ;-)

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/CAMF8tS0xPenB33xahL6S%2B0f6pLqgy%3D7Asyu%2BfghK-1KHggFTFw%40mail.gmail.com.


Re: Using Vitalije's code patterns

2020-01-29 Thread Thomas Passin


On Thursday, January 30, 2020 at 12:10:50 AM UTC-5, Thomas Passin wrote:
>
>
> Class B:
> func2(self, parms) = A.func1
>

Oops, I meant to write 

Class B:
   func2 = A.func1

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/9216db20-962c-43ac-9191-406bf448bb86%40googlegroups.com.


Re: Using Vitalije's code patterns

2020-01-29 Thread Thomas Passin


On Tuesday, January 7, 2020 at 7:58:41 AM UTC-5, Edward K. Ream wrote:
>
> While working on leoAst.py, I have come to understand more fully several 
> of Vitalije's suggested code patterns:
>
> *Prefer functions to classes/methods*
>
> Classes and methods are essential in python. They aren't going away. 
> However, in some cases functions are preferable to methods, for several 
> reasons:
>
> 1. Functions are available "everywhere".  In contrast, methods are 
> available only within their enclosing class.
>
> Methods can be used outside their class, say within another class, only be 
> instantiating a "helper" instance of the method's class.  That's a clumsy 
> pattern.
>
> This isn't quite  as true as you might think.  You can reuse them - in 
other classes - by direct assignment:

Class A:
def func1(self, parms):
# Do something here

Class B:
func2(self, parms) = A.func1

# or

   def func2(self, parms):
  return A.func1(self, parms)

Where you can get into trouble is when class A's init code causes conflicts 
with class B.  So you have to be thoughtful about initialization.

Basically, there isn't a lot of difference between a function and a 
method.  It's the difference between

result = self.method1(parms)

and 

result = function1(instance, parms)

A class method is helpful when the function is closely tied to how the 
class works, or needs to use a lot of its state.  A function is more 
helpful when it isn't tied so closely to a particular class, or doesn't 
need to use much of its state.

We are fortunate with Python because we can have both, unlike say Java.

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/bd1e5ff2-2a5c-490d-8498-17adf86dcc46%40googlegroups.com.


Re: Using Vitalije's code patterns

2020-01-09 Thread Edward K. Ream
Thu, Jan 9, 2020 at 6:58 AM Brian Theado  wrote:

> I'm guessing this is a response only to my 2nd sentence and not both
sentences?

Correct.  But in this case the present code is better, imo.  I'm not
suggesting that we should prefer functions to classes generally.
Without a class, you would have to implement visit as a callback.

Isn't the purpose of 'visit' to be able to loop over the nodes?
>

The visit method visits the given node.  It's natural and good to have
subclasses visit nodes in subclass-specific ways.

At one extreme, the Fstringify class only cares about BinOp nodes, so
Fstringify.visit contains a single test.  At the other extreme, other
classes could dispatch on the type of node, as is done in Orange.beautify.

However, the Orange class doesn't need TOT.traverse, because tokens already
are in a specific order. As a result, the Orange class isn't a subclass of
TOT.

I'm happy with the TOT.traverse where it is.  You have little chance of
changing my mind. And my mind is elsewhere, as I'll soon explain in a new
post about using parse tree data in the Orange class.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/CAMF8tS1sbpHdN-VbE4ZaOMq6HTeN2CS_Dut_QLO081STSX8TwA%40mail.gmail.com.


Re: Using Vitalije's code patterns

2020-01-09 Thread Brian Theado
On Thu, Jan 9, 2020 at 5:28 AM Edward K. Ream  wrote:

> On Wed, Jan 8, 2020 at 10:49 PM Brian Theado 
> wrote:
>
> *>> Prefer functions to classes/methods*
>
> > The TokenOrderTraverser class looks to me like a good opportunity to
> follow the above principle. AFAICT, the way it is written, that class is
> ONLY useful if it is subclassed.
>
> True.
>

I'm guessing this is a response only to my 2nd sentence and not both
sentences?


>
> > For me, subclassing is usually extra friction and the resulting code is
> less clear.
>
> Without a class, you would have to implement visit as a callback.
>

Isn't the purpose of 'visit' to be able to loop over the nodes? Sounds like
the job of a for loop to me. No callbacks and no classes needed.

Having the traverse functionality reside in a method of TOT forces the user
to subclass. Extracting it into a separate function like
traverse_in_token_order allows the user to choose to use a for loop
instead. The TOT class can still exist. It would call the same
traverse_in_token_order convenience function. If the user want to do the
extra work of subclassing TOT, they still can.

Brian

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/CAO5X8CyfcQRWX7yPHWXaSY-tdJ%3DxRhtWH_7qZyJfvm1XcJYMZA%40mail.gmail.com.


Re: Using Vitalije's code patterns

2020-01-09 Thread Edward K. Ream
On Wed, Jan 8, 2020 at 10:49 PM Brian Theado  wrote:

*>> Prefer functions to classes/methods*

> The TokenOrderTraverser class looks to me like a good opportunity to
follow the above principle. AFAICT, the way it is written, that class is
ONLY useful if it is subclassed.

True.

> For me, subclassing is usually extra friction and the resulting code is
less clear.

Without a class, you would have to implement visit as a callback.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/CAMF8tS1hJKysk2-aRpgLxMZHVA_VUHBCXy3Lwq%3DoT2pFFjCqPA%40mail.gmail.com.


Re: Using Vitalije's code patterns

2020-01-08 Thread Brian Theado
On Tue, Jan 7, 2020 at 7:58 AM Edward K. Ream  wrote:

> While working on leoAst.py, I have come to understand more fully several
> of Vitalije's suggested code patterns:
>
> *Prefer functions to classes/methods*
>

The TokenOrderTraverser class looks to me like a good opportunity to follow
the above principle. AFAICT, the way it is written, that class is ONLY
useful if it is subclassed. For me, subclassing is usually extra friction
and the resulting code is less clear.

If the TokenOrderTraverser.traverse method were written as a function (say
'traverse_in_token_order(tree)') which is exactly the same except in place
of calling self.visit(node), it will 'yield node'. Then if you really think
you still need to have the TokenOrderTraverser class, you could still
implement then the traverse method:

def traverse(self, tree):
for node in traverse_in_token_order(tree):
self.visit(node)


IMO, the fstringify code would be clearer if it were not written as a
subclass of TOT.

With the subclass way, this is the minimum I could imagine to print all the
nodes:

class TokenOrderPrinter(TokenOrderTraverser):
def print(tree):
self.traverse(tree)

def visit(node):
print(str(node))

TokenOrderPrinter().print(tree)


The function/generator way has so much less friction for the developer
using it:

for node in traverse_in_token_order(tree):
print(str(node))


Brian

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/CAO5X8CzULeNHG5NnfmtqhiBdNz34LWJg4yJOEBOBR_nDx8_7cA%40mail.gmail.com.


Using Vitalije's code patterns

2020-01-07 Thread Edward K. Ream
While working on leoAst.py, I have come to understand more fully several of 
Vitalije's suggested code patterns:

*Prefer functions to classes/methods*

Classes and methods are essential in python. They aren't going away. 
However, in some cases functions are preferable to methods, for several 
reasons:

1. Functions are available "everywhere".  In contrast, methods are 
available only within their enclosing class.

Methods can be used outside their class, say within another class, only be 
instantiating a "helper" instance of the method's class.  That's a clumsy 
pattern.

2. Functions help "disentangle" classes.

This is a direct consequence of point 1.  Code shared via functions reduces 
dependencies between classes.

Disentangling classes greatly simplified the code in leoAst.py.

*Prefer limited duplication of code*

I have come to see that there is an ongoing, never-to-be-fully-resolved, 
tension between the DRY (Don't repeat yourself) principle and other design 
principles.

In particular, *limited* duplication of code can help untangle code. The 
great Glenford Myers talked about avoiding "modules" whose only purpose was 
to avoid duplicating code. I should have paid more attention.

I have come to see that some code duplication can sometimes be seen as 
documentation. The fs.fstringify_file and fs.fstringify_file_diff methods 
both contain the following code:

tog = TokenOrderGenerator()
contents, tokens, tree = tog.init_from_file(filename)
if not contents or not tokens or not tree:
return False
# fstringify.
self.fstringify(contents, filename, tokens, tree)
results = tokens_to_string(tokens)

Imo, this duplicated code has no series negative consequences.

*Avoid kwargs*

This has been an ongoing project. I had overused kwargs in order to "share" 
code. This often has significant negative consequences.  Better to keep 
functions and methods simple, and accept a bit of code duplication.

*Summary*

Functions can sometimes preferable to methods. They are more easily 
accessible and they may disentangle the relationships between classes.

Limited code duplication can also be useful. In some cases, they serve as 
useful documentation.

Avoiding kwargs is often a good idea, despite the potential for code 
duplication.

I thank Vitalije for his helpful suggestions.  These ideas would not have 
come to me on my own.

The code in leoAst.py is an example of my revised coding style.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/leo-editor/7de4afbe-373e-452b-89e1-e448cba2f81b%40googlegroups.com.