2

Is there a way to get elisp to automatically treat all numeric variables as floating points without having to repeatedly use the float function?

For example to a division function that outputs the "true" quotient is

(defun divide ( x y )
  (/ (float x) y))

But I'd rather not have so many float functions floating around (even if, given the name, that's a part of the function's essence ;) ).

  • 1
    You might want to clarify why you have "many float functions": I don't see this problem occurring often within "typical" Elisp code and I can't think of a general way to satisfy your request (except in ways which break lots of existing code), so your specific circumstances are probably necessary to be able to come up with a good answer. – Stefan Oct 23 at 19:22
  • I guess it must be typical practice to just make sure the numbers passed at the beginning of a complicated procedure are floats? So in my example I'd remove the float function but just be sure to pass, say, 2.0 instead of 2 as an argument to the function divide. – Quinn Culver Oct 23 at 20:13
  • 1
    It's only "typical practice", except when you intend to use floating point computations (i.e. rarely). In Elisp, integers and floats are two distinct types that behave differently in various circumstances, and we write the code with this premise in mind (like in many (most?) other programming languages and unlike in JS). – Stefan Oct 23 at 20:29
  • Thanks @Stefan. I'm gonna delete this question unless you think I shouldn't. – Quinn Culver Oct 23 at 20:42
  • 1
    To elaborate slightly, floating point numbers are not a super-set of integers. FP is imprecise by definition; there are numbers (including integers) in the FP range which cannot be represented. As Stefan says, the two things can behave differently, so if you don't require FP then using it is probably a mistake. – phils Oct 23 at 20:50
3

The following Elisp code demonstrates how you can define your own wrapper macro with-float/ that treats all explicit occurences of / in its body as division of floats.

Division operators that are used in functions called within the body of with-float/ are the original operators.

(defmacro with-float/ (&rest body)
  "Evaluate BODY with / for float arguments."
  (declare (debug body))
  `(cl-macrolet ((/ (x &rest args)
           `(,(symbol-function #'/) (float ,x) ,@args)))
     ,@body))

(defun using-the-old-/ (x y)
  (/ x y))

(defun using-float/ (x y)
  (with-float/
   (/ x y)))

(append
 (list (using-float/ 1 2))
 (with-float/
  (list
   (/ 1 2)
   (using-the-old-/ 1 2))))

The last form (i.e., the append) returns (0.5 0.5 0).

3

For numeric calculation there is a parallel universe within Elisp: Calc.

The division operator / within defmath works with the floating numbers of Calc.

Nevertheless, the interface of Calc with the Elisp world is a bit complicated. You need to convert floating point numbers to strings. These strings are then converted by Calc to their Calc-internal representation.

This is not a problem if you stay in the defmath "environment" for your complicated maths calculations.

(defmath mydiv (x y)
  "Divide x by y within `defmath'."
  (/ x y))

(calc-eval "mydiv(1,2)")

The calc-eval form returns 0.5.

You can convert a float number X to Calc format by (math-read-number (number-to-string X)) and a Calc float Y to an Emacs float by (read (math-format-value Y)).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.