/
2012-02-08-Lisp-Let-in-GNU-Octave.html
89 lines (89 loc) · 2.94 KB
/
2012-02-08-Lisp-Let-in-GNU-Octave.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
---
title: Lisp Let in GNU Octave
layout: post
tags: [octave, trick, lisp, media, math]
---
<!-- This post is HTML because Maruku can't yet handle HTML5. -->
<p>
In BrianScheme, the standard Lisp binding form `let` isn't a special
form. That is, it's not a hard-coded language feature, or *special
form*. It's built on top of `lambda`. In any lexically-scoped Lisp,
the expression,
</p>
{% highlight cl %}
(let ((x 10)
(y 20))
(* 10 20))
{% endhighlight %}
<p>
Can also be written as,
</p>
{% highlight cl %}
((lambda (x y)
(* x y))
10 20)
{% endhighlight %}
<p>
BrianScheme's `let` is just a macro that transforms into a lambda
expression. This is also what made it so important to implement
<a href="http://en.wikipedia.org/wiki/Lambda_lifting">lambda
lifting</a>, to optimize these otherwise-expensive forms.
</p>
<p>
It's possible to achieve a similar effect in GNU Octave (but not
Matlab, due to <a href="/blog/2008/08/29/">its flawed parser
design</a>). The language permits simple lambda expressions, much like
Python.
</p>
{% highlight octave %}
> f = @(x) x + 10;
> f(4)
ans = 14
{% endhighlight %}
<p>
It can be used to create a scope in a language that's mostly devoid of
scope. For example, I can avoid assigning a value to a temporary
variable just because I need to use it in two places. This one-liner
generates a random 3D unit vector.
</p>
{% highlight octave %}
(@(v) v / norm(v))(randn(1, 3))
{% endhighlight %}
<p>
The anonymous function is called inside the same expression where it's
created. In practice, doing this is stupid. It's confusing and there's
really nothing to gain by being clever, doing it in one line instead
of two. Most importantly, there's no macro system that can turn this
into a new language feature. *However*, I enjoyed using this technique
to create a one-liner that generates `n` random unit vectors.
</p>
{% highlight octave %}
n = 1000;
p = (@(v) v ./ repmat(sqrt(sum(abs(v) .^ 2, 2)), 1, 3))(randn(n, 3));
{% endhighlight %}
<p>
Why was I doing this? I was using the Monte Carlo method to
double-check my solution to
<a href="http://godplaysdice.blogspot.com/2011/12/geometric-probability-problem.html">this
math problem</a>:
</p>
<blockquote>
What is the average straight line distance between two points on a
sphere of radius 1?
</blockquote>
<p>
I was also demonstrating to <a href="http://devrand.org/">Gavin</a>
that simply choosing two *angles* is insufficient, because the points
the angles select are not evenly distributed over the surface of the
sphere. I generated this video, where the poles are clearly visible
due to the uneven selection by two angles.
</p>
<p class="center">
<video src="https://s3.amazonaws.com/nullprogram/sphere/sphere-dark.webm"
controls height="340" width="340"/>
</p>
<p>
This took hours to render with gnuplot! Here are stylized versions:
<a href="https://s3.amazonaws.com/nullprogram/sphere/dark.html">Dark</a> and
<a href="https://s3.amazonaws.com/nullprogram/sphere/light.html">Light</a>.
</p>