Re: Two-Dimensional Expression Layout

2016-08-21 Thread Lawrence D’Oliveiro
On Sunday, August 21, 2016 at 7:19:49 PM UTC+12, Michael Selik wrote:
>
> On Sun, Aug 21, 2016, 3:06 AM Lawrence D’Oliveiro wrote:
> 
>> On Sunday, August 21, 2016 at 6:49:19 PM UTC+12, Michael Selik wrote:
>>
>>> Indeed it is, not sure why.
>>
>> Moral: It helps to understand the code you’re criticizing, before you
>> start criticizing, not after.
> 
> A true statement, but not my takeaway from this discussion.

Really? Even after it has been pointed out to you?

I wonder what the name is for people like that...
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-21 Thread Michael Selik
On Sun, Aug 21, 2016, 3:06 AM Lawrence D’Oliveiro 
wrote:

> On Sunday, August 21, 2016 at 6:49:19 PM UTC+12, Michael Selik wrote:
>
> > Indeed it is, not sure why.
>
> Moral: It helps to understand the code you’re criticizing, before you
> start criticizing, not after.
>

A true statement, but not my takeaway from this discussion.

>
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-21 Thread Lawrence D’Oliveiro
On Sunday, August 21, 2016 at 6:49:19 PM UTC+12, Michael Selik wrote:

> Indeed it is, not sure why.

Moral: It helps to understand the code you’re criticizing, before you start 
criticizing, not after.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-21 Thread Michael Selik
On Sun, Aug 21, 2016 at 12:31 AM Lawrence D’Oliveiro 
wrote:

> On Sunday, August 21, 2016 at 12:44:21 PM UTC+12, Michael Selik wrote:
> >
> > On Sat, Aug 20, 2016 at 6:21 PM Lawrence D’Oliveiro wrote:
> >
> >>> if any(not isinstance(obj, Image) for obj in [src, mask, dest]):
> >>> ...
> >>
> >> Spot the bug in your version...
> >
> > - ``mask != None`` is unnecessary, unless somehow None has been
> registered
> > as an instance of Image.
>
> That’s the bug: it’s not unnecessary.
>
> Maybe a quick application of one of De Morgan’s theorems might help:
>
> if (
> isinstance(src, Image)
> and
> (mask == None or isinstance(mask, Image))
> and
> isinstance(dest, Image)
> ) :
> don’t raise TypeError("image args must be Image objects")
> #end if
>
> Is that better for you?
>

Indeed it is, not sure why. I think Steven's right in this case. Since the
condition isn't identical for all objects, and it's only three variables,
I'd rather break it apart.

if not isinstance(src, Image):
raise TypeError('src must be an Image')
if mask and not isinstance(mask, Image):
raise TypeError('mask must be an Image or None')
if not isinstance(dest, Image):
raise TypeError('dest must be an Image')

As he said as well, this has the added benefit of encouraging more explicit
error messages.

In programming and in prose, sometimes repetition feels ugly and redundant,
but sometimes repetition feels like a beautiful harmony.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Lawrence D’Oliveiro
On Sunday, August 21, 2016 at 12:44:21 PM UTC+12, Michael Selik wrote:
>
> On Sat, Aug 20, 2016 at 6:21 PM Lawrence D’Oliveiro wrote:
> 
>>> if any(not isinstance(obj, Image) for obj in [src, mask, dest]):
>>> ...
>>
>> Spot the bug in your version...
> 
> - ``mask != None`` is unnecessary, unless somehow None has been registered
> as an instance of Image.

That’s the bug: it’s not unnecessary.

Maybe a quick application of one of De Morgan’s theorems might help:

if (
isinstance(src, Image)
and
(mask == None or isinstance(mask, Image))
and
isinstance(dest, Image)
) :
don’t raise TypeError("image args must be Image objects")
#end if

Is that better for you?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Steve D'Aprano
Oh wait! The penny drops!

On Sun, 21 Aug 2016 10:43 am, Michael Selik wrote:

> On Sat, Aug 20, 2016 at 6:21 PM Lawrence D’Oliveiro

>> >> if (
>> >> not isinstance(src, Image)
>> >> or
>> >> mask != None and not isinstance(mask, Image)
>> >> or
>> >> not isinstance(dest, Image)
>> >> ) :
>> >> raise TypeError("image args must be Image objects")
>> >> #end if
>> >>
>> >
>> > No need for the separate calls to isinstance, nor the check for None.
>> >
>> > if any(not isinstance(obj, Image) for obj in [src, mask, dest]):
>> > ...
>>
>> Spot the bug in your version...
>>
> 
> It'd be easier if I ran the code :-)
> Let's see...
> - the ``or`` translates to an ``any(...)``
> - ``not isinstance(obj, Image)`` is repeated 3 times
> - ``[src, mask, dest]`` corresponds to the 3 objects
> - ``mask != None`` is unnecessary, unless somehow None has been registered
> as an instance of Image.
> 
> ... can't spot it. Give me a hint?

I think you've got the mask != None bit backwards. In Lawrence's version, if
mask is None, *no exception is raised*. In yours, it raises.

I think that it would be easier to reason about this code if it were written
in terms of positive assertions ("this condition is true") rather than
negative ("this condition is not true").

- src must be an Image;
- mask must be None or an Image;
- dest must be an Image.

Assuming I check for this in at least two places, I'd factor it out into a
helper function. There are probably a thousand ways to write it, and I'm
not married to any of them. Here are a couple:


def _validate(src, mask, dest):
if mask is None or isinstance(mask, Image) and \
all(isinstance(o) for o in [src, dest]):
return
raise TypeError("image args must be Image objects")


def _validate(src, mask, dest):
if not (
isinstance(src, Image) and
mask is None or isinstance(mask, Image) and 
isinstance(dest, Image)
   ):
raise TypeError("image args must be Image objects")


The logic is *just* tricky enough that if this were my code I would
absolutely insist on having unit tests for this helper. Beyond that, the
specific details of how you test them is not that important, but given that
there are only three arguments to be tested, I'm inclined to test each one
individually and give a more useful error message:

def _validate(src, mask, dest):
if not isinstance(src, Image):
raise TypeError("src must be an Image")
if mask is not None and not isinstance(mask, Image):
raise TypeError("mask must be None or an Image")
if not isinstance(dest, Image):
raise TypeError("dest must be an Image")




-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Steve D'Aprano
On Sun, 21 Aug 2016 10:43 am, Michael Selik wrote:

> On Sat, Aug 20, 2016 at 6:21 PM Lawrence D’Oliveiro
>  wrote:
> 
>> > p0 = (0, 0)
>> > p1 = (major_dim, 0)
>> > colour_stops = (0, rect_1_colour), (1, complement(rect_1_colour))
>> > rect_1_pattern = qah.Pattern.create_linear(p0, p1, colour_stops)
>>
>> That’s an example of what I mean about obscure structure.
>>
> 
> To each his own. I was assuming all those variable names meant something
> to you. If not, then I expect it'd read well with good names. In this
> example, I think the abbreviations and numbers in the names could be
> changed to something more meaningful.
> 
> 
>> >> From , a
>> >> complex condition (with redundant parentheses again):
>> >>
>> >> if (
>> >> not isinstance(src, Image)
>> >> or
>> >> mask != None and not isinstance(mask, Image)
>> >> or
>> >> not isinstance(dest, Image)
>> >> ) :
>> >> raise TypeError("image args must be Image objects")
>> >> #end if
>> >>
>> >
>> > No need for the separate calls to isinstance, nor the check for None.
>> >
>> > if any(not isinstance(obj, Image) for obj in [src, mask, dest]):
>> > ...
>>
>> Spot the bug in your version...
>>
> 
> It'd be easier if I ran the code :-)
> Let's see...
> - the ``or`` translates to an ``any(...)``
> - ``not isinstance(obj, Image)`` is repeated 3 times
> - ``[src, mask, dest]`` corresponds to the 3 objects
> - ``mask != None`` is unnecessary, unless somehow None has been registered
> as an instance of Image.
> 
> ... can't spot it. Give me a hint?

Earlier, Lawrence wrote about this same piece of code that using any() or
all() was not a good idea because, and I quote:

"There is no short-cut evaluation when constructing tuples and lists."

I think that he is envisaging a scenario where (say) src and mask are
defined, but dest is not, so 

[src, mask, dest]

will raise a NameError, but his earlier version of the code:


if (
not isinstance(src, Image)
or
mask != None and not isinstance(mask, Image)
or
not isinstance(dest, Image)
) :


will not, *provided* one of the tests on src or mask fail first.





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Steve D'Aprano
On Sun, 21 Aug 2016 09:44 am, Lawrence D’Oliveiro wrote:

> Why do you think I put in those “#end” lines?


Do you really want us to answer that? I don't think you will like the
answer.





-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Steve D'Aprano
On Sun, 21 Aug 2016 08:22 am, Lawrence D’Oliveiro wrote:

> Another example, from : the sequence of
> values is laid out to allow easy additions/modifications in future.

When replying, I normally try to trim unnecessary code snippets down to the
critical line or two, but in this case I think that it is important that I
leave Lawrence's example in place in all its glory. See below for further
comments.


> for \
> symname, funcname \
> in \
> (
> ("FC_FONT", "ft_font_face_create_for_ft_face"),
> ("FT_FONT", "ft_font_face_create_for_pattern"),
> ("IMAGE_SURFACE", "image_surface_create"),
> # TODO: MIME_SURFACE, OBSERVER_SURFACE?
> ("PDF_SURFACE", "pdf_surface_create"),
> ("PNG_FUNCTIONS", "surface_write_to_png"),
> ("PS_SURFACE", "ps_surface_create"),
> ("RECORDING_SURFACE", "recording_surface_create"),
> ("SCRIPT_SURFACE", "script_create"),
> ("SVG_SURFACE", "svg_surface_create"),
> {"USER_FONT", "user_font_face_create"},
> ) \
> :
> setattr \
>   (
> HAS,
> symname,
> hasattr(cairo, "cairo_" + funcname)
>   )
> #end for
> 
> As a bonus, this also counts as an example of data-driven programming.


Is the subtle bug in your code also a bonus?

If this bug has never bit you, it will when you try to run it under a
version of Python with hash randomization turned on. (3.5 and above, I
think.) You're (accidentally, I presume) relying on the set:

{"USER_FONT", "user_font_face_create"}

always iterating in the same order. It won't. I assume that's just a typo
and it's meant to be a tuple.

Your idiosyncratic layout obscures what should be a standard two-line for
loop in a jumble of unneeded backslashes, almost empty lines and
indentation.


for symname, funcname in FONT_TABLE:
setattr(HAS, symname, hasattr(cairo, "cairo_" + funcname))


where FONT_TABLE is defined previously. If you don't want to give this its
own name, you can embed it in the for loop:


for symname, funcname in [
("FC_FONT", "ft_font_face_create_for_ft_face"),
("FT_FONT", "ft_font_face_create_for_pattern"),
("IMAGE_SURFACE", "image_surface_create"),
# TODO: MIME_SURFACE, OBSERVER_SURFACE?
("PDF_SURFACE", "pdf_surface_create"),
("PNG_FUNCTIONS", "surface_write_to_png"),
("PS_SURFACE", "ps_surface_create"),
("RECORDING_SURFACE", "recording_surface_create"),
("SCRIPT_SURFACE", "script_create"),
("SVG_SURFACE", "svg_surface_create"),
("USER_FONT", "user_font_face_create"),
]:
setattr(HAS, symname, hasattr(cairo, "cairo_" + funcname))



There's no need to arbitrarily indent parts of expressions to "allow easy
additions" in the future: it is already easy to add new tuples to the
table, or modify existing ones.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Michael Selik
On Sat, Aug 20, 2016 at 8:43 PM Michael Selik 
wrote:

> On Sat, Aug 20, 2016 at 6:21 PM Lawrence D’Oliveiro <
> lawrenced...@gmail.com> wrote:
>
>> > p0 = (0, 0)
>> > p1 = (major_dim, 0)
>> > colour_stops = (0, rect_1_colour), (1, complement(rect_1_colour))
>> > rect_1_pattern = qah.Pattern.create_linear(p0, p1, colour_stops)
>>
>> That’s an example of what I mean about obscure structure.
>>
>
> To each his own. I was assuming all those variable names meant something
> to you. If not, then I expect it'd read well with good names. In this
> example, I think the abbreviations and numbers in the names could be
> changed to something more meaningful.
>

I think that came out wrong. Let me try again...

origin = 0, 0
destination = width, 0
start_color = 0, selected_color
stop_color = 1, complement(selected_color)
pattern = qah.Pattern.from_line(origin, destination, (start_color,
stop_color))

Better?
I wasn't sure what the numbers 0 and 1 are doing for the colour_stops.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Michael Selik
On Sat, Aug 20, 2016 at 6:21 PM Lawrence D’Oliveiro 
wrote:

> > p0 = (0, 0)
> > p1 = (major_dim, 0)
> > colour_stops = (0, rect_1_colour), (1, complement(rect_1_colour))
> > rect_1_pattern = qah.Pattern.create_linear(p0, p1, colour_stops)
>
> That’s an example of what I mean about obscure structure.
>

To each his own. I was assuming all those variable names meant something to
you. If not, then I expect it'd read well with good names. In this example,
I think the abbreviations and numbers in the names could be changed to
something more meaningful.


> >> From , a
> >> complex condition (with redundant parentheses again):
> >>
> >> if (
> >> not isinstance(src, Image)
> >> or
> >> mask != None and not isinstance(mask, Image)
> >> or
> >> not isinstance(dest, Image)
> >> ) :
> >> raise TypeError("image args must be Image objects")
> >> #end if
> >>
> >
> > No need for the separate calls to isinstance, nor the check for None.
> >
> > if any(not isinstance(obj, Image) for obj in [src, mask, dest]):
> > ...
>
> Spot the bug in your version...
>

It'd be easier if I ran the code :-)
Let's see...
- the ``or`` translates to an ``any(...)``
- ``not isinstance(obj, Image)`` is repeated 3 times
- ``[src, mask, dest]`` corresponds to the 3 objects
- ``mask != None`` is unnecessary, unless somehow None has been registered
as an instance of Image.

... can't spot it. Give me a hint?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Lawrence D’Oliveiro
On Sunday, August 21, 2016 at 10:35:08 AM UTC+12, c...@zip.com.au wrote:
> Aye, but beware that the expression is actually correct for the
> indentation.  
> Compare:
> 
>assert \
>(
>len(self.points) == 0
>and
>not self.points[0].off
>or
>(closed or not self.points[-1].off)
> 
> where the precedence causes the layout to mislead.

At least there is a discrepancy between the two to set alarm bells ringing.

Compare statement indentation, where Python got rid of the statement brackets, 
so there is no more redundancy to be checked.

Why do you think I put in those “#end” lines?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread cs

On 19Aug2016 16:11, Lawrence D’Oliveiro  wrote:

On Saturday, August 20, 2016 at 10:38:34 AM UTC+12, Chris Angelico wrote:

On Sat, Aug 20, 2016 at 8:31 AM, Lawrence D’Oliveiro wrote:

There is no short-cut evaluation when constructing tuples and lists.


I'm not sure how that would make difference in these examples. The
three parts are independent - the one place where short-circuiting is
important is indeed short-circuited.


That often is not the case, e.g. 
:

   assert \
   (
   len(self.points) == 0
   or
   not self.points[0].off
   and
   (closed or not self.points[-1].off)
   )


Aye, but beware that the expression is actually correct for the indentation.  
Compare:


  assert \
  (
  len(self.points) == 0
  and
  not self.points[0].off
  or
  (closed or not self.points[-1].off)

where the precedence causes the layout to mislead.

I'm not arguing against indented spread out layout here, I use it myself, but 
just mentioning that the human eye will tend to take the visual layout over a 
strict parse. So care is needed, as in all programming.


Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Lawrence D’Oliveiro
On Friday, August 19, 2016 at 8:56:31 PM UTC+12, I wrote:
> It is handy to be able to keep complex expressions together sometimes, when
> breaking them up would simply obscure their structure. To avoid lines
> getting long, why not take advantage of the two available screen/page
> dimensions to make their structure clearer? As a bonus, spacing out
> parentheses makes them look less of a clutter.

Another example, from : the sequence of values 
is laid out to allow easy additions/modifications in future.

for \
symname, funcname \
in \
(
("FC_FONT", "ft_font_face_create_for_ft_face"),
("FT_FONT", "ft_font_face_create_for_pattern"),
("IMAGE_SURFACE", "image_surface_create"),
# TODO: MIME_SURFACE, OBSERVER_SURFACE?
("PDF_SURFACE", "pdf_surface_create"),
("PNG_FUNCTIONS", "surface_write_to_png"),
("PS_SURFACE", "ps_surface_create"),
("RECORDING_SURFACE", "recording_surface_create"),
("SCRIPT_SURFACE", "script_create"),
("SVG_SURFACE", "svg_surface_create"),
{"USER_FONT", "user_font_face_create"},
) \
:
setattr \
  (
HAS,
symname,
hasattr(cairo, "cairo_" + funcname)
  )
#end for

As a bonus, this also counts as an example of data-driven programming.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Lawrence D’Oliveiro
On Sunday, August 21, 2016 at 12:48:46 AM UTC+12, Michael Selik wrote:
>
> On Fri, Aug 19, 2016 at 5:01 AM Lawrence D’Oliveiro wrote:
> 
>> It is handy to be able to keep complex expressions together sometimes,
>> when breaking them up would simply obscure their structure.
> 
> p0 = (0, 0)
> p1 = (major_dim, 0)
> colour_stops = (0, rect_1_colour), (1, complement(rect_1_colour))
> rect_1_pattern = qah.Pattern.create_linear(p0, p1, colour_stops)

That’s an example of what I mean about obscure structure.

>> From , a
>> complex condition (with redundant parentheses again):
>>
>> if (
>> not isinstance(src, Image)
>> or
>> mask != None and not isinstance(mask, Image)
>> or
>> not isinstance(dest, Image)
>> ) :
>> raise TypeError("image args must be Image objects")
>> #end if
>>
> 
> No need for the separate calls to isinstance, nor the check for None.
> 
> if any(not isinstance(obj, Image) for obj in [src, mask, dest]):
> ...

Spot the bug in your version...
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-20 Thread Michael Selik
On Fri, Aug 19, 2016 at 5:01 AM Lawrence D’Oliveiro 
wrote:

> It is handy to be able to keep complex expressions together sometimes,
> when breaking them up would simply obscure their structure. To avoid lines
> getting long, why not take advantage of the two available screen/page
> dimensions to make their structure clearer? As a bonus, spacing out
> parentheses makes them look less of a clutter.
>
>

> Examples from <
> https://github.com/ldo/qahirah_examples/blob/master/operators>:
>
> A function call with complex arguments (specifying arguments by keywords
> is highly recommended here):
>
> rect_1_pattern = \
> qah.Pattern.create_linear \
>   (
> p0 = (0, 0),
> p1 = (major_dim, 0),
> colour_stops =
> (
> (0, rect_1_colour),
> (1, complement(rect_1_colour)),
> )
>   )
>

I'd rather have intermediate variables and avoid the non-semantic
indentation.

p0 = (0, 0)
p1 = (major_dim, 0)
colour_stops = (0, rect_1_colour), (1, complement(rect_1_colour))
rect_1_pattern = qah.Pattern.create_linear(p0, p1, colour_stops)



Computing a variable value (using redundant parentheses to avoid
> backslash-continuations):
>
> dest_rect = \
> (
> draw_bounds
> +
> Vector(col, row) * draw_bounds.dimensions
> +
> Vector(0, top_extra)
> )
>

I'd rather have one long line for this case, even if it's "too long" by PEP
8 standards. If it's too long to think about, I'd break the task into
parts, each with a well-considered variable name.

substep = a + b
final = substep + c



From , a
> complex condition (with redundant parentheses again):
>
> if (
> not isinstance(src, Image)
> or
> mask != None and not isinstance(mask, Image)
> or
> not isinstance(dest, Image)
> ) :
> raise TypeError("image args must be Image objects")
> #end if
>

No need for the separate calls to isinstance, nor the check for None.

if any(not isinstance(obj, Image) for obj in [src, mask, dest]):
...


If you prefer maps to comprehensions:

is_image = lambda obj: isinstance(obj, Image)
if any(map(is_image, [src, mask, dest])):
...
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread Lawrence D’Oliveiro
On Friday, August 19, 2016 at 8:56:31 PM UTC+12, I wrote:
> To avoid lines getting long, why not take advantage of the two available
> screen/page dimensions to make [expression] structure clearer?

Another aspect of this has to do with line length. I regularly set my editor 
window width to around 100 columns. But if you exclude indentation whitespace, 
my lines are usually much shorter than that.

There is a limit to the length of text lines that a human reader can cope with 
(which is why newspapers, for example, tend to have a many-column layout). 
Using two-dimensional layout and indentation helps to keep the (non-whitespace) 
line length within reasonable limits.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread Lawrence D’Oliveiro
On Saturday, August 20, 2016 at 10:38:34 AM UTC+12, Chris Angelico wrote:
>
> On Sat, Aug 20, 2016 at 8:31 AM, Lawrence D’Oliveiro wrote:
>>
>> There is no short-cut evaluation when constructing tuples and lists.
> 
> I'm not sure how that would make difference in these examples. The
> three parts are independent - the one place where short-circuiting is
> important is indeed short-circuited.

That often is not the case, e.g. 
:

assert \
(
len(self.points) == 0
or
not self.points[0].off
and
(closed or not self.points[-1].off)
)
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread codewizard
On Friday, August 19, 2016 at 6:38:34 PM UTC-4, Chris Angelico wrote:
> On Sat, Aug 20, 2016 at 8:31 AM, Lawrence D’Oliveiro
>  wrote:
> > On Saturday, August 20, 2016 at 9:56:05 AM UTC+12, codew...@gmail.com wrote:
> >>
> >> On Friday, August 19, 2016 at 5:30:22 PM UTC-4, Lawrence D’Oliveiro wrote:
> >>
> >>> On Saturday, August 20, 2016 at 7:52:09 AM UTC+12, codew...@gmail.com
> >>> wrote:
>  if any([
>  not isinstance(src, Image),
>  mask != None and not isinstance(mask, Image),
>  not isinstance(dest, Image),
>  ]):
>  raise TypeError("image args must be Image objects")
> 
>  Or equivalently:
> 
>  if not all([
>  isinstance(src, Image),
>  mask is None or isinstance(mask, Image),
>  isinstance(dest, Image),
>  ]):
>  raise TypeError("image args must be Image objects")
> >>>
> >>> Using “all” or “any” in this sort of situation may not be such a good
> >>> idea.
> >>
> >> Would you care to elaborate?
> >
> > There is no short-cut evaluation when constructing tuples and lists.
> 
> I'm not sure how that would make difference in these examples. The
> three parts are independent - the one place where short-circuiting is
> important is indeed short-circuited.
> 
> ChrisA

Agreed. Besides, just because this technique has limitations, it's still useful 
for me to improve readability.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread Chris Angelico
On Sat, Aug 20, 2016 at 8:31 AM, Lawrence D’Oliveiro
 wrote:
> On Saturday, August 20, 2016 at 9:56:05 AM UTC+12, codew...@gmail.com wrote:
>>
>> On Friday, August 19, 2016 at 5:30:22 PM UTC-4, Lawrence D’Oliveiro wrote:
>>
>>> On Saturday, August 20, 2016 at 7:52:09 AM UTC+12, codew...@gmail.com
>>> wrote:
 if any([
 not isinstance(src, Image),
 mask != None and not isinstance(mask, Image),
 not isinstance(dest, Image),
 ]):
 raise TypeError("image args must be Image objects")

 Or equivalently:

 if not all([
 isinstance(src, Image),
 mask is None or isinstance(mask, Image),
 isinstance(dest, Image),
 ]):
 raise TypeError("image args must be Image objects")
>>>
>>> Using “all” or “any” in this sort of situation may not be such a good
>>> idea.
>>
>> Would you care to elaborate?
>
> There is no short-cut evaluation when constructing tuples and lists.

I'm not sure how that would make difference in these examples. The
three parts are independent - the one place where short-circuiting is
important is indeed short-circuited.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread Lawrence D’Oliveiro
On Saturday, August 20, 2016 at 9:56:05 AM UTC+12, codew...@gmail.com wrote:
>
> On Friday, August 19, 2016 at 5:30:22 PM UTC-4, Lawrence D’Oliveiro wrote:
>
>> On Saturday, August 20, 2016 at 7:52:09 AM UTC+12, codew...@gmail.com
>> wrote:
>>> if any([
>>> not isinstance(src, Image),
>>> mask != None and not isinstance(mask, Image),
>>> not isinstance(dest, Image),
>>> ]):
>>> raise TypeError("image args must be Image objects")
>>> 
>>> Or equivalently:
>>> 
>>> if not all([
>>> isinstance(src, Image),
>>> mask is None or isinstance(mask, Image),
>>> isinstance(dest, Image),
>>> ]):
>>> raise TypeError("image args must be Image objects")
>> 
>> Using “all” or “any” in this sort of situation may not be such a good
>> idea.
> 
> Would you care to elaborate?

There is no short-cut evaluation when constructing tuples and lists.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread codewizard
On Friday, August 19, 2016 at 5:30:22 PM UTC-4, Lawrence D’Oliveiro wrote:
> On Saturday, August 20, 2016 at 7:52:09 AM UTC+12, codew...@gmail.com wrote:
> > if any([
> > not isinstance(src, Image),
> > mask != None and not isinstance(mask, Image),
> > not isinstance(dest, Image),
> > ]):
> > raise TypeError("image args must be Image objects")
> > 
> > Or equivalently:
> > 
> > if not all([
> > isinstance(src, Image),
> > mask is None or isinstance(mask, Image),
> > isinstance(dest, Image),
> > ]):
> > raise TypeError("image args must be Image objects")
> 
> Using “all” or “any” in this sort of situation may not be such a good idea. 
> More reasonable uses would be like 
> :
> 
> if any(uvface.flipped for uvface in island.faces):
> 
> if any(island.bounding_box.x > cage_size.x or island.bounding_box.y > 
> cage_size.y for island in self.islands):

You showed examples where you think it would be a good idea to use any/all.
But you didn't say why my examples "may not be such a good idea".
Would you care to elaborate?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread Lawrence D’Oliveiro
On Saturday, August 20, 2016 at 5:53:22 AM UTC+12, Terry Reedy wrote:
>
> To me, putting parens and '+' and 'or' on separate lines emphasizes them 
> too much and makes the layout more, not less, cluttered.

So having whitespace around these symbols makes things look *more* cluttered, 
while packing them together without whitespace makes them *less* cluttered?
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread Lawrence D’Oliveiro
On Saturday, August 20, 2016 at 7:52:09 AM UTC+12, codew...@gmail.com wrote:
> if any([
> not isinstance(src, Image),
> mask != None and not isinstance(mask, Image),
> not isinstance(dest, Image),
> ]):
> raise TypeError("image args must be Image objects")
> 
> Or equivalently:
> 
> if not all([
> isinstance(src, Image),
> mask is None or isinstance(mask, Image),
> isinstance(dest, Image),
> ]):
> raise TypeError("image args must be Image objects")

Using “all” or “any” in this sort of situation may not be such a good idea. 
More reasonable uses would be like 
:

if any(uvface.flipped for uvface in island.faces):

if any(island.bounding_box.x > cage_size.x or island.bounding_box.y > 
cage_size.y for island in self.islands):
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread codewizard
For some special cases, I prefer the versions below.


On Friday, August 19, 2016 at 4:56:31 AM UTC-4, Lawrence D’Oliveiro wrote:
> [snip]
> 
> Computing a variable value (using redundant parentheses to avoid 
> backslash-continuations):
> 
> dest_rect = \
> (
> draw_bounds
> +
> Vector(col, row) * draw_bounds.dimensions
> +
> Vector(0, top_extra)
> )

dest_rect = sum([
draw_bounds,
(col, row) * draw_bounds.dimensions,
Vector(0, top_extra),
])


> From , a complex 
> condition (with redundant parentheses again):
> 
> if (
> not isinstance(src, Image)
> or
> mask != None and not isinstance(mask, Image)
> or
> not isinstance(dest, Image)
> ) :
> raise TypeError("image args must be Image objects")
> #end if

if any([
not isinstance(src, Image),
mask != None and not isinstance(mask, Image),
not isinstance(dest, Image),
]):
raise TypeError("image args must be Image objects")

Or equivalently:

if not all([
isinstance(src, Image),
mask is None or isinstance(mask, Image),
isinstance(dest, Image),
]):
raise TypeError("image args must be Image objects")
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Two-Dimensional Expression Layout

2016-08-19 Thread Terry Reedy

On 8/19/2016 4:56 AM, Lawrence D’Oliveiro wrote:

It is handy to be able to keep complex expressions together sometimes, when 
breaking them up would simply obscure their structure. To avoid lines getting 
long, why not take advantage of the two available screen/page dimensions to 
make their structure clearer? As a bonus, spacing out parentheses makes them 
look less of a clutter.

Examples from :


To me, putting parens and '+' and 'or' on separate lines emphasizes them 
too much and makes the layout more, not less, cluttered.  But I won't 
argue with what you do in your own private code.



A function call with complex arguments (specifying arguments by keywords is 
highly recommended here):

rect_1_pattern = \
qah.Pattern.create_linear \
  (
p0 = (0, 0),
p1 = (major_dim, 0),
colour_stops =
(
(0, rect_1_colour),
(1, complement(rect_1_colour)),
)
  )

Computing a variable value (using redundant parentheses to avoid 
backslash-continuations):

dest_rect = \
(
draw_bounds
+
Vector(col, row) * draw_bounds.dimensions
+
Vector(0, top_extra)
)

From , a complex 
condition (with redundant parentheses again):

if (
not isinstance(src, Image)
or
mask != None and not isinstance(mask, Image)
or
not isinstance(dest, Image)
) :
raise TypeError("image args must be Image objects")
#end if




--
Terry Jan Reedy


--
https://mail.python.org/mailman/listinfo/python-list