Code Monkey home page Code Monkey logo

infix's Introduction

Infix

Build Status Coverage Status Dependencies Status Downloads Clojars Project Maintenance

A small Clojure library for representing LISP expressions in infix rather than prefix notation... sometimes it's easier to rely on operator precedence, instead of LISP's insistence on parentheses – this is especially true when dealing with mathematical equations.

An infix expression is rewritten as a prefix expression using a macro. The operator precedence rules were taken from Wikipedia. Any function calls should generally have parens around the arguments and not the function name. Aliased unary operators (as outlined below) do not need parens however.

Pre-requisites

You will need Leiningen 2.6.1 or above installed.

Building

To build and install the library locally, run:

$ cd infix
$ lein test
$ lein install

Including in your project

There is a version hosted at Clojars. For leiningen include a dependency:

[rm-hull/infix "0.4.0"]

For maven-based projects, add the following to your pom.xml:

<dependency>
  <groupId>rm-hull</groupId>
  <artifactId>infix</artifactId>
  <version>0.4.0</version>
</dependency>

API Documentation

See www.destructuring-bind.org/infix for API details.

Basic Usage

(use 'infix.macros)
; => nil

(infix 3 + 5 * 8)
; => 43

(infix (3 + 5) * 8)
; => 64

You can also use $= as a short alias for infix, like this for example:

(refer 'infix.macros :only '[$=])
; => nil

($= 3 + 5 * 8)
; => 43

All of the examples below should work if you replace infix by $=.

Some Math functions have been aliased (see below for full list), so nullary and unary-argument functions can be used as follows:

(infix √(5 * 5))
; => 5.0

(infix121)
; => 11.0

(infix 2 ** 6)
; => 64.0

(def t 0.324)
; => #'user/t

(infix sin(2 * t) + 3 * cos(4 * t))
; => 1.4176457261295824

(infix rand() * 3)
; => 0.5544039436207262

Debugging

It may be the case that you encounter some esoteric errors emitted from the library trying to rephrase expressions from infix to prefix. Use macroexpand-1 to show how the expression would be rewritten, and if necessary file an issue.

(macroexpand-1 '(infix sin(2 * t) + 3 * cos(4 * t))
; => (+ (Math/sin (* 2 t)) (* 3 (Math/cos (* 4 t))))

Usage in ClojureScript projects

The infix macro may be used to expand infix expressions in ClojureScript code by adding the require-macros directive to a namespace, for example:

(ns my.clojurescript.project
  (:require-macros [infix.macros :refer [infix]]))

Evaluating infix expressions dynamically from a string

A function can created at runtime from an expression held in a string as follows. When building from a string, a number of binding arguments should be supplied, corresponding to any variable that may be used in the string expression, for example:

(def hypot
  (from-string [x y]
    "sqrt(x**2 + y**2)"))
; => #'user/hypot

(hypot 3 4)
; => 5

(meta hypot)
; => {:params [:x :y], :doc "sqrt(x**2 + y**2)"}

from-string is deliberately designed to look like an anonymous function definition, mainly because that is more-or-less what it is. In effect, this is equivalent to creating the following function:

(def hypot
  (fn [x y]
    (infix sqrt(x ** 2 + y ** 2))))

However, it does so without recourse to eval and read-string - instead it is built using our old friend, the monadic parser-combinator, with an EBNF grammar (implementing the infix notation) and a restricted base environment of math functions, as outlined in the next section.

The base-env may be extended with any number of key/value pairs (where keys are keywords) and values may either be values or functions, to provide the required extensions. When referenced in the string it is not necessary to prefix the name with a colon.

(def extended-env
  (merge
    base-env
    {:rad (fn [deg] (infix deg * π / 180))
     :hypot hypot}))
; => user/extended-env

(def rhs-triangle-height
  (from-string [base angle]
    extended-env
    "tan(rad(angle)) * base"))
; => user/rhs-triangle-height

(rhs-triangle-height 10 45)
; => 9.9999999999998

Obviously, a function that was previously created from a string can also referenced in a subsequent function definition:

(def hypot2
  (from-string [x y]
    extended-env
    "hypot(x, y) ** 2"))
; => user/hypot2

(hypot2 5 12)
; => 169.0

Aliased Operators & Functions

Alias Operator Alias Operator Alias Operator
&& and abs Math/abs sin Math/sin
|| or signum Math/signum cos Math/cos
== = ** Math/pow tan Math/tan
> > < <
>= >= <= <=
!= not= exp Math/exp asin Math/asin
% mod log Math/log acos Math/acos
<< bit-shift-left e Math/E atan Math/atan
>> bit-shift-right π Math/PI sinh Math/sinh
! not sqrt Math/sqrt cosh Math/cosh
& bit-and Math/sqrt tanh Math/tanh
| bit-or root b √ a sec Secant
φ Golden ratio csc Cosecant
gcd Greatest common divisor fact Factorial cot Cotangent
lcm Least common multiple Sum asec Arcsecant
rand Random number generator Product acsc Arccosecant
randInt Random int between 0..n acot Arccotangent

EBNF Grammar Rules

The from-string macro parses infix expressions based on the EBNF grammar rules as follows:

  • <expression> ::= term { addop term }.

  • <term> ::= factor { mulop factor }.

  • <factor> ::= base { expop base }.

  • <base> ::= "(" expression ")" | boolean | number | var | function.

  • <addop> ::= "+" | "-" | "|" | "&" | "||" | "&&".

  • <mulop> ::= "*" | "/" | "÷" | "%" | ">>" | ">>>" | "<<".

  • <expop> ::= "**" .

  • <function> ::= envref expression | envref "(" <empty> | expression { "," expression } ")".

  • <ternary> ::= "(" expression ")" "?" expression ":" expression.

  • <envref> ::= letter | "" { letter | digit | "_" | "." }._

  • <var> ::= envref.

  • <boolean> ::= "true" | "false"

  • <number> ::= integer | decimal | rational | binary | hex

  • <binary> :: = [ "-" ] "0b" { "0" | "1" }.

  • <hex> :: = [ "-" ] "0x" | "#" { "0" | ... | "9" | "A" | ... | "F" | "a" | ... | "f" }.

  • <integer> :: = [ "-" ] digits.

  • <decimal> :: = [ "-" ] digits "." digits.

  • <rational> :: = integer "/" digits.

  • <letter> ::= "A" | "B" | ... | "Z" | "a" | "b" | ... | "z".

  • <digit> ::= "0" | "1" | ... | "8" | "9".

  • <digits> ::= digit { digit }.

References

License

The MIT License (MIT)

Copyright (c) 2016 Richard Hull

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

infix's People

Contributors

bpindelski avatar dsbw avatar mars0i avatar rm-hull avatar shevchuk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

infix's Issues

How to call parameter-less functions?

The following fails:

(defn
  circle-rectangle-intersects?
  [circle rect-x1 rect-x2 rect-y1 rect-y2]
  (let
    [circle-x (:x circle)
     circle-y (:y circle)
     circle-r (:r circle)
     rect-width (infix rect-x2 - rect-x1)
     rect-height (infix rect-y2 - rect-y1)
     circle-distance-x (infix abs(circle-x - rect-x1))
     circle-distance-y (infix abs(circle-y - rect-y1))
     check1 #(infix circle-distance-x > (rect-width / 2 + circle-r))
     check2 #(infix circle-distance-y > (rect-height / 2 + circle-r))
     check3 #(infix circle-distance-x <= (rect-width / 2))
     check4 #(infix circle-distance-y <= (rect-width / 2))
     corner-distance-sq #(infix (circle-distance-x - rect.width / 2) ** 2 + (circle-distance-y - rect-height / 2) ** 2)
     check5 #(infix corner-distance-sq() <= circle-r ** 2)
     ]
    (if
     (infix check1() || check2())
     false
     (if
       (infix check3() || check4())
       true
       (check5)))))
Compile Warning
Wrong number of args (1) passed to corner-distance-sq at line 274 /home/emh/github/rts/src.client/game/client/selection.cljs
Wrong number of args (1) passed to check1 at line 277 /home/emh/github/rts/src.client/game/client/selection.cljs
Wrong number of args (1) passed to check1 at line 277 /home/emh/github/rts/src.client/game/client/selection.cljs
Wrong number of args (1) passed to check2 at line 277 /home/emh/github/rts/src.client/game/client/selection.cljs
Wrong number of args (1) passed to check3 at line 280 /home/emh/github/rts/src.client/game/client/selection.cljs
Wrong number of args (1) passed to check3 at line 280 /home/emh/github/rts/src.client/game/client/selection.cljs
Wrong number of args (1) passed to check4 at line 280 /home/emh/github/rts/src.client/game/client/selection.cljs

Short alias for infix?

I think I'm about as comfortable with Lisp syntax as you could be, but reading complicated arithmetic expressions with prefix notation is still not as easy as reading infix notation. Thanks very much for infix.

I think you've probably chosen to intentionally avoid specifying a short alias for infix (or have I missed it?), e.g. like Incanter's $= infix operator (whose functionality is different from infixs). It's easy enough to define my own, e.g.:

(defmacro $ [& expr] `(infix ~@expr))

but there's some value to readability by others in specifying a standard alias, rather than every infix user defining their own variant. (Perhaps this is irrelevant if infix is not popular, though.)

My own preference is to use a single-character alias, but there are only a few suitable ones. $, ?, and | seem best. A capital I is another option. The single-character macro can be refered optionally, so it needn't clobber a user's own definition, although I think single-character function and macro definitions are uncommon.

Of course in itself infix is clearer than some arbitrary character since its name suggests its purpose, but I think this is a context where a single-character definition is sometimes useful. If I have a single long arithmetic calculation, it's no problem to add infix at the beginning of it. However, if I have a long series of related mathematical let bindings, adding infix each time isn't worth the trouble. Here's an example from some of my own code:

;; Original prefix version:
(defn next-p
  [wa1 wa2 wb1 wb2 p1 q1 p]
  (let [q  (- 1 p)
        p2 (- 1 p1)
        q2 (- 1 q1)
        abs-p' (* p (+ (* wa1 p1) (* wa2 p2)))
        abs-q' (* q (+ (* wa1 q1) (* wa2 q2)))]
    (/ abs-p'(+ abs-p' abs-q'))))

;; Version with the infix macro
(defn next-p
  [wa1 wa2 wb1 wb2 p1 q1 p]
  (let [q  (infix 1 - p)
        p2 (infix 1 - p1)
        q2 (infix 1 - q1)
        abs-p' (infix p * (wa1 * p1 + wa2 * p2))
        abs-q' (infix q * (wa1 * q1 + wa2 * q2))]
    (infix abs-p' / (abs-p' + abs-q'))))

;; Version with alias macro
(defn next-p
  [wa1 wa2 wb1 wb2 p1 q1 p]
  (let [q  ($ 1 - p)   ; The first three bindings were already readable with prefix notation,
        p2 ($ 1 - p1)  ; but switching back and forth from prefix to infix arithmetic in the
        q2 ($ 1 - q1)  ; same defn seems distracting.
        abs-p' ($ p * (wa1 * p1 + wa2 * p2))
        abs-q' ($ q * (wa1 * q1 + wa2 * q2))]
    ($ abs-p' / (abs-p' + abs-q'))))

(The short variable names aren't obfuscatory; they're based on common conventions in population genetics.)

IllegalStateException when calling the function returned from 'from-string', if the first argument of 'from-string' inside the vector is a non literal'

I am trying to convert from infix to prefix at runtime. My problem is that when i programmatically put parameters to 'from-string' i get the exception (IllegalStateException x is not bound in environment). The error points at line: 70 in grammar.clj. Here's what i do

The following macro is used to overcome that 'from-string' accepts only vector literals as first parameter

(defmacro from-string-helper [params expression]
    `(from-string [~@params] ~expression))

Writing on the repl

(def a (from-string-helper ["x" "y"] "x + y"))
(a 1 1)

prints 2 and it's all good. But if i call it from inside another function

(defn create-function [params expression]
    (from-string-helper (seq params) expression)) ;seq, otherwise the compiler doesn't know what to expect in 'from-string-helper' and will complain
(def b (create-function ["x" "y"] "x + y"))
(b 1 1)

'IllegalStateException x is not bound in environment'. Also, this happens if 'from-string' is directly put inside of a function

(defn create-function [param1 param2 expression]
    (from-string [param1 param2] expression))
(def c (create-function "x" "y" "x + y"))
(c 1 1)

'IllegalStateException x is not bound in environment'.

Could someone explain why this happens and how it could be fixed?

Logical and bitwise operators

I know it's no longer maintained, but I'm curious as to how the logical, bitwise and comparator operators are supposed to work. I've tried every combination I can think of:

((from-string "16 = 16"))
=> true
((from-string "16 > 16"))
Execution error (ParseException) at jasentaa.position/parse-exception-interop (position.cljc:45).
Failed to parse text at line: 1, col: 4
16 > 16
   ^

((from-string "16 || 16"))
Execution error (ParseException) at jasentaa.position/parse-exception-interop (position.cljc:45).
Failed to parse text at line: 1, col: 4
16 || 16

((from-string "16 or 16"))
Execution error (ParseException) at jasentaa.position/parse-exception-interop (position.cljc:45).
Failed to parse text at line: 1, col: 4
16 or 16
   ^

etc.

It doesn't work with ClojureScript

Tried to use in a pure clojureScript project. Doesn't work. Also, tried to use the source code, there are some functions not available in clojureScript.

Cannot install

I am sorry, I am a complete newbie to Clojure, and I am really looking forward to use this library to help me out with my arithmetics. I just don't seem to be able to install it. How does that work?

I have a Leiningen project. I added infix as a dependency

:dependencies [[org.clojure/clojure "1.8.0"] [rm-hull/infix "0.3.3"]]

I have a recent version of Leiningen, that the Readme says matters.

$ lein --version Leiningen 2.8.1 on Java 9.0.4 Java HotSpot(TM) 64-Bit Server VM

But then...

$ lein repl
nREPL server started on port 45235 on host 127.0.0.1 - nrepl://127.0.0.1:45235
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
Java HotSpot(TM) 64-Bit Server VM 9.0.4+11
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

jayray.core=> (refer 'infix.macros :only '[infix from-string base-env])

Exception No namespace: infix.macros  clojure.core/refer (core.clj:4104)
jayray.core=> Bye for now!

I must be missing a completely stupid, basic and obvious step, and I apologize in advance. But what is it that I am missing?

Function name conflict with clojure.core

useing this library in a project emits
WARNING: boolean already refers to: #'clojure.core/boolean in namespace: infix.grammar, being replaced by: #'infix.grammar/boolean.

Steps to reproduce with Clojure 1.10.3:

  • clj -Sdeps "{:deps {rm-hull/infix {:mvn/version \"0.4.0\"}}}"
  • (use 'infix.macros)

Unable to load infix 0.3.2

Hello!

Using a minimal Leiningen project depending on rm-hull/infix "0.3.2", I start a lein repl and

user=> (require '[infix.core :as i])
;; ... I get the error:
CompilerException java.lang.RuntimeException: Unable to resolve var: v in this context, compiling:(infix/core.clj:145:35) 

Should this happen? Leftovers from a REPL session, perhaps? Here's the relevant lines from my local jar included below.

Regards,
Teodor

(defn rewrite
  "Recursively rewrites the infix-expr as a prefix expression, according to
   the operator precedence rules"
  [infix-expr]
  (cond
    (not (seq? infix-expr))
    (resolve-alias infix-expr)

    (and (seq? (first infix-expr)) (= (count infix-expr) 1))
    (rewrite (first infix-expr))

    (empty? (rest infix-expr))
    (first infix-expr)

    :else
    (let [infix-expr (map resolve-alias infix-expr)]
      (loop [ops operator-precedence]
        (if-let [op (first ops)]
          (let [idx (.lastIndexOf ^java.util.List infix-expr op)]
            (if (pos? idx)
              (let [[expr1 [op & expr2]] (split-at idx infix-expr)]
                (list op (rewrite expr1) (rewrite expr2)))
              (recur (next ops))))

          (if (empty-arglist? infix-expr)
            (list (rewrite (first infix-expr)))
            (list (rewrite (first infix-expr)) (rewrite (next infix-expr)))))))))

(def base-env
  (merge (->>
    @operator-alias
    (map (fn [[k v]] [(keyword k) (var v)])) ;; This is line 145
    (into {}))

   ; Basic ops
   {:== ==
    := =
    :!= not=
    :+ +
    :- -
    :* *
    :/ /
    :% mod}
         )
  )

(println base-env)

(var )

(rewrite '(1 + 3))

(from-string [t] "'...") should enforce operator precedence

For example t>>5|t>>8 should evaluate as (t >> 5) | (t >> 8), but instead it is evaluating to t>>(5 | t >> 8). Demonstrating failing test:

(deftest check-equivalence
  (let [f (from-string [t] "t>>5 | t>>8")]
    (dotimes [t 1000]
      (is (= (f t) (infix (t >> 5 | t >> 8)))))))

Dot multiplication fails to parse

Trying to add new functionality and discovered this doesn't seem to work out of the box.

((infix.macros/from-string "10 * 5"))
=> 50
((infix.macros/from-string "10 . 5"))
Execution error (ParseException) at jasentaa.position/parse-exception-interop (position.cljc:45).
Failed to parse text at line: 1, col: 4
10 . 5
   ^

Support Clojurescript?

I tried to use the from-string macro, but it doesn't work in clojurescript.
The infix macro itself is a little shaky; it will throw an error when using functions from infix.math.trig.

Looking at the code, I see a few places that could be solved by using reader conditionals to dispatch to different functions when in clj or cljs.

However there's a dependency which would need to be ported to clojurescript as well : https://github.com/rm-hull/jasentaa

Is this something that is planned?

Way to discover needed aliases/bindings?

I'm trying to give my users a way to script formulae, a la Excel. Let's say one puts in the formula for Body Mass Index (BMI) which is:

(wt / (ht**2)) * 703

Is there a way I can find that the symbols wt and ht are needed? Basically, I'm going to be coming in with a map of values and I want to be able to say "Hey, bub, your map has wt but not ht.

(I edited this to remove an extraneous issue).

Regression with infix macro

Between 0.2.7 and 0.2.8, the infix macro behaviour has regressed, for example

(macroexpand-1 '(infix sin(x ** 2 + y ** 2) - sin(x ÷ y ** 2))) 

now (erroneously) expands to:

(- (Math/sin (+ (Math/pow x 2) (Math/pow y 2))) (Math/sin (Math/pow (x (infix.math.core/divide y)) 2)))

It should be as per 0.2.7-SNAPSHOT:

(- (Math/sin (+ (Math/pow x 2) (Math/pow y 2))) (Math/sin (infix.math.core/divide x (Math/pow y 2))))

incorrect evaluation of powers

2^2^2^2 will give a result that is like (((2 ^ 2) ^ 2) ^ 2) which is 16^2

i actually have my own implementation of what you wrote, that relies on clojure.walk

if you are ok with that, i can issue a PR with some more tests

Precedence error for **

From the Wiki (pasting in the 2s as superscript didn't work, so I prefaced the 2 with **, as it would be in infix):

When exponents were introduced in the 16th and 17th centuries, they were given precedence over both addition and multiplication, and could be placed only as a superscript to the right of their base.[1] Thus 3 + 5**2 = 28 and 3 × 5**2 = 75.

Using infix from-string:

((from-string "3 + 5**2"))
=> 28.0
((from-string "3 * 5**2"))
=> 225.0
((from-string "10 / 10**2"))
=> 1.0

Looks like * and / are given precedence over **.

Dot-namespacing?

Hello,

I've got code I've been running for a while where the variables are namespaced.

{:x.y.z 4}
And formulae that are composed like:

((from-string [] (merge all-fns {:x.y.z 4}) "1+2+x.y.z"))

And it does not work now. I get a

Execution error (ParseException) at jasentaa.position/parse-exception-interop (position.cljc:45).
Failed to parse text at line: 1, col: 6
1+2+x.y.z

I was using 0.40 when I noticed this and just switched to 0.41. Then I tried flipping back to 0.33, and it all got the same error.

So did something change or did I just hallucinate that the dot-notation for variables are usable?

Unify alias resolving between macros

from-string uses the base-env to resolve aliases, whereas the infix macro has its own LUT for resolving aliases - these both do approximately the same thing, so there should only be one implementation for both.

Basic operator precedence

Hi, thanks for creating a great library! Very useful for human-readable math-expressions!
Not sure if this is an issue, but it confused me. Using several basic operators after each-other like this:
(infix 3 - 2 - 1)
You would expect 3 - 2 - 1 to evaluate to 0, right? But default precedence in the library makes it evaluate to 2 - since it is evaluated as 3 - (2 - 1) = 3 - 1 = 2
Fixing this would make the library more useful for me. As some of the reason for using this is to show the expression more or less as it is given in a formula description - avoiding the std. Clojure grouping of expressions.

You think this could be done? I can try to look at it myself in a pull-request, but I thought you could probably solve it or answer the question much faster :)

Edit: The problem is easily testable:
(is (= 0 (infix 3 - 2 - 1)))

FAIL in (basic-arithmetic) (macros_tests.clj:35)
expected: (= 0 (infix 3 - 2 - 1))
actual: (not (= 0 2))

Adding functionality

I wanted to add some features not built-in to infix, so I did the following:

  1. Defined the routines I wanted to use:
(defn max [a, b] (Math/max a, b))
(defn min [a, b] (Math/min a, b))
  1. Created a map with those routines:
(def obz-fns {:max max
              :min min})
  1. Merged them into the existing routines:
(def all-fns (merge base-env obz-fns))
  1. I then use my all-fns when calling from-string:
((from-string [] (merge all-fns local-vars)  "min(a,b)")))

This seems to be pretty trauma free. Just wondering if I should beware of any particular dangers.

Doesn't fully expand all aliases properly

(defn checkerboard [x y]
  (infix exp(sin x + cos y) - sin(exp(x + y))))

This doesn't alias the 2nd exp:

(- (Math/exp (+ (Math/sin x) (Math/cos y))) (Math/sin (exp (+ x y))))  

Drop selected aliases?

In my code I had a value named e. In the expression this was translated to Math/E:

user=> (macroexpand-1 '(infix e * 2))
(* Math/E 2)

Is there any way I could exclude e from being aliased? I could of course change my code, but the original expression description uses the name e so I would rather keep it if I can..

What I wish for is a way I could make it keep e as the value:

user=> (macroexpand-1 '(infix e * 2))
(* e 2)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.