Post Reply 
prefix notation and () on newRPL project
01-21-2019, 05:06 PM
Post: #1
prefix notation and () on newRPL project
Hi Claudio,

2 Crazy ideas =)

◉ Observing the u_LISP project that has a notation similar to the prefix notation, and that the R-PN is a inverse prefix.
So I "think" it's easy to add a second type of operation engine PN/prefix ("eliminate" the Reverse) or consult it in this community if they are involved in this type of notation in your project.


[Image: lispbadgehand.jpg]


(3+4) * (5-6) returns -7 // "infix" operation or what better should be called standard notation

*( +(3,4), -(5,6) ) prefix operation with ( )
* + 3 4 - 5 6 prefix operation

◉ A second idea, RPN with parentheses, this gives a faster interpretation of the source code

3 4 + 5 6 - * postfix operation
((3,4)+, (5,6)-)* postfix operation with ()


The importance of the use of parentheses is that each operator can operate on n arguments
(a,b,c)+ (a,b,c,d,e)-
Find all posts by this user
Quote this message in a reply
01-21-2019, 05:51 PM
Post: #2
RE: prefix notation and () on newRPL project
(01-21-2019 05:06 PM)compsystems Wrote:  Hi Claudio,

2 Crazy ideas =)

◉ Observing the u_LISP project that has a notation similar to the prefix notation, and that the R-PN is a inverse prefix.
So I "think" it's easy to add a second type of operation engine PN/prefix ("eliminate" the Reverse) or consult it in this community if they are involved in this type of notation in your project.

◉ A second idea, RPN with parentheses, this gives a faster interpretation of the source code

3 4 + 5 6 - * postfix operation
((3,4)+, (5,6)-)* postfix operation with ()

The importance of the use of parentheses is that each operator can operate on n arguments
(a,b,c)+ (a,b,c,d,e)-

While crazy, adding alternate syntax rules to RPL is possible and I'm considering an alternate language to the same code.
The idea is to compile code in other languages to an RPL stream. Decompiling is much more complex so it would probably have to keep the source code separate (like most compiled languages).
Lisp would be very straighforward: An opening parenthesis simply compiles as the start of a list '{', everything gets pushed to the stream until a closing parenthesis is found, which is compiled as an end of list '}'. Then parenthesis simply pushes the number of arguments, then does LIST-> ROLL EVAL to execute the first argument.

But rather than adding a language of similar difficulty as RPL, the idea is to add a much higher level language, like Lua or python.
Compiling these languages is very difficult, so I'm still studying this as a possibility, not saying I might do it.
Find all posts by this user
Quote this message in a reply
01-21-2019, 06:17 PM
Post: #3
RE: prefix notation and () on newRPL project
(01-21-2019 05:51 PM)Claudio L. Wrote:  Lisp would be very straightforward …

But rather than adding a language of similar difficulty as RPL, the idea is to add a much higher level language, like Lua or python.

Not sure if you are aware of the power of Lisp macros.

Cheers
Thomas
Find all posts by this user
Quote this message in a reply
01-21-2019, 07:40 PM (This post was last modified: 01-21-2019 08:24 PM by Albert Chan.)
Post: #4
RE: prefix notation and () on newRPL project
(01-21-2019 05:06 PM)compsystems Wrote:  ◉ Observing the u_LISP project that has a notation similar to the prefix notation, and that the R-PN is a inverse prefix.
So I "think" it's easy to add a second type of operation engine PN/prefix ("eliminate" the Reverse) or consult it in this community if they are involved in this type of notation in your project.

Infix or rpn macro is not hard, but you are better off stay with lisp syntax.
It does not take much time to get used to (* (+ 3 4) (- 5 6))

BTW, does u-lisp support macro ?

Quote:◉ A second idea, RPN with parentheses, this gives a faster interpretation of the source code
The importance of the use of parentheses is that each operator can operate on n arguments (a,b,c)+ (a,b,c,d,e)-

It might not run faster.
I never tried u-lisp, but with Chez scheme 7.4d, (+ a b c) is slower than (+ (+ a b) c)

Above assumed a,b,c are variables. With numbers, both form optimized to a single number.
Find all posts by this user
Quote this message in a reply
01-21-2019, 09:37 PM
Post: #5
RE: prefix notation and () on newRPL project
(01-21-2019 06:17 PM)Thomas Klemm Wrote:  Not sure if you are aware of the power of Lisp macros.

Cheers
Thomas

I wasn't. I did a lot of Lisp programming many years ago, but not on a general purpose Lisp. I used to code AutoLISP, the implementation used in AutoCAD. I have no idea if that implementation had macros (since AutoCAD has another syntax for macros called Diesel), and I never needed to use them anyway.
But it looks really powerful. Unfortunately, that's not what I was talking about in this thread, implementing macros is a whole different animal than just doing the basic syntax over the RPL execution engine.
Find all posts by this user
Quote this message in a reply
01-22-2019, 03:06 PM
Post: #6
RE: prefix notation and () on newRPL project
(01-21-2019 05:51 PM)Claudio L. Wrote:  But rather than adding a language of similar difficulty as RPL, the idea is to add a much higher level language, like Lua or python.
Compiling these languages is very difficult, so I'm still studying this as a possibility, not saying I might do it.

Python on my 50g would be quite incredible! List comprehension alone would make my day.

Hmm. How hard would it be to do list comprehension in newRPL? I'm guessing very, but I honestly have no real idea.

Syntax would be something like the bastard love-child of FOR/NEXT and SEQ.
Find all posts by this user
Quote this message in a reply
01-22-2019, 07:32 PM
Post: #7
RE: prefix notation and () on newRPL project
(01-22-2019 03:06 PM)The Shadow Wrote:  List comprehension alone would make my day.

What's wrong with SEQ?

Python

>>> [ x**2 + 1 for x in range(1, 11, 2) ]

[2, 10, 26, 50, 82]

Algebraic

'SQ(X)+1'
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }

Or using RPL

« X SQ 1 + »
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }


Kind regards
Thomas
Find all posts by this user
Quote this message in a reply
04-20-2020, 02:01 AM (This post was last modified: 04-22-2020 08:43 PM by Albert Chan.)
Post: #8
RE: prefix notation and () on newRPL project
Here is a *fast* rpn macro for Chez Scheme
Instead of using macro pattern matching, the code rearrange the list of syntax objects.

Code:
(define ^ expt)

(define (rpn-aux lst)
  (let scan ([e (cdr lst)] [x (car lst)] [s '()])
    (if (null? e)
      (if (null? s) x [cons* #'list x s]) ; return x or stack
        (case (syntax->datum (car e))
          ((+ - * / ^) (scan (cdr e) [list (car e) (car s) x] [cdr s]))
          ((@)         (scan (cdr e) [list x (car s)] [cdr s]))
          ((swap)      (scan (cdr e) [car s] [cons x (cdr s)]))
          ((dup)
            (if (atom? (syntax->datum x))
              (scan (cdr e) x [cons x s])
              (let ([dup (datum->syntax (car e) (gensym))])
                (list #'let (list (list dup x))
                  (scan (cdr e) dup [cons dup s])))))
          (else (scan (cdr e) [car e] [cons x s])))))) ; push data

(define-syntax (rpn stx)
  (syntax-case stx ()
    ((rpn x ...) (rpn-aux #'(x ...)))))

scheme> (load "rpn.ss")
scheme> (define phi (rpn 5 sqrt @ 1 + 2 /))
scheme> (define (fib n) (rpn phi n ^ 1 phi - n ^ - 5 sqrt @ /))
scheme> (fib 10)
55.000000000000014
scheme> (fib 20)
6765.000000000005
Find all posts by this user
Quote this message in a reply
04-23-2020, 05:06 PM (This post was last modified: 11-04-2024 05:55 PM by Albert Chan.)
Post: #9
RE: prefix notation and () on newRPL project
For completeness, this is my attempt for infix-to-prefix calc macro, for Chez Scheme

Note: the code scan tokens in reverse, from right to left.
This simplified code to use stack only for (* /)

(calc whatever +/- x) ⇒ (+/- (calc whatever) x)     ; unary ± has higher precedence than infix ±
(calc whatever x ^ y) ⇒ (calc whatever (^ x y))     ; ^ has associativity right to left

Code:
(define ^ expt)
(define calc-aux #f)
(let ()
  (define (calc-obj obj)
    (if (atom? (syntax->datum obj)) obj
        (calc-aux (syntax->list obj))))

  (define (1st e)  (calc-obj (car e)))
  (define (2nd e)  (calc-obj (cadr e)))
  (define (op e)   (syntax->datum (car e)))
  (define (process e)   (scan (cdr  e) (1st e) '()))
  (define (rest e) (scan (cddr e) (2nd e) '()))
  (define (do-term a term) [set-car! (cdr term) a] term)
  (define (build a term) [fold-left do-term a term])

  (define (scan e a term)      ; work with reversed expression e
    (if (null? e) (build a term)
      (case (op e)
        ((+ -)  (if (null? (cdr e))
                    (build [list (car e) a] term)  ; unary +/-
                    (if (memq (op (cdr e)) '(+ - * / ^))
                        (scan (cdr e) [list (car e) a] term)  ; op +/-
                        (list (car e) [rest e] (build a term)))))
        ((* /)  (scan (cddr e) (2nd e) [cons [list (car e) #f a] term]))
        ((^)    (scan (cddr e) [list (car e) (2nd e) a] term))
        (else   (scan (cdr  e) (1st e) [cons [list #'* #f a] term])))))

  (set! calc-aux
    (lambda (e)
      (if (eq? (op e) '@)
        (cons (cadr e) (map calc-obj (cddr e))) ; (@ f ...) -> (f ...)
        (process (reverse e))))))

(define-syntax (calc stx)
  (syntax-case stx ()
    ((calc a ...) (calc-aux #'(a ...)))))

scheme> (load "calc.ss")
scheme> (calc - 2 ^ 3 ^ 4)     ; = - (2 ^ (3 ^ 4))
-2417851639229258349412352
scheme> (calc - (2 ^ 3) ^ 4)
-4096

scheme> (calc 1 + 2 3 4)       ; implied multiply
25
scheme> (define (calc-expand s) (syntax->datum (calc-aux (syntax->list s))))
scheme> (calc-expand #'(1 + 2 3 4))
(+ 1 (* (* 2 3) 4))

scheme> (define phi (calc (1 + (@ sqrt 5)) / 2))
scheme> (define (fib n) (calc (phi ^ n - (1 - phi) ^ n) / (@ sqrt 5)))
scheme> (fib 10)
55.000000000000014
scheme> (fib 20)
6765.000000000005

calc macro had unary (+ -) between binary (* /) and (+ -), similar to Fortran 77
see http://macnauchtan.com/pub/precedence.html#_Fortran


2024/11/4:

1. added unary +/- feature (next post)

scheme> (calc-aux '(- 3 * + 4 ^ - 5))
(* (- 3) (+ (^ 4 (- 5))))

2. added recursing into @ function arguments

scheme> (calc (@ sqrt
(5 *(((((1 + .2 *(350 / 661.5)^ 2)^ 3.5 - 1)*
(1 - 6.875E-6 * 25500)^ - 5.2656)+ 1)^ .286 - 1))))

0.8357245351752515
Find all posts by this user
Quote this message in a reply
12-23-2022, 02:59 AM (This post was last modified: 12-25-2022 06:12 PM by Albert Chan.)
Post: #10
RE: prefix notation and () on newRPL project
(12-23-2022 12:02 AM)Albert Chan Wrote:  How to distinguish subtraction from negation
Quote:If you can subtract, do it; if you can’t, then take it as a negation. Subtraction has priority.

Scanning backward, it will handle (op +/-) without issue.

2^-3^4
2^-(3^4)
2^(-(3^4))

2*-3/4
(2*-3)/4
(2*(-3))/4

Patched above (op +/-) logic to calc macro (previous post)
Also, unary +/- precedence placed below POW, above MUL/DIV, similar to Python/Lua

Before:
Code:
        ((+ -)  (if (null? (cdr e))
                    (list (car e) (build a term))  ; unary +/-
                    (list (car e) [rest e] (build a term))))

After:
Code:
        ((+ -)  (if (null? (cdr e))
                    (build [list (car e) a] term)  ; unary +/-
                    (if (memq (op (cdr e)) '(+ - * / ^))
                        (scan (cdr e) [list (car e) a] term)  ; op +/-
                        (list (car e) [rest e] (build a term)))))

Test with calc-expand macro (previous post)

scheme> (calc-expand '(2 ^ - 3 ^ 4)) ; op +/- tests
(^ 2 (- (^ 3 4)))
scheme> (calc-expand '(2 * - 3 / 4))
(/ (* 2 (- 3)) 4)

scheme> (calc-expand '(- 2 ^ 3 ^ 4)) ; unary +/- precedence below POW
(- (^ 2 (^ 3 4)))
scheme> (calc-expand '(- 2 * 3 / 4 )) ; unary +/- precedence above MUL/DIV
(/ (* (- 2) 3) 4)

And, for Mach number test. Spaces are needed to separate the tokens.

scheme> (sqrt (calc 5 *(((((1 + .2 *(350 / 661.5)^ 2)^ 3.5 - 1)* (1 - 6.875E-6 * 25500)^ - 5.2656)+ 1)^ .286 - 1)))
0.8357245351752515


For comparison, we figured precedence rules, then use rpn macro.

scheme> (rpn 350 661.5 / 2 ^ .2 * 1 + 3.5 ^ 1 -
                      1 6.875E-6 25500 * - -5.2656 ^ *
                      1 + .286 ^ 1 - 5 * sqrt @)
0.8357245351752515
Find all posts by this user
Quote this message in a reply
01-13-2023, 04:15 PM (This post was last modified: 01-13-2023 11:22 PM by carey.)
Post: #11
RE: prefix notation and () on newRPL project
(01-22-2019 07:32 PM)Thomas Klemm Wrote:  
(01-22-2019 03:06 PM)The Shadow Wrote:  List comprehension alone would make my day.

What's wrong with SEQ?

Python

>>> [ x**2 + 1 for x in range(1, 11, 2) ]

[2, 10, 26, 50, 82]

Algebraic

'SQ(X)+1'
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }

Or using RPL

« X SQ 1 + »
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }


Kind regards
Thomas

Thomas, thanks for this clear comparison!

Just out of curiosity to see what this SEQ example would look like using the HP50g's not-often used algebraic mode (in contrast to the algebraic example in the quoted post that uses an algebraic expression in rpn mode), the following worked:

Code:

SEQ('SQ(X) + 1', 'X', 1, 9, 2)

{ 2 10 26 50 82 }

Two things surprised me: (i) the algebraic mode parameter list for SEQ was intuitive so it was easy to guess right the first time, and although I'm reluctant to admit it, (ii) the function call looks nicer (to me) in algebraic mode than in RPL or Python.
Find all posts by this user
Quote this message in a reply
01-14-2023, 12:29 AM
Post: #12
RE: prefix notation and () on newRPL project
(01-13-2023 04:15 PM)carey Wrote:  
(01-22-2019 07:32 PM)Thomas Klemm Wrote:  What's wrong with SEQ?

Python

>>> [ x**2 + 1 for x in range(1, 11, 2) ]

[2, 10, 26, 50, 82]

Algebraic

'SQ(X)+1'
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }

Or using RPL

« X SQ 1 + »
'X'
1 9 2
SEQ

{ 2 10 26 50 82 }


Kind regards
Thomas

Thomas, thanks for this clear comparison!

Just out of curiosity to see what this SEQ example would look like using the HP50g's not-often used algebraic mode (in contrast to the algebraic example in the quoted post that uses an algebraic expression in rpn mode), the following worked:

Code:

SEQ('SQ(X) + 1', 'X', 1, 9, 2)

{ 2 10 26 50 82 }

Two things surprised me: (i) the algebraic mode parameter list for SEQ was intuitive so it was easy to guess right the first time, and although I'm reluctant to admit it, (ii) the function call looks nicer (to me) in algebraic mode than in RPL or Python.

I agree with you.
But fortunately, you can do the same thing in RPN mode. It's probably a little slower though.

Just surround the entire expression with the character #96.
I mean: << 96 CHR >> on your calculator or SHIFT↱ + CHARS ... then it's just the character before the lowercase "a" (unicode U+2035 on a computer).


<< ‵SEQ('SQ(X) + 1', 'X', 1, 9, 2)‵ >>

Bruno
Sanyo CZ-0124 ⋅ TI-57 ⋅ HP-15C ⋅ Canon X-07 + XP-140 Monitor Card ⋅ HP-41CX ⋅ HP-28S ⋅ HP-50G ⋅ HP-50G
Find all posts by this user
Quote this message in a reply
01-14-2023, 01:20 AM (This post was last modified: 01-14-2023 01:51 AM by carey.)
Post: #13
RE: prefix notation and () on newRPL project
(01-14-2023 12:29 AM)FLISZT Wrote:  I agree with you.
But fortunately, you can do the same thing in RPN mode. It's probably a little slower though.

Just surround the entire expression with the character #96.
I mean: << 96 CHR >> on your calculator or SHIFT↱ + CHARS ... then it's just the character before the lowercase "a" (unicode U+2035 on a computer).

<< ‵SEQ('SQ(X) + 1', 'X', 1, 9, 2)‵ >>

FLISZT,
That's so cool that entire algebraic mode function calls (and not just algebraic expressions) can be used in rpn mode!
Thank you,
Carey
Find all posts by this user
Quote this message in a reply
Post Reply 




User(s) browsing this thread: