Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail From: Kaz Kylheku <643-408-1753@kylheku.com> Newsgroups: comp.lang.lisp Subject: Re: infix via code walker hook. Date: Fri, 4 Apr 2025 19:35:28 -0000 (UTC) Organization: A noiseless patient Spider Lines: 126 Message-ID: <20250404112007.58@kylheku.com> References: <20250331141507.905@kylheku.com> <20250401201007.528@kylheku.com> <20250403192220.35@kylheku.com> Injection-Date: Fri, 04 Apr 2025 21:35:29 +0200 (CEST) Injection-Info: dont-email.me; posting-host="0acdb8a9a9b6b4fb3b99d09777fb4d36"; logging-data="310197"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/qB2EFvA04mPlK2aSW+iMd/xN7nOY8Xh4=" User-Agent: slrn/pre1.0.4-9 (Linux) Cancel-Lock: sha1:MUJgaVLJ2loekxTDom1HE7LOi2A= Bytes: 4705 On 2025-04-04, Stefan Monnier wrote: >> 1> (parse-infix '(sin a + b + c + d)) >> (sin (+ (+ (+ a b) c) >> d)) >> >> But, if we put parentheses on the operand of sin, then it's no longer >> the unary sin, but a function call with that argument: >> >> 2> (parse-infix '(sin (a) + b + c + d)) >> (+ (+ (+ (sin a) b) >> c) >> d) > > For someone coming from "statically typed functional programming", this > is *very* weird. > All those languages (Haskell/OCaml/SML/Coq/Idris/Agda/...) treat > > (sin a + b + c + d) > > the same as > > (sin (a) + b + c + d) Ah, but how about higher precedence operators? Would you want sin a * b * c to be sin (a) * b *c If not, you're asking for the operator version of sin to be a unary operator with a higher precedence than plus or minus, but lower than multiplication. In math boox and papers, you certainly see expression like sin 2cx I believe I have also seen sin t + 1 But also: (sin t - cos t)**2 It seems that a useful behavior to have would be for the range of the unary operator to stop when we encounter another such unary operator; i.e. sin a + b + c + sin d + e + f ^ ^ Suppose that when the binary + is adjacent to a unary operator as above, we pretend that the + has a lower precedence. Ooh, that seems to nicely for all unary operators. I put into the parser a couple of hack lines which look like this: (iflet ((o3 [ifx-uops (car rest)])) (if (eq o1.arity :infix) (set o1 (copy o1) o1.prec (pred o3.prec)))) When about to process an infix operator o1, we first peek at the rest of the input. If it starts with a prefix operator, which we call o3, (since o2 is being used for a previous operator pushed onto the operator stack) then we duplicate the current o1 operator object, and give it a precedence that is one lower than the infix. (A better implementation would be to have a lexical variable here holding a copy of the precedence, and just adjust the lexical, so as not to copy the operator object.) Bam: What we want works: 2> (parse-infix '(sin x + x + cos y + y)) (+ (sin (+ x x)) (cos (+ y y))) Also the higher precedence unary minus now does the right thing, syntactically, FWIW: 3> (parse-infix '(- x * x * - y * y)) (* (- (* x x)) (- (* y y))) The rule is easy to understand and leads to intuitive, symmetric treatment of symmetric-looking formulas. A lower precedence prefix operator suddenly appearing in a chain of higher precedence operators should interrupt that chain, and begin a new chain piece at the same level of depth. Say, I wonder whether this logic could be nicely expressed in LAR(1) anymore. I have a feeling that not, because LALR(1) makes only simple shift or reduce Next question: should the precedence-lowering propagate thorugh stacks of prefix operators? Like here: 5> (parse-infix '(sin x + x + - cos y + y)) (sin (+ x (+ x (- (cos (+ y y)))))) When we are processing (+ - cos y ...), looking at the binarry +, should we take into consideration all the consecutive unary operators that prefix the rest of the input? In this case (- cos). And should we then take their lowest precedence? The idea being that cos propagates its low precedence to the higher precedence -, which propagates it to + (decremeted by 1). Then we could get the parse (+ (sin (+ x x)) (- (cos (+ y y)))) -- TXR Programming Language: http://nongnu.org/txr Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal Mastodon: @Kazinator@mstdn.ca