Обсуждение: Unary Operators

Поиск
Список
Период
Сортировка

Unary Operators

От
Andreas Ulbrich
Дата:
Salvete!

I have the following problem.
I'd like to define the operator symbol / as a left unary operator for
reciprocal value of a number.
I did this with a C-function and all the stuff around, but it does not work.
Hiere is an extract and simplified example with the same error message
as in my complex example:

create function reciproce(float) returns float as
$$ values(1.0::float / $1) $$ language sql immutable strict;
create operator / (rightarg = float, procedure = reciproce);
select / 5.0::float;
-->
ERROR:  syntax error at or near "/"
LINE 1: select / 5.0;

This is in 9.3.0 and 9.2.4 the same.

If I take the ! as the operator all is fine:
create operator ! (rightarg = float, procedure = reciproce);
select ! 5.0::float;
-->
?column?
----------
       0.2
(1 row)

The definition seems to be equivalent:
# \do
                                  List of operators
  Schema | Name | Left arg type |  Right arg type  | Result type    |
Description
--------+------+---------------+------------------+------------------+-------------
  public | !    |               | double precision | double precision |
  public | /    |               | double precision | double precision |
(2 rows)

create operator ^- (leftarg = float, procedure = reciproce);
works too, but
create operator / (leftarg = float, procedure = reciproce);
not.

In the documentation I can't find, that / is not possible as an unary
operator.

Are there any restrictions.



Re: Unary Operators

От
Rowan Collins
Дата:
On 15/09/2013 19:32, Andreas Ulbrich wrote:
> Salvete!
>
> I have the following problem.
> I'd like to define the operator symbol / as a left unary operator for
> reciprocal value of a number.
> I did this with a C-function and all the stuff around, but it does not
> work.
> Hiere is an extract and simplified example with the same error message
> as in my complex example:
>
> create function reciproce(float) returns float as
> $$ values(1.0::float / $1) $$ language sql immutable strict;
> create operator / (rightarg = float, procedure = reciproce);
> select / 5.0::float;
> -->
> ERROR:  syntax error at or near "/"
> LINE 1: select / 5.0;

Interesting that it's a syntax error. Defining it as  // works fine, so
it's not the / symbol in general that's causing the problem, but
specifically a token consisting only of a single /, which presumably
(nearly) matches some particular rule in the parser.

The documentation page on Lexical Structure
(http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html)
doesn't specifically mention that this is reserved when it is describing
restrictions on custom operators. However, further down that page it
says "The precedence and associativity of the operators is hard-wired
into the parser." and "the operator precedence rules also apply to
user-defined operators that have the same names as the built-in
operators mentioned above". Note that + and - exist both as unary and
binary operators, but with different rules; any custom operators, on the
other hand, fall into a fairly low-precedence "any other" bucket.

My guess is that the "hard-wired" parsing rule for the (binary) /
operator is trying to match the / in your query, and failing to find its
left-hand argument. The "some other operator" rule, which would be able
to look for a unary operator, isn't even getting a chance. This is borne
out by looking at the other operators in that table - I've tried ^ and *
and get the same error (you need some extra brackets around "SELECT (*
5.0)" otherwise it would look like "SELECT *", which is an entirely
different piece of syntax!).

Someone who knows more about the internals may come along and tell me
I'm barking up completely the wrong tree, but it's at least a logical
explanation. If it is true, it should probably either be considered a
parser bug, or listed as a restriction on operator creation alongside --
and /* (or both).

Regards,
--
Rowan Collins
[IMSoP]


Re: Unary Operators

От
David Johnston
Дата:
Andreas Ulbrich wrote
> create operator ^- (leftarg = float, procedure = reciproce);
> works too, but
> create operator / (leftarg = float, procedure = reciproce);
> not.

Do you mean the "^" operator or the "^-" operator?  Rowan claims that "^"
does not in fact work here...


Rowan Collins wrote
> I've tried ^ and *
> and get the same error (you need some extra brackets around "SELECT (*
> 5.0)" otherwise it would look like "SELECT *", which is an entirely
> different piece of syntax!).

I would tend to concur with the "hard-wired" theory but am in the same boat
that I'm not really able to prove so; but figured I'd give my support.

This qualifies as documentation improvement potential at minimum so in the
interest of getting more notice I'd suggest reconciling the "^" discrepancy
- and maybe trying the other supposedly hybrid operators and stating which
ones work and don't work for the report - and move this over there.

David J.




--
View this message in context: http://postgresql.1045698.n5.nabble.com/Unary-Operators-tp5770983p5771360.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.


Re: Unary Operators

От
Andreas Ulbrich
Дата:
On 18.09.2013 02:17, David Johnston wrote:
> Andreas Ulbrich wrote
>> create operator ^- (leftarg = float, procedure = reciproce);
>> works too, but
>> create operator / (leftarg = float, procedure = reciproce);
>> not.
> Do you mean the "^" operator or the "^-" operator?  Rowan claims that "^"
> does not in fact work here...
>
>
> --
> View this message in context: http://postgresql.1045698.n5.nabble.com/Unary-Operators-tp5770983p5771360.html
> Sent from the PostgreSQL - general mailing list archive at Nabble.com.
>
>
I'd like to take the /-Operator as the inverse element of an element
relating to multiplication analogous the '-'-Operator for the inverse
relating to addition.
As a compromise, because the left unary / not work, I took '^-' for "to
the power of minus (one)".

It sounds logical, that native operators (4.1.6, Table 4-2) could be not
redefined with other number of arguments (% doesn't work to as left
unary...). But than a miss some documentation hints what are native
operators.

Thanks

Andreas


Re: Unary Operators

От
Tom Lane
Дата:
Andreas Ulbrich <andreas.ulbrich@matheversum.de> writes:
> In the documentation I can't find, that / is not possible as an unary
> operator.
> Are there any restrictions.

Yeah, if you look in the bison grammar you'll find out that the operators
with special precedence are hard-wired as to which syntaxes are allowed:

+ -                   prefix or infix
* / % ^ < > =        infix only

It's possible that if we just added some more productions these could be
used in nonstandard ways.  But I think interest in that is really pretty
low, and it might lead to behavior that would be surprising to people
who aren't interested in using them in weird ways.

            regards, tom lane