• Stars
    star
    101
  • Rank 338,166 (Top 7 %)
  • Language
    Clojure
  • License
    MIT License
  • Created over 9 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Clojure library for expressing LISP expressions as infix rather than prefix notation

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

(infix √ 121)
; => 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.

More Repositories

1

luma.oled

Python module to drive a SSD1306 / SSD1309 / SSD1322 / SSD1325 / SSD1327 / SSD1331 / SSD1351 / SH1106 OLED
Python
809
star
2

pifm

Copy of http://www.icrobotics.co.uk/wiki/index.php/Turning_the_Raspberry_Pi_Into_an_FM_Transmitter
C++
524
star
3

luma.led_matrix

Python module to drive LED Matrices & 7-segment displays (MAX7219) and RGB NeoPixels (WS2812 / APA102)
Python
519
star
4

luma.examples

Companion repo for running examples against the luma.oled, luma.lcd, luma.led_matrix and luma.emulator display drivers.
Python
348
star
5

nvd-clojure

National Vulnerability Database dependency checker for Clojure projects
Clojure
268
star
6

OPi.GPIO

RPi.GPIO drop-in replacement library for Orange Pi Zero and other SBCs
Python
185
star
7

luma.lcd

Python module to drive PCD8544, HT1621, ST7735, ST7567 and UC1701X-based LCDs
Python
157
star
8

luma.core

A component library providing a Pillow-compatible drawing canvas, and other functionality to support drawing primitives and text-rendering capabilities for small displays on the Raspberry Pi and other single board computers.
Python
148
star
9

programming-enchiladas

A ClojureScript-based HTML5 Canvas and SVG Graphics Playground, much like http://bl.ocks.org/ but specifically for showcasing small ClojuresScript code demos: The underlying agenda is to show how small simple functional programs can generate complex behaviour.
JavaScript
138
star
10

sql_graphviz

Generates graphviz commands to graphically display tables and show foreign key links.
Python
138
star
11

bme280

Raspberry PI schematics & python module to drive a Bosch BME280 digital sensor module
Python
96
star
12

spidev-test

C
88
star
13

big-bang

ClojureScript event loop abstraction, loosely based on Racket's big-bang and implemented on top of core.async
Clojure
66
star
14

barebones-toolchain

Barebones [ i686-elf / ARMv7-eabi / MIPS ] cross-compiler & toolchain
C
64
star
15

jasentaa

A parser combinator library for Clojure and ClojureScript
Clojure
60
star
16

wireframes

A lightweight 3D graphics rendering engine in Clojure & ClojureScript.
Clojure
60
star
17

byok

A bare-metal x86 Forth interpreter & compiler
C
54
star
18

skull-canyon

Notes on setting up Ubuntu 18.04 (Bionic Beaver) on Intel NUC6i7KYK
46
star
19

luma.emulator

Provides a series of pseudo-display devices which allow the luma.core components to be used without running a physical device.
Python
43
star
20

inkspot

A small Clojure/ClojureScript library for creating colour swatches
Clojure
39
star
21

lindenmayer-systems

An L-system or Lindenmayer system is a parallel rewriting system, namely a variant of a formal grammar, most famously used to model the growth processes of plant development, but also able to model the morphology of a variety of organisms. Clojure / Heroku.
Clojure
38
star
22

clj-wordnet

An interface to the WordNet database using idiomatic Clojure
Clojure
35
star
23

markov-chains

A library (and application examples) of stochastic discrete-time Markov Chains (DTMC) in Clojure
Clojure
31
star
24

st7735fb

Schematics and build info for assembling a custom Raspberry Pi kernel with ST7735 TFT-LCD framebuffer drivers
Python
28
star
25

k8055

Velleman k8055 linux driver and GUI sources for the Raspberry Pi
C
27
star
26

wam

Gradual WAM implementation using Hassan AΓ―t-Kaci's tutorial reconstruction
Clojure
25
star
27

hmc5883l

Python wrapper class for HMC5883L magnetometer (using smbus I2c)
Python
22
star
28

clustering

Implementation of K-Means, Self-Organising Maps, QT and Hierarchical clustering algorithms, in Clojure.
Clojure
21
star
29

weatherstation

TypeScript
16
star
30

project-euler

Clojure solutions to Project Euler problems
Clojure
14
star
31

turtle

A logo-style turtle graphics library for Clojure & ClojureScript (renders to SVG, bitmaps & HTML5 Canvas)
Clojure
11
star
32

wiringPi

A fork of Gordon Henderson's git://git.drogon.net/wiringPi but with python bindings
C
10
star
33

corewar

A clojure / clojurescript / core.async implementation of A. K. Dewdney's Core War
Clojure
9
star
34

linux-journal-archive

Copy of the Linux Journal archives (issues 1–293)
HTML
8
star
35

local-cast

Stream local video/audio content to a Chromecast on your network
JavaScript
7
star
36

maze

Maze generator and solver, in ClojureScript with a HTML5 canvas
Clojure
7
star
37

turmites

A turmite is a Turing machine which has an orientation as well as a current state and a "tape" that consists of an infinite two-dimensional grid of cells. ClojureScript / HTML5 Canvas / Heroku.
Clojure
6
star
38

yalix

Seven LISPs in seven languages
Python
5
star
39

task-scheduler

Fork/Join task scheduling in Clojure
Clojure
5
star
40

luma.docs

Python
5
star
41

ars-magna

A multi-word anagram solver, based on the article "Anagrams and Pangrams" from The Armchair Universe
Clojure
5
star
42

byok3

A forth interpreter and compiler implemented in scala using typelevel/cats
Scala
4
star
43

ambages

A small prolog interpreter, implemented in Clojure.
Clojure
4
star
44

table

Display ascii tables for almost any data structure with ease.
Clojure
4
star
45

apds9960

Python
4
star
46

mcp23017

Schematics and build info for assembling a Raspberry Pi breakout board with multiple MCP23017 input/output port expanders
Python
3
star
47

jwi

(Mavenized version of) JWI 2.3.3
Java
3
star
48

zaup

TOTP authentication using ZeroSeg
Python
3
star
49

8-bit-trip

Algorithmic music streaming
TypeScript
3
star
50

helpmate

A Clojure library for emitting SGML (HTML,SVG,XML,MathML) fragments
Clojure
3
star
51

implicit-equations

A graphing library for implicit equations, in Clojure
Clojure
3
star
52

colorforth

cvs->git conversion of http://colorforth.cvs.sourceforge.net/viewvc/colorforth/colorforth/
Assembly
3
star
53

loose-labels

An implementation of "Nice numbers for graph labels" from Graphics Gems, vol. 1
Clojure
2
star
54

TR4-monitor

Small utility script to display TR4 system information on a 2.42" SSD1309 OLED
Python
2
star
55

treebank-viz

SVG graph generation of treebank language parsing
Clojure
2
star
56

zaup2

A TOTP authenticator for the web
TypeScript
2
star
57

newell-teapot

Shadow of ftp://ftp.funet.fi/pub/sci/graphics/packages/objects/teaset.tar.Z
C
2
star
58

image-preview

CLI takes in an image file, and using ANSI escape sequences, outputs a low-fidelity preview of the image in the terminal.
Rust
2
star
59

pysensors3

Python3 bindings to libsensors (via ctypes)
Python
1
star
60

rg-matrix

Python library to drive a 32x16 red/green LED matrix
1
star
61

vim-locate

A vim plugin that integrates the unix locate database
Vim Script
1
star
62

henry

HTML
1
star
63

glsl-transpiler

A ClojureScript to GLSL cross compiler ... probably
1
star
64

webrot

Clojure, Noir and Clojurescript toy implementations for mandlebrot, julia & sierpinski fractals
Clojure
1
star
65

sound-flour

An experiment in collaborative broadcast streaming computer-generated music, in Clojure
Clojure
1
star
66

polyhedra

A Clojure/Clojurescript library for reading netlib polyhedra data files
Clojure
1
star
67

boyer-moore-search

Boyer-Moore string search library in Clojure
Clojure
1
star
68

ods-search-appliance

A JSON full-text search endpoint API onto NHS ODS data
Clojure
1
star
69

kebab

An ad-scrubbing web proxy, focusing on subverting commercial tracking and other general panoptic shenanigans. [Scala / Play 2.1]
CSS
1
star
70

proliant-microserver

1
star
71

led-blaster

C
1
star
72

nostalgia

A trip back though some personal 1980's & 90's computing memorabilia
1
star
73

cellular-automata

Migrating from CA code in webrot into separate stand-alone project
Clojure
1
star
74

cljs-dataview

A ClojureScript library for asynchronously fetching & dicing remote binary objects
Clojure
1
star
75

dotfiles

Essentials pour le vim exigeants basΓ©s programmeur informatique agiotage
Vim Script
1
star
76

speedtest-logger

Broadband speedtest logger
JavaScript
1
star