Smylers wrote:
Jonathan Lang writes:
> If you expected it to be a string, why did you use curly braces?

Because it isn't possible to learn of all Perl (5 or 6) in one go.  And
in general you learn rules before exceptions to rules.

Agreed.

In general in Perl the replacement part of a substitution is a string,
one that takes interpolation like double-quoted strings do.

Here's where I differ from you.  In general, string literals are
delimited by quotes; pattern literals are delimited by forward
slashes; and closures (i.e., code literals) are delimited by curly
braces.  And once you learn that other delimiters are possible for
patterns and strings, that knowledge comes with the added fact that in
order to use a non-standard delimiter, you have to preface it with a
short tag clearly identifying what is being delimited.

In general, you can use literals anywhere you can use variables, and
vice versa.  There are two crucial exceptions to this, both of which
apply to the topic at hand: one is minor, and the other is major.  The
minor exception is the pattern-matching macro, m//.  This macro takes
a pattern literal and applies it as a match criterion to either the
current topic ($_) or whatever is attempting to match (via ~~).  m//
_must_ take a pattern literal; it cannot take a variable containing a
Regex object.  To do the latter, you have to embed the Regex object in
a pattern literal.

m// is a _minor_ exception because it can be viewed as being the
complement of rx// - both can be thought of as pattern literals, with
m// being a pattern literal that always attempts to create a Match
object and rx// being a pattern literal that always tries to create a
Regex object.  Meanwhile, you have the .match method: unlike m//,
.match isn't choosy about where it gets its Regex object; it can come
from a pattern literal, as with m//; it can be passed in by means of a
variable; it can be composed on the spot by an expression; and so on.
The possibilities are endless.

The s/// macro is a Frankenstein Monster, stitched together from the
bodies of a pattern literal and an interpolating string literal and
infused with the spirit of a search-and-replace algorithm.  Like the
m// macro, s/// can only work on literals, never on variables (unless,
as above, you embed them in literals).  In addition, if you choose a
non-bracketing delimiter for the pattern literal, you _must_ use the
same delimiter for the string literal.  (This is more of a handicap
than at first it seems: in general, different kinds of literals use
different delimiters.  With s///, you're forced to use the same
delimiter for two different kinds of literals: a pattern and a
string.)  Using bracketed delimiters for the pattern gets around this
problem, but you're still left with the fact that the delimiters for
the string no longer follow the common-sense rule of "either
double-quotes or 'qq' followed by something else" - no matter what
delimiters you apply here, the semantics remain the same - unlike
anywhere else that string literals are used.  And short of embedding
them in the literal (notice a trend here?), you cannot apply any
modifiers to the string - only to the pattern or to the
search-and-replace algorithm.  In this regard, the string literal is
the odd man out - s/// could be thought of as a pattern literal with
an auxiliary string literal attached to it, but not the other way
around.

There's nothing natural about this beastie; and if it wasn't so darn
useful, I'd advocate dropping it.

The .subst method bypasses _all_ of these problems, letting you use
distinct and independently modifiable literals for each of the pattern
and the string, or even letting you use a variable or expression to
supply the pattern (or string) in lieu of literals.  On the downside,
the .subst syntax isn't nearly as streamlined as the s/// syntax.  In
addition, there's the issue about delayed evaluation (or lack thereof)
of the string argument, currently being discussed.

In general in Perl if the default delimiter for something is
inconvenient you can pick a different delimiter -- this includes
patterns, and also strings.  And if you pick any sort of brackets for
your delimiters then they match -- which is handy, cos it means that
they can still be used even if the string inside contains some of those
brackets.

As noted above, if you choose non-standard delimiters, you have to
explicitly tag them; and with the exception of s/// and tr///, a given
set of delimiters delimits one thing at a time.  s/// and tr/// are
exceptions to the general rule.

So it's quite possible for somebody to have picked up all the above, and
have got used to using C<qq[long string]> or C<qq{long string}> when he
wishes to quote long strings.  The form with braces has the advantage
that they are relatively uncommon in text (and HTML, and SQL, and many
other typically encountered long strings).

And he will be used to saying 'qq{long string}', as opposed to '{long
string}', when he expects the curly braces to act as string
delimiters.

At which point if he wants to do substitution with slashes in at least
one of the pattern or the replacement text (perhaps it's a URL or a
filename) then he's likely to pick some other arbitrary characters for
doing the quoting.  And braces seem as likely to be picked as anything
else.  Unless he specifically knows about an exception there's no reason
not to pick them.

However, he _will_ have to get used to the fact that both sets of
delimiters will have their semantics controlled by a common tag (the
leading s).  This is _not_ an intuitive step to make, and it is only a
neccessary one when you're using non-bracketing delimiters for the
pattern literal.

I refer simply to "Perl" above.  The above situation could just as
easily arise (or already have arisen) in Perl 5 -- in which case the
programmer's expectations would've been met and the code interpreted
fine.  Your proposal would make that no longer the case in Perl 6.

Agreed.  For instance, I learned about the above in perl 5.  IMHO,
this is a perl 5 flaw; I'd like to see as little of it carried over to
perl 6 as possible.

That's unfortunate, but probably liveable with in general.  But in this
particular case the particular behaviour involves _executing as Perl
code something which the programmer never intended to be code in the
first place_.  That's crazily dangerous.

I'll have to grant you that.  Still, it's not too hard to have the
perl5-to-perl6 porting code include a part that prepends 'qq' onto any
non-double-quote second-half delimiters of a s[]'' construct.  This
results in the perl6 version of the code doing precisely what the
perl5 version did, and being a bit more explicit that that's what's
being done.

> While I'm completely on board with the idea that _pattern_ delimiters
> shouldn't affect the _pattern's_ semantics, the second half of the
> search-and-replace syntax isn't a pattern.  Conceptually, it's either
> a string or an expression that returns a string.

Sure.  Or rather, it's a string (but braces inside strings can be used
to embed expressions in them).

To be consistent your proposal should also suggest that these become
equivalent:

* "{ function() }"
* qq[ {function() }]
* qq{ function() }
* eval "function()"

How so?  AFAIK, string literal syntax requires you to prepend a sigil
on the front of any embedded closure that you want to interpolate a
value from; otherwise, it isn't a closure - it's just a pair of
curly-brace characters.  My proposal isn't "curly braces _always_ act
like closures, no matter what"; it's "the second part of a s[]
construct doesn't have to be a literal; it can be anything that can be
evaluated as needed by the algorithm to provide substitute text."

and, naturally, that these no longer are:

* "string"
* qq[string]
* qq{string}

Why not?  The qq tag defines the semantics of the [] and {} in the
second two cases to match the semantics of the first.  Apparently,
you've gravely misunderstood what I'm trying to say.

--
Jonathan "Dataweaver" Lang

Reply via email to