#WritersCoffeeClub June 22. What's the best piece of writing advice you ever received?

"There's more than one way to do it." By Larry Wall. Who, okay, was talking about software: but he's also a linguist and wrote a couple of (non-fiction) books and invented an incredibly flexible programming language that obeyed that dictum and he was absolutely right.

(Beyond that? Heinlein: "finish every story you start, send it out, then don't wait for it to sell before you start a new one.")

@cstross Perl. Aaaugh. I wrote Perl professionally for a few years. It has a deserved reputation as a read-only language. "There's more than one way to do it" means in practice you have to know _every_ way to do it. A huge PITA.

I much prefer C, C++, and Python. Code in those languages is far easier to maintain. Even bash code is preferable.

And I _met_ Tom Christiansen on a Linux Lunacy cruise.

@lemgandi @cstross The reputation was for being "write-only", and was propagated by people who didn't realize one does NOT have to know "every" way to code it in order to write something well.

What one _does_ need is the ability to learn and teach, and to write code with a human audience in mind.

Coding can be extremely fun, and especially with #Perl and #RakuLang - IF you allow yourself to play and share the joy.

Don't be a #toolblamer, be a good colleague instead.

#fwp #fwr

@sjn @lemgandi @cstross

That's only true if you never ever work on any code that anyone else has ever written or modified. If you do, you have to be a Perl language lawyer.

Be a good colleague, write code in better languages.

@resuna @lemgandi @cstross With apologies, but that claim is not only false, but also a "perl truism" that deserves to be classified as #disinformation.

Be a good colleague, write & share something awesome in your favorite language – and if that is #Perl, then all power to you!

Though I acknowledge that if "everyone" insists on writing bad code… Maybe consider moving to a better place? 😅

Even if no-one else tries, it's still admirable to gift your audience a good code-reading experience.

@resuna @sjn @lemgandi @cstross Absolutely not my experience, and I've worked with hundreds of Perl modules that were written or modified by other people. I've never had to be a language lawyer.

What's far more annoying is formatting idiosyncrasies like insisting on spaces between array names and indices (like $foo [0]), no space before = for assignment ($foo= 42;), or putting a line break before {, but not after:

sub foo($n)
{ my $x = false;
if ($n % 2 == 0)
{ $x = true;
# etc.
}
return $x;
}

Absolutely awful to work with if you need to remove the first statement or insert new statements before the first statement in a block.

Switching languages won't save you from these (OK, except for the case of braces in Python).

@barubary @sjn @lemgandi @cstross

So you just don't mind the half a dozen gratuitous variations on conditional statements and other syntactic elements, or you just got used to arbitrarily having if after the block or unless instead of if and forty dozen different quotes and here documents?

@resuna What half a dozen variations?

C (C++, Java, PHP, JavaScript, ...):

// single statement
if (foo) bar();
// block
if (foo) {
bar();
baz();
}

Perl:

// single statement
bar() if foo;
// block
if (foo) {
bar();
baz();
}

I don't mind unless if that's what you mean. It's just a negated if and follows the same syntax.

As for different string quoting styles, I actually like that a lot (especially custom delimiters). It lets you choose what is most readable for any given situation. But fundamentally, it's just two types of "normal" quotes (q and qq) and two types of here-doc. What do you think requires language lawyering?

Other languages have much more complicated syntax, e.g.:

2. Lexical analysis

A Python program is read by a parser. Input to the parser is a stream of tokens, generated by the lexical analyzer(also known as the tokenizer). This chapter describes how the lexical analyzer brea...

Python documentation

@barubary

The two "C" examples you give are the same picture. Blocks and single statements are not semantically different.

C:

if (condition) statement

Perl:

if (condition) statement

statement if (condition)

statement unless (condition)

There is no reason for the latter two to even exist.

And just about every data type, constant, control structure, or other semantic object in Perl has at least as many gratuitously different syntaxes for exactly the same thing.

@barubary

And I am not a stan for Python or C++. But they don't have gratuitous extra syntax for the sake of having extra syntax, C++ in particular is just fucked up for historical reasons because it grew out of a C preprocessor. It wasn't deliberately broken.

@resuna OK, then let's talk about basics. What's the difference between while (foo) and for (;foo;) in C?

Or let's say I want to get element i of array a in C++. Which one of these is correct?

  • a[i]
  • a<:i:>
  • i[a]
  • *(a + i)
  • 0<:i+a]

(Spoilers: It's all of them.)

How do I write logical conjunction? Is it a and b or a && b? (Answer: both.)

We could also talk about how the class keyword in C++ is 100% redundant: 95% of its use could be replaced by struct, the other 5% by typename.

Or let's say I want to declare an integer constant:

  • const int answer = 42;
  • const int answer (42);
  • const int answer = { 42 };
  • const int answer { 42 };
  • const int (answer) = 42;
  • int const answer = 42;
  • signed const answer = 42;
  • int const signed answer = 42;

As far as I know, these are all valid.

(Half of them are valid C, too. The C example of a fully redundant keyword is auto. The only thing that saves signed from being redundant is the existence of signed char, which is not a syntactic issue, but requires genuine language lawyering to fully explain.)

As for Python, I'm less familiar with it so I don't have a big list of examples ready. But I still found the following within a few minutes of looking:

What's the difference between 'abc', "abc", u'abc', u"abc", U'abc', and U"abc"?

What's the difference between def succ(x): return x + 1 and succ = lambda x: x + 1?

I have a variable x = 42. Which of the following is the correct way to print its value?

  • print("x is", x)
  • print("x is " + str(x))
  • print(f"x is {x}")
  • print("x is %d" % x)
  • print("x is %d" % (x,))

No gratuitous extra syntax, my behind.

In my opinion there is nothing wrong with syntactic sugar in general. Having extra syntax doesn't necessarily make a language bad, let alone broken. (Let alone "deliberately broken"; no language outside of the esoteric/joke language group is deliberately broken.)

But somehow it is only Perl that gets a bad rap for admitting (and embracing) that usually "there is more than one way to do it".

@barubary yes you can force C syntax into a bit of redundancy if you do things like taking advantage of the expression syntax. But it is not deliberately designed to have a bunch of redundant, functionally identical syntaxes for the same thing as a design goal of the language. Larry Wall specifically created redundant syntax because he believed that redundant syntax by itself was a good thing. This is unique to perl.

@barubary and I don’t know why you’re trying to get me to defend C++ and python, they have their own unique categories of stupidity, but they are not specifically designed with the specific kind of stupidity that perl enjoys.

Edit: you also seem to be confused about what's C and what's C++.

@resuna You are technically correct about the C grammar: A block ("compound statement") is just a type of statement. But that's not how I tend to think about it. In practice, it's more like "an if body can be either a single statement or multiple statements wrapped in braces" or even "the braces after if are optional if there's just a single statement in them". (Treating {} as special punctuation is also how most formatting styles work.)

However, that is not how Perl works. if (foo) bar(); is a syntax error. Perl requires a full block as the body of control structures like if, while, etc. Similarly, { bar(); } if (foo); is a syntax error because, in the modifier syntax, the thing before if cannot be a statement.

The correct syntactic forms for Perl are:

if ( <expression> ) <block>

<expression> if <expression> ;

Instead of if you can also have unless, while, or until. (There is also for, but its syntax is a bit more involved.)

So why does Perl require a full block after a control structure? Because it avoids the "dangling else" ambiguity typically found in C-like languages (in if (a) if (b) f(); else g();, which if does the else belong to?) and because it avoids an error where you start out with a simple statement in an if, but then add a second statement without adding braces:

if (cond)
foo();
bar(); // oops, bar() is called unconditionally

This kind of bug has caused security vulnerabilities (CVE-2014-1266 or the "goto fail" bug, https://en.wikipedia.org/wiki/Unreachable_code#goto_fail_bug) and Perl is immune to it, by design.

There is no reason for the latter two to even exist.

Sometimes they make code more readable. For example, many people think the following code reads quite naturally:

return $x
unless $x < 0;
...
push @ results, $record
if $record->matches($query);

And just about every data type, constant, control structure, or other semantic object in Perl has at least as many gratuitously different syntaxes for exactly the same thing.

Yeah, nah. I don't think that's true and the examples you've given so far are still just simple syntax (or syntax errors in some cases 😃). This is the stuff you'd expect to encounter in week 1 or 2 of learning Perl. We're not even close to "language lawyer" territory yet.

Unreachable code - Wikipedia

@barubary yeah OK I forgot about that stupid quirk of perl. You’re just making it worse.