Deutsch   English   Français   Italiano  
<20250404112007.58@kylheku.com>

View for Bookmarking (what is this?)
Look up another Usenet article

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>
 <jwvldsfrecv.fsf-monnier+comp.lang.lisp@gnu.org>
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 <monnier@iro.umontreal.ca> 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