Thread: Unary Operators
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.
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]
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.
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
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