• thanks - calculate pi fn. in elisp

    From Richard Smith@null@void.com to gnu.emacs.help on Tue Jul 9 19:48:48 2024
    From Newsgroup: gnu.emacs.help

    I know this is "help" and for emacs as a program,
    but for what it's worth,
    sort of as a thanks,
    this is what I as a welder and bit of an engineer managed to do
    readily on finding there is a formula for calculating the value of
    pi...

    You will know better ways, but this "scribble" was a nice bit of
    learning maths.

    Thanks everyone for help along the way

    Rich S

    --------------------------------

    (setq max-lisp-eval-depth (expt 2 20))

    (defun h-invnsq (this-n invnsq-sum)
    (if (zerop this-n)
    invnsq-sum
    (h-invnsq (1- this-n) (+ invnsq-sum (/ 1e0 (expt this-n 2))))))

    (defun pi-calc (n-to)
    "calculates Pi - arg integer is to how 1/n^2 integer to sum"
    (sqrt (* 6 (h-invnsq n-to 0))))

    (= (sqrt 6) (pi-calc 1)) ;; t
    (pi-calc 10) ;; 3.04936163598207
    (pi-calc 100) ;; 3.132076531809106
    (pi-calc 1000) ;; 3.140638056205993
    (pi-calc 10000) ;; 3.1414971639472093
    pi ;; 3.141592653589793
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Axel Reichert@mail@axel-reichert.de to gnu.emacs.help on Tue Jul 9 23:15:26 2024
    From Newsgroup: gnu.emacs.help

    Richard Smith <null@void.com> writes:

    You will know better ways, but this "scribble" was a nice bit of
    learning maths.

    I can imagine. Maths and Lisp are fascinating mind games. (:

    Some comments ...

    (setq max-lisp-eval-depth (expt 2 20))

    This sets some limit for stack recursion to some high value. My
    understanding is that this is not the number of recursive calls, but
    something different, which I could not find out. Pointers appreciated.

    (defun h-invnsq (this-n invnsq-sum)
    (if (zerop this-n)
    invnsq-sum
    (h-invnsq (1- this-n) (+ invnsq-sum (/ 1e0 (expt this-n 2))))))

    So here h-invnsq calls itself, with a different set of arguments, and
    this is the last action within this function, no matter the outcome of
    the "if". So h-invnsq is in "tail position". Other Lisps will transform
    a recursive call in tail position into a simple jump ("goto"). This is
    required behaviour for all Scheme implementations, but some Common Lisp implementations, e.g., SBCL, will do it as well.

    Unfortunately, Emacs Lisp does not do this TCO ("Tail Call
    Optimization"), with the exception of named-let. So I have taken to the
    habit of writing recursive stuff not only with tail calls (where
    possible, and this often mandates "helper functions", in your case
    "pi-calc", kind of initializing the recursive "workhorse"), but also
    with "named-let", to reap the benefits of TCO.

    Your example would then look like this:

    (defun pi-calc (n-to)
    "calculates Pi - arg integer is to how 1/n^2 integer to sum"
    (named-let h-invnsq ((this-n n-to)
    (invnsq-sum 0))
    (if (zerop this-n)
    (sqrt (* 6 invnsq-sum))
    (h-invnsq (1- this-n) (+ invnsq-sum (/ 1.0 (expt this-n 2)))))))

    So this-n gets bound to n-to and invnsq-sum to 0 (this is the "let"
    part; as you know, let is used for local bindings). However, this also
    names a function (this is the "named" part of "named-let") which can
    then be called in the body of the named-let (guaranteering TCO).

    (pi-calc 1000000)

    will then work fine without increasing "max-lisp-eval-depth".

    Now if you think this boilerplate code is annoying, then I am with
    you. Fortunately, since all Lisps are extremely malleable languages
    (think metal plasticity ...), automation of this is just a macro (not:
    keyboard macro) away:

    (defmacro defun-tco (name args body)
    "Wraps a 'named-let' around BODY to have a TCO of function NAME with ARGS."
    (declare (indent defun))
    (let ((bindings (gensym)))
    (setq bindings (mapcar #'(lambda (arg) (list arg arg)) args))
    `(defun ,name ,args
    (named-let ,name ,bindings
    ,body))))

    Ignore the "declare" and the "gensym" for now. With this, you can simply
    do

    (defun-tco pi-calc (this-n invnsq-sum)
    (if (zerop this-n)
    (sqrt (* 6 invnsq-sum))
    (pi-calc (1- this-n) (+ invnsq-sum (/ 1.0 (expt this-n 2))))))

    and then call

    (pi-calc 1000000 0)

    without exploding the stack. There is room for improvement (neither
    support for good-practice docstrings nor local variables eliminating the
    need to give two arguments to "pi-calc"), but I am sure the Emacs Lisp
    gurus here could help with this. It was meant as a brief sketch. For a discussion on optional docstrings in macros (Common Lisp, not Emacs
    Lisp), see

    https://stackoverflow.com/questions/66364347/correct-way-to-incorporate-a-docstring-in-a-def-macro

    Best regards

    Axel
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Richard Smith@null@void.com to gnu.emacs.help on Wed Jul 10 06:28:30 2024
    From Newsgroup: gnu.emacs.help

    Thanks Axel
    Regarding the second approach;
    I have read
    * Paul Graham's "On Lisp"
    * Siebel's "Practical Common Lisp"
    so have seen things like "gensym" and why has to be so.

    Reality is, with very not-advanced lisp basics I seem to do well.

    In my world of melting and shaping metal, there seems to be something
    good about the working environment of equations and explanations in one document. It seems to facilitate a person developing their thoughts.

    This seems to be the biggest issue - what the environment makes readily
    and enjoyably achievable.

    In recent years

    * every beam calculation I want to do
    (Euler-Bernoulli beam - derived 1750's; applied eg. Eiffel 1880's-ish)
    which I do use frequently in my welding and engineering work

    * a 1-D computer-numerical solution for heat-flow which proves a useful
    "nutcracker" for considering what's going on where the issue is
    conductive heat transfer

    * in mineral processing (considering processing metal ores - tin,
    copper, etc) I can run through calculations actually feeling very
    happy

    Mineral processing was last new application, a couple of months ago.
    I'm surrounded by abandoned mines here - some of the iconic images of
    Cornwall. With for me the crucial thing being that tin-mining is
    restarting here. There's also lithium here - efforts to work that.
    None of these metals "self-extract" from the "run-of-mine" ore.
    Hence mineral processing as an expertise.

    Thing is, those happily-done calculations enabled me to see the twists-and-turns the author, with decades of experience of mineral
    processing, could throw at you to get you to think through the issue.
    Layers deeper than the text alone could take you.

    I had to visualise the minerals and mineral streams, then draw sketches
    which were my "model", then derive the maths (concurred with the
    author's equations) - then write the elisp functions and get the
    answers.
    No immediate jobs so having to get back to welding - but could return to
    remind of the logical path which worked for me, in those files, whenever.

    These were all "trivial" algebraic expressions, in computing terms.

    I appreciate you showing me
    where I could take my computing
    if that juncture came.

    Regards,
    Rich Smith
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Richard Smith@null@void.com to gnu.emacs.help on Wed Jul 10 06:36:56 2024
    From Newsgroup: gnu.emacs.help

    Axel - I know that elisp doesn't optimise if an expressed recursive
    function is tail-recursive.
    A practical work-around is an alterative approach using the looping
    built-in's like "dotimes" (?) - where a recursive approach would have minimalistic beauty.
    Regards, Rich S
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Richard Smith@null@void.com to gnu.emacs.help on Wed Jul 10 06:59:02 2024
    From Newsgroup: gnu.emacs.help

    Axel, all - for what it's worth...
    It's often much quicker to get a solution than to explain that solution.
    It can take minutes or something like an hour and a half to know
    something vitally important.
    The feeling is it's very rewarding.
    But how you explain that to the rest of the world living in a world
    structured around word-processors, spreadsheets, etc...
    That is the hard-work.

    With structures you can test-load while it is centimetres above the
    ground - well-known acceptable method. IF you'd got it wrong and the
    structure failed that would have no consequence as it would simply sag
    those centimetres to the ground. That test done at some
    margin-of-safety overload, you can use it at any height, etc.

    So you can happily sketch your solutions - and you know there is a
    long-stop which will catch any errors.
    The efficiency is knowing exactly what that test-load is which will have
    the structure accepted on the basis of empirical test.

    Hopefully I am giving insight into why what you specialise in is
    appreciated in my world.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Richard Smith@null@void.com to gnu.emacs.help on Wed Jul 10 09:18:19 2024
    From Newsgroup: gnu.emacs.help

    Hi again Axel
    I have made structures out of offcuts of metal and tested them to
    destruction.
    For both (Euler-Bernoulli) beam calculations and Finite Element Analysis modelling the prediction exactly matches what is observed.
    Even for Finite Element Analysis modelling you often have calculations
    to do working out or preparing the overall design.
    Again - it's about this working environment in emacs. Including
    functions

    Example, for what it's worth

    standard Rectangular Hollow Section beam 200x100x8mm, 3m long

    (beam-rhs-simple-fmax-y-bb-pp 200e-3 100e-3 8e-3 3 355e6 210e9)
    "H=0.2 W=0.1 wthk=0.008 len=3 sigma=3.550000e+08 E=2.100000e+11 : I=2.306014e-05 Z_el=2.306014e-04 M_max=81863.49226666673
    F=109151.3230222223 Defln=0.012678571428571428"
    That's pretty-printed so you can see all is well.
    Mathematically useless though.

    (beam-fmax-rhs-simple-cload-bb 200e-3 100e-3 8e-3 3 355e6) ;; 109151.3230222223 Correct, but that's in Newtons - hard to visualise in a practical sense

    (/
    (beam-fmax-rhs-simple-cload-bb 200e-3 100e-3 8e-3 3 355e6)
    9.81 ;; Newtons per kg in Earth's gravity
    1e3 ;; 1000kg per Tonne
    ) ;; 11.126536495639378
    Tonnes

    It'll take 11 Tonnes load in gravity before bending.


    The point - the path to the answer is part of the record, as well as the
    answer itself.

    And this is what makes the emacs environment so useful to me for what I
    do.

    I've preceded C-x C-e by C-u to put the answer into the buffer
    C-u C-x C-e
    Familiar day-to-day usage.

    Thanks for showing me the more advanced programming posibilities.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From steve g@sgonedes1977@gmail.com to gnu.emacs.help on Sat Aug 10 15:56:32 2024
    From Newsgroup: gnu.emacs.help

    Richard Smith <null@void.com> writes:

    Thanks Axel
    Regarding the second approach;
    I have read
    * Paul Graham's "On Lisp"
    * Siebel's "Practical Common Lisp"
    so have seen things like "gensym" and why has to be so.

    Reality is, with very not-advanced lisp basics I seem to do well.

    yeah me too :)


    In my world of melting and shaping metal, there seems to be something
    good about the working environment of equations and explanations in one document. It seems to facilitate a person developing their thoughts.

    I so agree! I thread and weld pipe for fire suppression systems. we use hydraulic calculations; if you can do this you are golden...


    This seems to be the biggest issue - what the environment makes readily
    and enjoyably achievable.

    In recent years

    * every beam calculation I want to do
    (Euler-Bernoulli beam - derived 1750's; applied eg. Eiffel 1880's-ish)
    which I do use frequently in my welding and engineering work



    * a 1-D computer-numerical solution for heat-flow which proves a useful
    "nutcracker" for considering what's going on where the issue is
    conductive heat transfer


    Oh yeah! another heat transfer variable :)

    * in mineral processing (considering processing metal ores - tin,
    copper, etc) I can run through calculations actually feeling very
    happy

    Mineral processing was last new application, a couple of months ago.
    I'm surrounded by abandoned mines here - some of the iconic images of Cornwall. With for me the crucial thing being that tin-mining is
    restarting here. There's also lithium here - efforts to work that.
    None of these metals "self-extract" from the "run-of-mine" ore.
    Hence mineral processing as an expertise.

    Thing is, those happily-done calculations enabled me to see the twists-and-turns the author, with decades of experience of mineral processing, could throw at you to get you to think through the issue.
    Layers deeper than the text alone could take you.



    I had to visualise the minerals and mineral streams, then draw sketches
    which were my "model",


    my boss still uses graphing paper and HGC3 (hydrolic calculator v3).

    then derive the maths (concurred with the
    author's equations) - then write the elisp functions and get the
    answers.

    No immediate jobs so having to get back to welding - but could return to remind of the logical path which worked for me, in those files, whenever.

    These were all "trivial" algebraic expressions, in computing terms.

    I appreciate you showing me
    where I could take my computing
    if that juncture came.

    Regards,
    Rich Smith



    Thank you!
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From steve g@sgonedes1977@gmail.com to gnu.emacs.help on Sat Aug 10 16:22:54 2024
    From Newsgroup: gnu.emacs.help

    Richard Smith <null@void.com> writes:

    Axel - I know that elisp doesn't optimise if an expressed recursive
    function is tail-recursive.

    actually the byte-compiler does do tail recursive optimizations.

    A practical work-around is an alterative approach using the looping built-in's like "dotimes" (?) - where a recursive approach would have minimalistic beauty.
    Regards, Rich S


    check the elisp manual. it shows how to implement true tail recursion in
    emacs.


    (defun elisp-sum (args)
    (elisp-sum-aux args 0))

    (defun elisp-sum-aux (args res)
    (if (null args)
    res
    (elisp-sum-aux (cdr args) (+ (car args) res))))


    you can byte compile it. very simple.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From steve g@sgonedes1977@gmail.com to gnu.emacs.help on Sat Aug 10 16:26:13 2024
    From Newsgroup: gnu.emacs.help

    Richard Smith <null@void.com> writes:


    It'll take 11 Tonnes load in gravity before bending.


    what guage steel you using at what incline? :)

    The point - the path to the answer is part of the record, as well as the answer itself.

    And this is what makes the emacs environment so useful to me for what I
    do.

    I've preceded C-x C-e by C-u to put the answer into the buffer
    C-u C-x C-e
    Familiar day-to-day usage.

    Thanks for showing me the more advanced programming posibilities.
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Axel Reichert@mail@axel-reichert.de to gnu.emacs.help on Sat Aug 10 23:15:54 2024
    From Newsgroup: gnu.emacs.help

    steve g <sgonedes1977@gmail.com> writes:

    check the elisp manual. it shows how to implement true tail recursion
    in emacs.

    (defun elisp-sum (args)
    (elisp-sum-aux args 0))

    (defun elisp-sum-aux (args res)
    (if (null args)
    res
    (elisp-sum-aux (cdr args) (+ (car args) res))))

    you can byte compile it. very simple.

    ... and then easily find out that it will enter the debugger for large
    ARGS, say

    (defun elisp-sum (number-sequence 1 10000000))

    But with

    (defmacro defun-tco (name args body)
    "Wraps a 'named-let' around BODY to have a TCO of function NAME with ARGS."
    (declare (indent defun))
    (let ((bindings (gensym)))
    (setq bindings (mapcar #'(lambda (arg) (list arg arg)) args))
    `(defun ,name ,args
    (named-let ,name ,bindings
    ,body))))

    and

    (defun-tco elisp-sum-aux (args res)
    (if (null args)
    res
    (elisp-sum-aux (cdr args) (+ (car args) res))))

    a

    (defun elisp-sum (number-sequence 1 10000000))

    will do.

    Best regards

    Axel
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Richard Smith@null@void.com to gnu.emacs.help on Sat Aug 10 22:28:18 2024
    From Newsgroup: gnu.emacs.help

    steve g <sgonedes1977@gmail.com> writes:

    Richard Smith <null@void.com> writes:

    Thanks Axel
    Regarding the second approach;
    I have read
    * Paul Graham's "On Lisp"
    * Siebel's "Practical Common Lisp"
    so have seen things like "gensym" and why has to be so.

    Reality is, with very not-advanced lisp basics I seem to do well.

    yeah me too :)


    In my world of melting and shaping metal, there seems to be something
    good about the working environment of equations and explanations in one
    document. It seems to facilitate a person developing their thoughts.

    I so agree! I thread and weld pipe for fire suppression systems. we use hydraulic calculations; if you can do this you are golden...


    This seems to be the biggest issue - what the environment makes readily
    and enjoyably achievable.

    In recent years

    * every beam calculation I want to do
    (Euler-Bernoulli beam - derived 1750's; applied eg. Eiffel 1880's-ish)
    which I do use frequently in my welding and engineering work



    * a 1-D computer-numerical solution for heat-flow which proves a useful
    "nutcracker" for considering what's going on where the issue is
    conductive heat transfer


    Oh yeah! another heat transfer variable :)

    * in mineral processing (considering processing metal ores - tin,
    copper, etc) I can run through calculations actually feeling very
    happy

    Mineral processing was last new application, a couple of months ago.
    I'm surrounded by abandoned mines here - some of the iconic images of
    Cornwall. With for me the crucial thing being that tin-mining is
    restarting here. There's also lithium here - efforts to work that.
    None of these metals "self-extract" from the "run-of-mine" ore.
    Hence mineral processing as an expertise.

    Thing is, those happily-done calculations enabled me to see the
    twists-and-turns the author, with decades of experience of mineral
    processing, could throw at you to get you to think through the issue.
    Layers deeper than the text alone could take you.



    I had to visualise the minerals and mineral streams, then draw sketches
    which were my "model",


    my boss still uses graphing paper and HGC3 (hydrolic calculator v3).

    then derive the maths (concurred with the
    author's equations) - then write the elisp functions and get the
    answers.

    No immediate jobs so having to get back to welding - but could return to
    remind of the logical path which worked for me, in those files, whenever.

    These were all "trivial" algebraic expressions, in computing terms.

    I appreciate you showing me
    where I could take my computing
    if that juncture came.

    Regards,
    Rich Smith



    Thank you!

    Hi there!
    I can hardly believe it that there is someone else out there who does metal-bashing and uses emacs as a working environment.

    "I so agree! I thread and weld pipe for fire suppression systems. we use
    hydraulic calculations; if you can do this you are golden..."

    I have a website
    weldsmith.co.uk
    Lots of technical things.

    If you want to get in contact there is a contact form.

    Since I wrote that post I have been volunteering at a mine museum making
    a replica of the "cage" of the haulage shaft - which for me is getting
    my hand back in in welding.

    Regards
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Richard Smith@null@void.com to gnu.emacs.help on Sat Aug 10 22:51:30 2024
    From Newsgroup: gnu.emacs.help

    steve g <sgonedes1977@gmail.com> writes:

    Richard Smith <null@void.com> writes:


    It'll take 11 Tonnes load in gravity before bending.


    what guage steel you using at what incline? :)

    The point - the path to the answer is part of the record, as well as the
    answer itself.

    And this is what makes the emacs environment so useful to me for what I
    do.

    I've preceded C-x C-e by C-u to put the answer into the buffer
    C-u C-x C-e
    Familiar day-to-day usage.

    Thanks for showing me the more advanced programming posibilities.

    I put the dimensions in the familiar way we express it
    "Rectangular Hollow Section beam 200x100x8mm, 3m long"
    So that's 200mm tall, 100mm wide and 8mm wall thickness.
    3metres long, obviously

    You could check my values against beam tables - eg. in "The Blue Book" https://www.steelforlifebluebook.co.uk/hfrhs/ec3-ukna/section-properties-dimensions-properties
    "200x100x8" is a commercial section.

    I see what you are asking about "incline".
    The implicit assumption for a "simple beam" - it sits on an immovable
    support at each end, otherwise span free space and is loaded in the
    middle - is that the beam is horizontal and the load is vertical, as
    would be the case for a mass in gravity bearing upon the beam
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From steve g@sgonedes1977@gmail.com to gnu.emacs.help on Sun Aug 11 14:56:19 2024
    From Newsgroup: gnu.emacs.help

    Axel Reichert <mail@axel-reichert.de> writes:

    steve g <sgonedes1977@gmail.com> writes:

    < > check the elisp manual. it shows how to implement true tail recursion
    < > in emacs.
    < >
    < > (defun elisp-sum (args)
    < > (elisp-sum-aux args 0))
    < >
    < > (defun elisp-sum-aux (args res)
    < > (if (null args)
    < > res
    < > (elisp-sum-aux (cdr args) (+ (car args) res))))
    < >
    < > you can byte compile it. very simple.


    ... and then easily find out that it will enter the debugger for large
    ARGS, say

    (defun elisp-sum (number-sequence 1 10000000))


    I was thinking more of the concept; no more than that.

    (elisp-sum (number-sequence 1 107)).. there is a limit to list length; that is usually time.


    But with

    (defmacro defun-tco (name args body)
    "Wraps a 'named-let' around BODY to have a TCO of function NAME with ARGS."
    (declare (indent defun))
    (let ((bindings (gensym)))
    (setq bindings (mapcar #'(lambda (arg) (list arg arg)) args))
    `(defun ,name ,args
    (named-let ,name ,bindings
    ,body))))



    yes, yes; lambda bindings will certainly work better. even in common
    lisp there is a limit to the length of &rest arguments and can take some
    time to process large lists; sometimes crashing the stack.

    If you are interested in non-deterministic software then screamer is
    fairly cool.

    and

    (defun-tco elisp-sum-aux (args res)
    (if (null args)
    res
    (elisp-sum-aux (cdr args) (+ (car args) res))))

    a



    (defun elisp-sum (number-sequence 1 10000000))

    will do.

    this is probably the best option - just mentioning that recursion does
    work fairly well in emacs lisp...



    Best regards

    same


    Axel
    --- Synchronet 3.21d-Linux NewsLink 1.2
  • From Richard Smith@null@void.com to gnu.emacs.help on Tue Apr 8 10:26:56 2025
    From Newsgroup: gnu.emacs.help

    Axel Reichert <mail@axel-reichert.de> writes:

    steve g <sgonedes1977@gmail.com> writes:

    check the elisp manual. it shows how to implement true tail recursion
    in emacs.

    (defun elisp-sum (args)
    (elisp-sum-aux args 0))

    (defun elisp-sum-aux (args res)
    (if (null args)
    res
    (elisp-sum-aux (cdr args) (+ (car args) res))))

    you can byte compile it. very simple.

    ... and then easily find out that it will enter the debugger for large
    ARGS, say

    (defun elisp-sum (number-sequence 1 10000000))

    But with

    (defmacro defun-tco (name args body)
    "Wraps a 'named-let' around BODY to have a TCO of function NAME with ARGS."
    (declare (indent defun))
    (let ((bindings (gensym)))
    (setq bindings (mapcar #'(lambda (arg) (list arg arg)) args))
    `(defun ,name ,args
    (named-let ,name ,bindings
    ,body))))

    and

    (defun-tco elisp-sum-aux (args res)
    (if (null args)
    res
    (elisp-sum-aux (cdr args) (+ (car args) res))))

    a

    (defun elisp-sum (number-sequence 1 10000000))

    will do.

    Best regards

    Axel

    Hi there - several months later...
    Axel, Steve in particular with your responses.
    I got a job as a welder - my first local job on moving here - and had a
    "winter campaign". Was exhausting getting back into it.
    Strengthening-up my torso to do weld-runs quickly And accurately And
    able to overcome perturbations like the "hose" from machine to MIG
    gun/torch snagging and dragging while continuing welding at constant
    rate.
    Then mental tiredness of getting to grips with the various products and
    what they needed.
    Just had a chance to look through those posts again.
    Thanks so much.
    Best wishes, Rich S
    --- Synchronet 3.21d-Linux NewsLink 1.2