Den ons. 20. jan. 2021 kl. 08.43 skrev Stuart Hungerford <
stuart.hungerf...@gmail.com>:

> On Wednesday, 20 January 2021 at 12:34:59 UTC+11 Robby Findler wrote:
>
> I'm no expert on algebras, but I think the way to work on this is not to
>> think "what Racket constructs are close that I might coopt to express what
>> I want?" but instead to think "what do I want my programs to look like" and
>> then design the language from there, reusing libraries as they seem helpful
>> or designing new ones that do what you want. Racket's
>> language-implementation facilities are pretty powerful (of course, if there
>> is nothing like what you end up needing, there will still be actual
>> programming to do ;).
>>
>
> Thanks Robby -- that's a very interesting way to look at library design
> that seems to make particular sense in the Racket environment.
>

An example of such an approach is racket-cas, a simple general purpose cas,
which
represents expressions as s-expression.

The polynomial 4x^2 + 3 is represented as '(+ 3 (* 4 (expt x 2)))
internally.

The expressions are manipulated through pattern matching. Instead of
using the standard `match`, I wanted my own version `math-match`.
The idea is that `math-match` introduces the following conventions in
patterns:

  prefix  x y z  will match symbols only
  prefix  r s     will match numbers only (not bigfloats)
  prefix  p q    wil match exact naturals only
  prefix 𝛼 𝛽     will match exact numbers
  prefix bool   will match booleans only

  suffix .0      will match inexact numbers only
  suffix .bf     will match bigfloats only

As an example, here is the part that implements the symbolic natural
logarithm
(the assumption is that the argument u is in normalized form):

(define (Ln: u)
  (math-match u
    [1  0]                                         ; ln(1)=0
    [r. #:when (%positive? r.)  (%ln r.)]          ; here %ln is an ln that
handles both reals and bigfloats
    [@e  1]                                        ; @e is the syntax
matching Euler's e,  ln(e)=1
    [(Complex a b) #:when (not (equal? 0 b))       ; all complex numbers
are handled here
                   (⊕ (Ln (Sqrt (⊕ (Sqr a) (Sqr b))))
                      (⊗ @i (Angle (Complex a b))))]
    [(Expt @e v) v]                                ; ln(e^v) = v
    [(Expt u α) #:when (= (%numerator (abs α)) 1)  ; ln( u^(/n) ) = 1/n
ln(u)
                (⊗ α (Ln: u))]
    [(⊗ u v)  (⊕ (Ln: u) (Ln: v))]                 ; ln(u*v) = ln(u) + ln(v)
    [_ `(ln ,u)]))                                 ; keep as is

Note that the match pattern (⊗ u v) matches not only products of two
factors, but general products.
Matching (⊗ u v)  agains (* 2 x y z) will bind u to 2 and v to (* x y z).
This convention turned out to be very convenient.

I am happy about many aspects of racket-cas, but I wish I used structs to
represent the expressions.
Thanks to the custom matcher, it ought to be possible to change the
underlying representation
and still reuse most parts of the code. That's a future project.


Back to your project - what is the goal of the project?
Making something like GAP perhaps?
Do you want your users to supply types - or do you want to go a more
dynamic route?

/Jens Axel

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CABefVgwbdetq%2BWBa4h6MPLt1XxnhFQSiOACPC46xsx6cVA9imQ%40mail.gmail.com.

Reply via email to