Skip to content

Collection of some useful functions and macros for hylang

License

Notifications You must be signed in to change notification settings

guanyilun/hylab

Repository files navigation

hylab

This repository collects some of the useful functions and macros that I wrote or borrowed for hylang. I am more accustomed to the common lisp syntax, so I borrowed from the nice work of riktor on hycl to make hylang more friendly to people coming from common lisp.

Prerequisite

hy==0.17.0

Installation

To install

pip install git+https://github.com/guanyilun/hylab/

Examples

To start with, import the core library

(import [hylab.core [*]])
(require [hylab.core [*]])
(setf x 10)
(defun plus-one (x)
    (inc x)
)
(print (plus-one x))
11

One can also use defparameter which is the same as setv or setf, however I find it more readable to use this exclusively for global variables.

(defparameter *global-var* 10)
(print *global-var*)
10

numpy and plt are also loaded automatically

(print (np.arange 0 10))
[0 1 2 3 4 5 6 7 8 9]

numpy array indexing can be done by

(setf x (np.random.randn 100 100 100))
(nget x 0 1 :10)
array([ 0.87120279, -1.66700778,  0.26169724, -0.60144387,  0.55433208,
       -0.43233873, -1.11727772,  0.41093365,  0.36703862, -1.88770578])

With Ellipsis

(. (nget x ... 0:10) shape)
(100, 100, 10)

Add new columns

(. (nget x ... None) shape)
(100, 100, 100, 1)

Some more examples of nget

(setf a (.reshape (np.arange 36) (, 6 6)))
(nget a (, 0 1 2 3 4) (, 1 2 3 4 5))
array([ 1,  8, 15, 22, 29])
(nget a 3: (, 0 2 5))
array([[18, 20, 23],
       [24, 26, 29],
       [30, 32, 35]])
(setf mask (np.array (, 1 0 1 0 0 1) :dtype bool))
(nget a mask  2)
array([ True, False,  True, False, False,  True])
array([ 2, 14, 32])
(nget a ::2 3)
(nget a ::2 3 None)
(nget a ... 0)
array([ 3, 15, 27])
array([[ 3],
       [15],
       [27]])
array([ 0,  6, 12, 18, 24, 30])

Quick python->hy equation translation,

(let ((x (np.linspace 0 10 10)))
    (+ (** (np.sin x) 2) (** (np.cos x) 2)))
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

It can be written as

(let ((x (np.linspace 0 10 10)))
    ($ "np.sin(x)**2+np.cos(x)**2"))
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

This is different to the py-eval function as this is a macro that gets converted into the previous (lisp) notation at compile time so there is no performance issue.

The same symbol represents curry when used as tag macro

(tuple (map #$(+ 10) '(1 2 3 4 5)))
(11, 12, 13, 14, 15)

This is equivalent to using the tag macro for tuple

#t(map #$(+ 10) '(1 2 3 4 5))
(11, 12, 13, 14, 15)

Similarly

#t(map #$(+ 10) '(1 2 3 4 5))
#l(map #$(+ 10) '(1 2 3 4 5))
#a(map #$(+ 10) '(1 2 3 4 5))
#h(map #$(+ 10) '(1 2 3 4 5))
(11, 12, 13, 14, 15)
[11, 12, 13, 14, 15]
array([11, 12, 13, 14, 15])
HyExpression([11, 12, 13, 14, 15])

Some convenient conversions (to HySymbol) for macros

#sym"my-var1"
#sym 'my-var2
#."my-var3"
#. 'my-var4
HySymbol('my-var1')
HySymbol('my-var2')
HySymbol('.my-var3')
HySymbol('.my-var4')

Lambda expression, the following three expressions are equivalent, the first is the built-in notation from hylang, the second is a common lisp like alias and the last is a unicode alias.

#l(map (fn [x] (1+ x)) [1 2 3])
#l(map (lambda (x) (1+ x)) [1 2 3])
#l(map (λ (x) (1+ x)) [1 2 3])
[2, 3, 4]
[2, 3, 4]
[2, 3, 4]

Get elements of lists or tuples

(let ((x '((1 2) (3 4) (5 6))))
    (lget x 0 :))
array([1, 2])
(let ((x '((1 2) (3 4) (5 6))))
    (lget x None ...))
array([[[1, 2],
        [3, 4],
        [5, 6]]])

Threading

(let ((x (np.arange 1 10)))
    (as-> x it
          (/ 100 it)
          (+ it 3)
          (np.sin it)
          (** it 2 )))
array([0.38811483, 0.15675672, 0.95855331, 0.07338995, 0.71608897,
       0.53169132, 0.99995163, 0.04262882, 0.99932125])

This can also be written as (borrowed from riktor)

(let ((x (np.arange 1 10)))
    (=> x
        (/ 100 _)
        (+ 3)
        (np.sin)
        (** 2)))
array([0.38811483, 0.15675672, 0.95855331, 0.07338995, 0.71608897,
       0.53169132, 0.99995163, 0.04262882, 0.99932125])

Quick plotting tools

(setf x (np.linspace 1 10 100))
(setf y (np.sin x))
(plot
    x y "r-"
    y x "g-"
    :xlabel "x"
    :ylabel "y"
    :title "Test Plot"
    :legend ["Line1" "Line2"]
    :savefig "plots/test.png"
    :show)

For printing

(setf
  age 99
  height 2.2)

(print (+ "I am " (str age) " years old, and I am " (str height) " m tall"))
I am 99 years old, and I am 2.2 m tall

A simpler way of printing is

(print (.format "I am {} years old, and I am {} m tall" age height))
I am 99 years old, and I am 2.2 m tall

An even simpler way of printing from hylab

(print #f"I am {age} years old, and I am {height} m tall")
I am 99 years old, and I am 2.2 m tall

Clearly this is inspired by f-string in python. It allows arbitrary s-expression too

(print #f"I am {(inc age)} years old, and I am {(round (* np.pi height) 2)} m tall")
I am 100 years old, and I am 6.91 m tall

It should work with format options too (though there may be cases that I haven’t considered, PR is welcomed).

(print #f"Pi = {np.pi:8.2f}")
Pi =     3.14
(setf n "cat")
(print #f"Animal: {n:5}")
(print #f"Animal: {n:>5}")
(print #f"Animal: {n:^5}")
(print #f"Animal: {n:*^5}")
Animal: cat
Animal:   cat
Animal:  cat
Animal: *cat*

I also included codes from hyiter written by riktor, which I find amazing. Here are some examples that I borrowed directly from hyiter to showcase this function

NEEDS FIXING for hy==0.17.0

;; loop on iterable
(itr
  (for i in '(1 2 3))
  (print i))
1
2
3
(print (itr
         (for i in (range 10))
         (when (= (% i 2) 0)
           (collect (* 10 i)))))
[0, 20, 40, 60, 80]
(itr
  (initially
    (print "LOOP Start!"))
  (for i in '(1 2 3))
  (print i))
LOOP Start!
1
2
3
(itr
  (for i in '(1 2 3))
  (print i)
  (finally
    (print "LOOP Finish!")))
1
2
3
LOOP Finish!
(print (itr
         (for i in (range 10))
         (maximize i)))
9
(print (itr
         (for i in (range 10))
         (count (= (% i 2) 0))))
5

This is only a subset of what’s possible, for more details please refer to this link.

More to come …

Credits

  • Credits to riktor from whom I borrowed lots of codes.
  • I also borrowed some codes from Eric Kaschalk.
  • The template is based on cookiecutter-pypackage.

License

MIT

About

Collection of some useful functions and macros for hylang

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published